@aimee-blue/ab-service-kit
Version:
Aimee Blue Service Template
1 lines • 9.46 kB
Source Map (JSON)
{"version":3,"sources":["../../../src/shared/sockets/socketRegistryState.ts"],"names":["detachFromSocketInWatchMode","state","id","socketState","sockets","get","subscription","waitForCompletion","rest","set","unsubscribe","onDetach","closeSocketCore","attachToSocket","buildTeardown","delete","waitForCompletionThenTeardown","wait","teardown","logger","then","catch","err","error","clientSideCloseHandler","ws","closingByKit","addSocket","oldState","on","code","close","closeSocket","waitForAllToComplete","all","reduce","previous","Promise","resolve","onServerClose","values","buildRegistryStateApi","Object","freeze"],"mappings":"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","sourcesContent":["import { Socket } from 'net';\nimport { Subscription } from 'rxjs';\nimport { SocketWithInfo, MessageWithInfo } from './types';\nimport { AnySocketEpic } from '../kit';\nimport { BasicLogger } from '../logging';\n\nexport type WaitForCompletionFn = () => Promise<'completed' | 'timed-out'>;\n\nexport type WatchModeDetachBehavior = 'unsubscribe' | 'disconnect';\n\nexport interface IConnectedSocket {\n id: string;\n pathname: string;\n ws: SocketWithInfo;\n socket: Socket;\n request: MessageWithInfo;\n subscription?: Subscription;\n waitForCompletion?: WaitForCompletionFn;\n onDetach: WatchModeDetachBehavior;\n}\n\nexport interface ISocketRegistryState {\n epicsByPath: Map<string, AnySocketEpic>;\n sockets: Map<string, IConnectedSocket>;\n logger: BasicLogger;\n}\n\nconst detachFromSocketInWatchMode = (state: ISocketRegistryState) => (\n id: string\n) => {\n const socketState = state.sockets.get(id);\n if (!socketState) {\n return;\n }\n\n const { subscription, waitForCompletion, ...rest } = socketState;\n\n if (!subscription) {\n return;\n }\n\n state.sockets.set(id, rest);\n\n // detachFromSocket should only be called in case if we want to unload\n // previous version of the code from memory\n subscription.unsubscribe();\n\n if (rest.onDetach === 'disconnect') {\n closeSocketCore(socketState, 1012);\n }\n};\n\nconst attachToSocket = (state: ISocketRegistryState) => (\n id: string,\n subscription: Subscription,\n waitForCompletion: WaitForCompletionFn,\n onDetach: WatchModeDetachBehavior\n) => {\n const socketState = state.sockets.get(id);\n if (!socketState) {\n return;\n }\n\n state.sockets.set(id, {\n ...socketState,\n subscription,\n waitForCompletion,\n onDetach,\n });\n};\n\nconst buildTeardown = (state: ISocketRegistryState, id: string) => () => {\n const socketState = state.sockets.get(id);\n if (!socketState) {\n return;\n }\n\n if (socketState.subscription) {\n socketState.subscription.unsubscribe();\n }\n state.sockets.delete(socketState.id);\n};\n\nconst waitForCompletionThenTeardown = (\n wait: WaitForCompletionFn,\n teardown: ReturnType<typeof buildTeardown>,\n logger: BasicLogger\n) => {\n wait()\n .then(teardown)\n .catch((err) => {\n logger.error('💥 Error while waiting for epic to complete', err);\n teardown();\n });\n};\n\nconst clientSideCloseHandler = (\n state: ISocketRegistryState,\n id: string\n) => () => {\n const socketState = state.sockets.get(id);\n if (!socketState) {\n return;\n }\n\n if (socketState.ws.closingByKit) {\n return;\n }\n\n const teardown = buildTeardown(state, id);\n\n if (socketState.waitForCompletion) {\n waitForCompletionThenTeardown(\n socketState.waitForCompletion,\n teardown,\n state.logger\n );\n } else {\n teardown();\n }\n};\n\nconst addSocket = (state: ISocketRegistryState) => (\n socketState: IConnectedSocket\n) => {\n const oldState = state.sockets.get(socketState.id);\n if (oldState) {\n state.logger.error(\n '💥 Socket with id already exists',\n oldState,\n 'will be replaced with',\n socketState\n );\n }\n\n socketState.ws.on('close', clientSideCloseHandler(state, socketState.id));\n\n state.sockets.set(socketState.id, socketState);\n};\n\nconst closeSocketCore = (socketState: IConnectedSocket, code?: number) => {\n socketState.ws.closingByKit = true;\n socketState.ws.close(code);\n};\n\nconst closeSocket = (state: ISocketRegistryState) => (\n id: string,\n code?: number\n) => {\n const socketState = state.sockets.get(id);\n if (!socketState) {\n return;\n }\n\n closeSocketCore(socketState, code);\n};\n\nconst waitForAllToComplete = async (all: IConnectedSocket[]) =>\n await all.reduce(\n (previous, state) =>\n previous.then(() =>\n state.waitForCompletion\n ? state.waitForCompletion()\n : Promise.resolve('completed')\n ),\n Promise.resolve()\n );\n\nconst onServerClose = (state: ISocketRegistryState) => async () => {\n const all = [...state.sockets.values()];\n\n // close sockets and possibly start teardown/completion process\n // on the epic handlers:\n for (const socketState of all) {\n closeSocketCore(socketState, 1012);\n }\n\n // wait for all the epics to complete:\n await waitForAllToComplete(all);\n\n // cleanup all the data in the state:\n for (const socketState of all) {\n if (socketState.subscription) {\n socketState.subscription.unsubscribe();\n }\n state.sockets.delete(socketState.id);\n }\n};\n\nexport const buildRegistryStateApi = (state: ISocketRegistryState) => {\n return Object.freeze({\n addSocket: addSocket(state),\n closeSocket: closeSocket(state),\n detachFromSocketInWatchMode: detachFromSocketInWatchMode(state),\n attachToSocket: attachToSocket(state),\n onServerClose: onServerClose(state),\n });\n};\n\nexport type RegistryStateApi = ReturnType<typeof buildRegistryStateApi>;\n"],"file":"socketRegistryState.js"}