Event Service (IPC)
The Event Service in Trufos facilitates Inter-Process Communication (IPC) between the main process and the renderer process. It’s implemented as two distinct but related services: MainEventService for the backend and RendererEventService for the frontend.
MainEventService
- Location:
src/main/event/main-event-service.ts - Purpose: To expose main process functionalities to the renderer process securely and handle requests originating from the UI.
- Mechanism:
- It implements the
IEventServiceinterface (defined insrc/shim/event-service.ts). - During its construction, it iterates over its own methods and dynamically registers IPC handlers for each using
ipcMain.handle(channelName, handler). ThechannelNameis typically the method name itself. - Each handler is wrapped with
wrapWithErrorHandler, which catches errors from the underlying service calls, logs them, and returns them as standardErrorobjects over IPC.
- It implements the
- Responsibilities:
- Delegates calls to other main process services (e.g.,
PersistenceService,HttpService,EnvironmentService). - Acts as the single point of entry for most renderer-to-main communication.
- Handles specialized IPC events like those for data streaming (
stream-events.ts) and log forwarding.
- Delegates calls to other main process services (e.g.,
RendererEventService
- Location:
src/renderer/services/event/renderer-event-service.ts - Purpose: To provide a clean, Promise-based API for renderer-side code to interact with the main process functionalities exposed by
MainEventService. - Mechanism:
- It also conceptually implements the
IEventServiceinterface. - For each method in
IEventService, it uses acreateEventMethodhelper. This helper function:- Calls
window.electron.ipcRenderer.invoke(channelName, ...args), wherechannelNamematches the method name. - Awaits the Promise returned by
invoke. - If the result from the main process is an
Errorobject, it throws a newMainProcessError(fromsrc/renderer/error/MainProcessError.ts) to distinguish it from renderer-side errors. - Otherwise, it returns the successful result.
- Calls
- It also provides methods for listening to (
on) and emitting (emit) general IPC events that are not part of the request/response pattern (e.g.,before-close,ready-to-closefor application shutdown).
- It also conceptually implements the
- Responsibilities:
- Abstracts away the raw
ipcRenderercalls. - Provides type safety for IPC calls based on
IEventService. - Handles error wrapping for responses from the main process.
- Abstracts away the raw
IEventService Interface
- Location:
src/shim/event-service.ts - Purpose: Defines the contract for methods that are exposed via IPC. This shared interface ensures that both
MainEventServiceandRendererEventServiceare synchronized in terms of method signatures and channel names. - Key Methods Defined:
loadCollection,listCollectionssendRequestsaveRequest,saveChanges,discardChangesdeleteObjectgetAppVersiongetActiveEnvironmentVariables,getVariable,setCollectionVariablesselectEnvironmentsaveFolderopenCollection,createCollection,closeCollectionshowOpenDialog
Overall Flow
- Renderer component/service needs to perform a main process task (e.g., save a file).
- It calls a method on
RendererEventService.instance(e.g.,RendererEventService.instance.saveRequest(requestData)). RendererEventServiceuseswindow.electron.ipcRenderer.invoke('saveRequest', requestData)to send the request to the main process.MainEventService(which has a handler registered for'saveRequest') receives the call.- The handler in
MainEventServicecalls the actual implementation (e.g.,PersistenceService.instance.saveRequest(requestData)). - The result (or an error) from
PersistenceServiceis returned by theMainEventServicehandler. RendererEventServicereceives the result. If it’s an error, it throwsMainProcessError; otherwise, it returns the data.- The original caller in the renderer process receives the data or catches the error.
This structured approach to IPC ensures maintainability, type safety, and proper error handling between the main and renderer processes. For more details on the underlying IPC mechanisms, see IPC Communication.