import ipc from "node-ipc"; import { Socket } from "net"; import Service from "./Service"; import Application from "../Application"; import RawIPC = require("node-ipc"); interface IResponse { response?: any, error?: string | Error } export default class SeekerIpc extends Service { /** * Indicate if there is an active connection to the IPC */ private __isConnected: boolean; /** * 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(app: Application) { super("Seeker IPC", app); this.ipc = new RawIPC.IPC(); this.ipc.config.id = "request"; this.ipc.config.retry = 1500; this.ipc.config.silent = true; this.__isConnected = false; } /** * Boot the seeker client IPC service */ public boot() { return new Promise((resolve, reject) => { this.ipc.connectTo("seeker", process.env["SEEKER_IPC_SOCKET"], () => { this.socket = this.ipc.of["seeker"]; this.installSocketEventHandlers(this.socket); this.installSocketMessageHandlers(this.socket); resolve(); }); }); } /** * Shutdown the seeker IPC service */ public async shutdown() { this.ipc.disconnect("seeker"); } /** * 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()); } protected installSocketMessageHandlers(socket: Socket) { } // Socket Event Handlers ----------------------------------------------------------------------- protected onConnect() { this.log("Seeker IPC: Connection established"); this.__isConnected = true; } protected onError(error: string | Error) { this.log("Seeker IPC: Error occurred:", error); } protected onDisconnect() { this.log("Seeker IPC: Disconnected"); this.__isConnected = false; } protected onDestroy() { this.log("Seeker IPC: Destroyed"); } // Methods ------------------------------------------------------------------------------------- /** * Perform a general request to the Seeker */ protected async request(method: string, message?: any) { return new Promise((resolve, reject) => { if (!this.isConnected) { throw new Error("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("Seeker IPC request timeout") }, 1000); this.socket.once(method, respond); this.socket.emit(method, message); }); } /** * Notify Seeker that a movie was added */ public notifyMovieRequested(ticketId: number) { this.request("search_movie", ticketId).catch((e) => { this.log("No response from seeker notifying added movie"); }); } // Accessors ----------------------------------------------------------------------------------- get isConnected() { return this.__isConnected; } }