|
|
@ -1,156 +0,0 @@ |
|
|
|
import { Socket } from "net"; |
|
|
|
import { InternalService } from "@autoplex/microservice"; |
|
|
|
import RawIPC = require("node-ipc"); |
|
|
|
import Application from "@server/Application"; |
|
|
|
|
|
|
|
export interface IIpcResponse { |
|
|
|
response?: any, |
|
|
|
error?: string | Error |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* IPC connection error type |
|
|
|
*/ |
|
|
|
export class IpcConnectionError extends Error { |
|
|
|
constructor(...args: any[]) { |
|
|
|
super(...args); |
|
|
|
Object.setPrototypeOf(this, IpcConnectionError.prototype); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
export default class IpcClient extends InternalService<Application> |
|
|
|
{ |
|
|
|
/** |
|
|
|
* Indicate if there is an active connection to the IPC |
|
|
|
*/ |
|
|
|
private __isConnected: boolean; |
|
|
|
|
|
|
|
/** |
|
|
|
* The IPC ID to connect to |
|
|
|
*/ |
|
|
|
private __targetIpc: string; |
|
|
|
|
|
|
|
/** |
|
|
|
* The IPC client name |
|
|
|
*/ |
|
|
|
protected readonly IPC_NAME: string; |
|
|
|
|
|
|
|
/** |
|
|
|
* HOLY @#$@% WHOEVER MADE THE TYPES FOR node-ipc SHOULDB BE HANGED |
|
|
|
*/ |
|
|
|
protected ipc; |
|
|
|
|
|
|
|
/** |
|
|
|
* The active IPC socket |
|
|
|
*/ |
|
|
|
protected socket!: Socket; |
|
|
|
|
|
|
|
/** |
|
|
|
* Create a new IPC client for the Seeker |
|
|
|
*/ |
|
|
|
constructor(name: string, app: Application, ipcId: string, targetIpc: string) { |
|
|
|
super(app); |
|
|
|
this.IPC_NAME = name; |
|
|
|
this.ipc = new RawIPC.IPC(); |
|
|
|
this.ipc.config.id = ipcId; |
|
|
|
this.ipc.config.retry = 1500; |
|
|
|
this.ipc.config.silent = true; |
|
|
|
this.__targetIpc = targetIpc; |
|
|
|
this.__isConnected = false; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* The name of the service |
|
|
|
*/ |
|
|
|
public get name() { return this.IPC_NAME } |
|
|
|
|
|
|
|
/** |
|
|
|
* Boot the seeker client IPC service |
|
|
|
*/ |
|
|
|
public boot() { |
|
|
|
return new Promise<void>((resolve, reject) => { |
|
|
|
this.ipc.connectTo(this.__targetIpc, process.env["SEEKER_IPC_SOCKET"], () => { |
|
|
|
this.socket = this.ipc.of[this.__targetIpc]; |
|
|
|
this.installSocketEventHandlers(this.socket); |
|
|
|
this.installSocketMessageHandlers(this.socket); |
|
|
|
resolve(); |
|
|
|
}); |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Shutdown the seeker IPC service |
|
|
|
*/ |
|
|
|
public async shutdown() { |
|
|
|
this.ipc.disconnect(this.__targetIpc); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Install the event handlers for the IPC socket |
|
|
|
*/ |
|
|
|
protected installSocketEventHandlers(socket: Socket) { |
|
|
|
socket.on("connect", () => this.onConnect()); |
|
|
|
socket.on("error", (error: any) => this.onError(error)); |
|
|
|
socket.on("disconnect", () => this.onDisconnect()); |
|
|
|
socket.on("destroy", () => this.onDestroy()); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Install the event handlers for receiving on the IPC socket |
|
|
|
*/ |
|
|
|
protected installSocketMessageHandlers(socket: Socket) {} |
|
|
|
|
|
|
|
// Socket Event Handlers -----------------------------------------------------------------------
|
|
|
|
|
|
|
|
protected onConnect() { |
|
|
|
this.log("IPC: Connection established"); |
|
|
|
this.__isConnected = true; |
|
|
|
} |
|
|
|
|
|
|
|
protected onError(error: string | Error) { |
|
|
|
if (this.__isConnected) { |
|
|
|
this.log("IPC: Error occurred:", error); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
protected onDisconnect() { |
|
|
|
if (this.__isConnected) { |
|
|
|
this.log("IPC: Disconnected"); |
|
|
|
} |
|
|
|
this.__isConnected = false; |
|
|
|
} |
|
|
|
|
|
|
|
protected onDestroy() { |
|
|
|
this.log("IPC: Destroyed"); |
|
|
|
} |
|
|
|
|
|
|
|
// Methods -------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
/** |
|
|
|
* Perform a general request |
|
|
|
*/ |
|
|
|
protected async request(method: string, message?: any) { |
|
|
|
return new Promise<IIpcResponse>((resolve, reject) => { |
|
|
|
if (!this.isConnected) { |
|
|
|
reject(new IpcConnectionError("Not connected to Seeker")); |
|
|
|
} |
|
|
|
let respond = (response: any) => { |
|
|
|
clearTimeout(timeout); |
|
|
|
resolve(response); |
|
|
|
} |
|
|
|
// Include timeout mechanism in the off chance something breaks
|
|
|
|
let timeout = setTimeout(() => { |
|
|
|
this.socket.off(method, respond); |
|
|
|
reject(new IpcConnectionError("IPC request timeout")); |
|
|
|
}, 1000); |
|
|
|
this.socket.once(method, respond); |
|
|
|
this.socket.emit(method, message); |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
// Accessors -----------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
get isConnected() { |
|
|
|
return this.__isConnected; |
|
|
|
} |
|
|
|
} |