feat: enhance RPC connection handling with disconnection error and event emitter improvements

This commit is contained in:
tone
2025-10-15 15:29:48 +08:00
parent 5d8c32e8e8
commit ab288c24aa
3 changed files with 25 additions and 4 deletions

View File

@@ -14,18 +14,31 @@ interface RPCConnectionEvents {
closed: void;
}
class CallResponseEmitter extends EventEmitter<{
[id: string]: RPCPacket;
}> {
emitAll(packet: RPCPacket) {
this.events.forEach(subscribers => {
subscribers.forEach(fn => fn(packet));
})
}
}
export class RPCConnection extends EventEmitter<RPCConnectionEvents> {
closed: boolean = false;
private callResponseEmitter = new EventEmitter<{
[id: string]: RPCPacket;
}>();
private callResponseEmitter = new CallResponseEmitter();
constructor(public socket: SocketConnection) {
super();
socket.on('closed', () => {
this.emit('closed');
this.callResponseEmitter.emitAll(makeCallResponsePacket({
status: 'error',
requestPacketId: 'connection error',
errorCode: RPCErrorCode.CONNECTION_DISCONNECTED,
}));
this.callResponseEmitter.removeAllListeners();
this.closed = true;
});
@@ -68,6 +81,12 @@ export class RPCConnection extends EventEmitter<RPCConnectionEvents> {
args: any[];
timeout: number;
}): Promise<any> {
if (this.closed) {
throw new RPCError({
errorCode: RPCErrorCode.CONNECTION_DISCONNECTED,
});
}
const { fnPath, args } = options;
const packet = makeCallPacket({
fnPath,

View File

@@ -9,6 +9,7 @@ export enum RPCErrorCode {
HANDSHAKE_INCOMPLETE = -400,
TIMEOUT_ERROR = -500,
CALL_PROTOCOL_ERROR = -600,
CONNECTION_DISCONNECTED = -700,
}
export const RPC_ERROR_MESSAGES: Record<RPCErrorCode | number, string> = {
@@ -22,6 +23,7 @@ export const RPC_ERROR_MESSAGES: Record<RPCErrorCode | number, string> = {
[RPCErrorCode.HANDSHAKE_INCOMPLETE]: 'Handshake not completed',
[RPCErrorCode.TIMEOUT_ERROR]: 'Request timeout',
[RPCErrorCode.CALL_PROTOCOL_ERROR]: 'Call protocol error',
[RPCErrorCode.CONNECTION_DISCONNECTED]: 'Connection disconnected',
} as const;
export class RPCError extends Error {

View File

@@ -2,7 +2,7 @@ type EventType = Record<string, any>;
export class BaseEventEmitter<T extends EventType> {
private events: Map<keyof T, Set<(args: any) => void>> = new Map();
protected events: Map<keyof T, Set<(args: any) => void>> = new Map();
public on<K extends keyof T>(event: K, listener: (args: T[K]) => void) {
this.addListener({ event, listener });