feat: implement telemetry system for application usage tracking
- Added telemetry utility to capture application events and metrics. - Integrated PostHog for event tracking with distinct user identification. - Implemented telemetry initialization, event capturing, and shutdown procedures. feat: add UV environment setup for Python management - Created utilities to manage Python installation and configuration. - Implemented network optimization checks for Python installation mirrors. - Added functions to set up managed Python environments with error handling. feat: enhance host API communication with token management - Introduced host API token retrieval and management for secure requests. - Updated host API fetch functions to include token in headers. - Added support for creating event sources with authentication. test: add comprehensive tests for gateway protocol and startup helpers - Implemented unit tests for gateway protocol helpers, event dispatching, and state management. - Added tests for startup recovery strategies and process policies. - Ensured coverage for connection monitoring and restart governance logic.
This commit is contained in:
64
electron/api/event-bus.ts
Normal file
64
electron/api/event-bus.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
import type { ServerResponse } from 'node:http';
|
||||
|
||||
type EventPayload = unknown;
|
||||
|
||||
type EventListener = (payload: EventPayload) => void;
|
||||
|
||||
export class HostEventBus {
|
||||
private readonly listeners = new Map<string, Set<EventListener>>();
|
||||
private readonly sseClients = new Set<ServerResponse>();
|
||||
|
||||
on(eventName: string, listener: EventListener): () => void {
|
||||
const bucket = this.listeners.get(eventName) ?? new Set<EventListener>();
|
||||
bucket.add(listener);
|
||||
this.listeners.set(eventName, bucket);
|
||||
|
||||
return () => {
|
||||
bucket.delete(listener);
|
||||
if (bucket.size === 0) {
|
||||
this.listeners.delete(eventName);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
addSseClient(res: ServerResponse): void {
|
||||
this.sseClients.add(res);
|
||||
res.on('close', () => {
|
||||
this.sseClients.delete(res);
|
||||
});
|
||||
}
|
||||
|
||||
emit(eventName: string, payload: EventPayload): void {
|
||||
const bucket = this.listeners.get(eventName);
|
||||
if (bucket) {
|
||||
for (const listener of bucket) {
|
||||
listener(payload);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.sseClients.size > 0) {
|
||||
const message = `event: ${eventName}\ndata: ${JSON.stringify(payload)}\n\n`;
|
||||
for (const client of this.sseClients) {
|
||||
try {
|
||||
client.write(message);
|
||||
} catch {
|
||||
this.sseClients.delete(client);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
closeAll(): void {
|
||||
this.listeners.clear();
|
||||
for (const client of this.sseClients) {
|
||||
try {
|
||||
client.end();
|
||||
} catch {
|
||||
// Ignore individual client close failures.
|
||||
}
|
||||
}
|
||||
this.sseClients.clear();
|
||||
}
|
||||
}
|
||||
|
||||
export const hostEventBus = new HostEventBus();
|
||||
Reference in New Issue
Block a user