import { DyFM_AnyError, DyFM_Error, DyFM_Error_Settings, DyFM_Log } from '@futdevpro/fsm-dynamo'; import * as SocketIO from 'socket.io'; import { DyNTS_global_settings } from '../../..'; /** * socket handling and clarification is under development */ export class DyNTS_SocketPresence { /** * this is the presence ID which is used to get and handle the presence * usually the service master identifier such as userID * (issuerLocalId != issuer which is the main master identifier usually the accountID) * */ issuerLocalId: string; serviceName?: string = 'unknown'; onDestroy?: (issuerId: string) => void = (): void => {}; defaultErrorUserMsg?: string = `We encountered an unhandled Socket Error, ` + `\nplease contact the responsible development team.`; sockets?: SocketIO.Socket[] = []; issuer: string; constructor( set: Partial ) { if (!set?.issuerLocalId) { throw new DyFM_Error({ ...this._getDefaultErrorSettings( 'constructor', new Error( `trying to create DyNTS_SocketPresence without a valid issuerLocalId!`/* + `\nset: ${JSON.stringify(set)}` */ ), set?.issuer ), errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-SD0-C00`, additionalContent: { set: set }, }); } this.issuerLocalId = set.issuerLocalId; if (set.serviceName) { this.serviceName = set.serviceName; } if (set.onDestroy) { this.onDestroy = set.onDestroy; } if (set.defaultErrorUserMsg) { this.defaultErrorUserMsg = set.defaultErrorUserMsg; } if (!set?.sockets?.length) { throw new DyFM_Error({ ...this._getDefaultErrorSettings( 'constructor', new Error( `trying to create DyNTS_SocketPresence without a single active socket!` + `\nissuerId: ${this.issuerLocalId}` ), set?.issuer ), errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-SD0-C01`, }); } this.sockets = set.sockets; } /** * Emits event on all sockets * @param event * @param content */ emitEvent(event: string, content: any, issuer: string): void { /* let anyFailed: boolean = false; */ const errors: any = []; const inactiveSockets: SocketIO.Socket[] = []; try { JSON.stringify(content); } catch { throw new DyFM_Error({ ...this._getDefaultErrorSettings( 'emitEvent', new Error( `Emitting event '${event}' on socket(s)(${this.serviceName}) failed!`+ `\n ERROR: content is not stringify-able!` ), issuer ), errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-SPC-EE1`, }); } this.sockets.forEach((socket: SocketIO.Socket, index: number) => { if (!socket.connected) { DyFM_Log.warn( `Emitting event '${event}' on socket(${this.serviceName})-(${index}) failed!` + `\n ERROR: socket[${socket.id}] is not connected! (it will be removed...)` ); /* errors.push( new DyFM_Error({ status: 500, errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-SPC-EE2', addECToUserMsg: true, message: `Emitting event '${event}' on socket(${this.serviceName})-(${index}) failed!`+ `\nERROR: socket[${socket.id}] is not connected!`, userMessage: 'We encountered an unhandled Server Error, please contact the responsible development team.', }) ); */ inactiveSockets.push(socket); socket?.disconnect(true); } }); /* this.sockets.forEach((socket: SocketIO.Socket, index: number) => { if (!socket) { return; } if (inactiveSockets.includes(socket) || !socket?.connected) { socket.TRY RECONNECT } */ this.sockets = this.sockets.filter( (socket): boolean => !inactiveSockets.includes(socket) && socket?.connected ); this.sockets.forEach((socket: SocketIO.Socket, index: number): void => { const success: boolean = socket.emit(event, content, (error): void => { DyFM_Log.error( `Emitting event '${event}' on socket(${this.serviceName})-(${index}) failed!(0)` + `\nerror:`, error ); errors.push(error); }); if (!success) { DyFM_Log.error( `Emitting event '${event}' on socket(${this.serviceName})-(${index}) failed!(1)` ); } }); if (0 < errors.length) { throw new DyFM_Error({ ...this._getDefaultErrorSettings( 'emitEvent', new Error( `Emitting event '${event}' on socket(s)(${this.serviceName}) failed!`+ `\n${errors.length} errors occured!` ), issuer ), errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-SPC-EE3`, additionalContent: { inactiveSockets: inactiveSockets, errors: errors, }, }); } else if (this.sockets.length === 0) { throw new DyFM_Error({ ...this._getDefaultErrorSettings( 'emitEvent', new Error( `Emitting event '${event}' on socket(s)(${this.serviceName}) failed!`+ `\n No more sockets left connected!` ), issuer ), errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-SPC-EE4`, }); } } private _getDefaultErrorSettings( fnName: string, error: DyFM_AnyError, issuer: string ): DyFM_Error_Settings { return { status: (error as DyFM_Error)?.___status ?? 500, message: (error as Error)?.message ?? (error as DyFM_Error)?._message ?? `${fnName} was UNSUCCESSFUL (NTS; ${this.serviceName})`, userMessage: (error as DyFM_Error)?.__userMessage ?? this.defaultErrorUserMsg, issuerService: this.serviceName + ` (${this?.constructor?.name}-DyNTS_SocketPresence)`, addECToUserMsg: !(error as DyFM_Error)?.__userMessage, issuer: issuer, error: error, }; } }