slavery-js
Version:
A simple clustering app that allows you to scale an application on multiple thread, containers or machines
1 lines • 33.5 kB
Source Map (JSON)
{"version":3,"sources":["../../src/nodes/Node.ts"],"sourcesContent":["import Network, { Listener, Connection } from '../network/index.js';\nimport { ServiceClient } from '../service/index.js';\nimport type { ServiceAddress } from './types/index.js';\nimport { await_interval, execAsyncCode, log } from '../utils/index.js';\nimport { serializeError, deserializeError } from 'serialize-error';\n\n/*\n * this class will basicaly connect to all of the services given to it by the primary service.\n * 1.- attempt to make a conenction the primary service passed by the server\n * 2.- it will take a list of services\n\n/* this calss will make a slave type which will be an a child of the Node class\n * this is the class that will be used to run the the client of a node\n * like other classes it will work as both\n * the server connection to the client and the client conenction to the server.\n * this class will have a list of methods that will be converted to listeners\n * and a list of listeners that will be converted to methods\n */\n\ntype NodeStatus = 'idle' | 'working' | 'error';\n\ntype NodeOptions = {\n timeout?: number,\n}\n\ntype NodeClientParamters = {\n mode: 'client',\n master_host: string,\n master_port: number,\n methods: { [key: string]: (parameter: any) => any },\n services?: ServiceAddress[],\n options?: NodeOptions,\n}\n\ntype NodeServerParameters = {\n mode: 'server',\n connection: Connection,\n network: Network,\n stashSetFunction: (key: string, value: any) => any,\n stashGetFunction: (key: string) => any,\n services: ServiceAddress[],\n statusChangeCallback: (status: NodeStatus, node: Node) => void,\n options?: NodeOptions,\n}\n\nclass Node {\n public mode: 'client' | 'server';\n public id: string | undefined = undefined;\n public status: NodeStatus = 'idle';\n public listeners: Listener[] = [];\n public lastUpdateAt: number = Date.now();\n public master_host: string | undefined = undefined;\n public master_port: number | undefined = undefined;\n public network: Network | undefined = undefined;\n public servicesConnected: boolean = false;\n public hasStartupFinished: boolean = false;\n // fields when the class is client handler on a service\n public statusChangeCallback: ((status: NodeStatus, node: Node) => void) | null = null;\n // stash changes functions\n public stashSetFunction: (({ key, value }: { key: string, value: any }) => any) | null = null;\n public stashGetFunction: ((key: string) => any) | null = null;\n // fields when the class is a service handler on a node\n public services: ServiceAddress[] = [];\n public doneMethods: { [key: string]: boolean } = {};\n public methods: { [key: string]: (parameter?: any, self?: Node) => any } = {};\n // options\n public options: NodeOptions = {\n timeout: 10000,\n }\n\n // takes and empty parameter or a object with the propertie methods\n constructor(params : NodeClientParamters | NodeServerParameters){\n // set the mode\n this.mode = params.mode;\n if(this.mode === 'client'){\n params = params as NodeClientParamters;\n // set the master host and port\n this.master_host = params.master_host;\n this.master_port = params.master_port;\n // set the services\n this.services = params.services || [];\n // set the options\n this.options = params.options || {};\n // add the methods\n this.addMethods(params.methods);\n }else if(this.mode === 'server'){\n params = params as NodeServerParameters;\n // set the stash functions\n this.setStashFunctions({ set: params.stashSetFunction, get: params.stashGetFunction });\n // set the connection\n this.setNodeConnection(params.connection, params.network);\n // set the services\n this.services = params.services;\n // set the status change callback\n this.statusChangeCallback = params.statusChangeCallback;\n }\n }\n\n /* this function will work on any mode the class is on */\n public getId = () => this.id;\n public getStatus = () => this.status;\n public lastHeardOfIn = () => Date.now() - this.lastUpdateAt;\n public isIdle = () => this.status === 'idle';\n public isWorking = () => this.status === 'working';\n public isError = () => this.status === 'error';\n private updateLastHeardOf = () => this.lastUpdateAt = Date.now();\n private updateStatus = (status: NodeStatus) => this.status = status;\n public untilFinish = async () => {\n await await_interval({\n condition: () => this.isIdle(),\n interval: 100,\n }).catch(() => { throw new Error('The node is not idle') })\n return true;\n }\n\n public start = async () => {\n // this function will start the node\n if(this.mode === 'client') return await this.start_client();\n else if(this.mode === 'server') return await this.start_server();\n }\n\n public run = async (method: string, parameter: any) => {\n if(this.mode === 'client') return await this.run_client({ method, parameter });\n else if(this.mode === 'server') return await this.run_server({ method, parameter });\n }\n\n public exec = async (method: string, code: string) => {\n if(this.mode === 'client') return await this.exec_client(code);\n else if(this.mode === 'server') return await this.exec_server(code);\n }\n\n public setServices = async (services: ServiceAddress[]) => {\n if(this.mode === 'client') return await this.setServices_client(services);\n else if(this.mode === 'server') return await this.setServices_server(services);\n }\n\n public exit = async () => {\n if(this.mode === 'client') return await this.exit_client();\n else if(this.mode === 'server') return await this.exit_server();\n }\n\n public ping = async () => {\n if(this.mode === 'client') return await this.ping_client();\n else if(this.mode === 'server') return await this.ping_server();\n }\n\n /* this functions will set the Node.ts as a client handler for the server */\n public setNodeConnection(connection: Connection, network: Network){\n // get the node id from the conenction\n this.id = connection.getTargetId();\n // set the network\n this.network = network;\n // define the listners which we will be using to talk witht the client node\n if(this.stashSetFunction === null || this.stashGetFunction === null )\n throw new Error('The stash functions have not been set');\n // set the listeners\n this.listeners = [// this callbacks will run when we recive this event from the client node\n { event: '_set_status', parameters: ['status'], callback: this.handleStatusChange.bind(this) },\n { event: '_ping', parameters: [], callback: () => '_pong' },\n { event: '_set_stash', parameters: ['key', 'value'], callback: this.stashSetFunction },\n { event: '_get_stash', parameters: ['key'], callback: this.stashGetFunction },\n { event: '_get_services_address', parameters: [], callback: () => this.services },\n ]\n // register the listeners on the connection\n connection.setListeners(this.listeners);\n }\n\n public setStatusChangeCallback(callback: (status: NodeStatus, node: Node) => void){\n this.statusChangeCallback = callback;\n }\n\n public setStashFunctions({ set, get }: { set: (key: string, value: any) => any, get: (key: string) => any }){\n this.stashSetFunction = ({ key, value }: { key: string, value: any }) => set(key, value);\n this.stashGetFunction = get;\n }\n\n public handleStatusChange(status: NodeStatus){\n // set status as status and call the callback\n this.updateStatus(status);\n this.statusChangeCallback && this.statusChangeCallback(status, this);\n }\n\n public lastHeardOf(){\n // this function will be called when the client node tells us that it is working\n this.updateLastHeardOf();\n return this.lastHeardOfIn();\n }\n\n private async start_server(){\n // send the list of services to the client node\n let response = await this.setServices_server(this.services);\n if(response === true){\n this.servicesConnected = true;\n return true;\n }else\n throw new Error(`slavery-js: [Node][${this.id}] Could not set services on the client node`);\n }\n\n\n private async run_server({method, parameter}: {method: string, parameter: any}){\n // this function will send the node a method to be run in the client\n // set the status to working\n this.handleStatusChange('working');\n let res = await this.send('_run', { method, parameter });\n // set the status to idle\n this.handleStatusChange('idle');\n // if there is an error\n if(res.isError === true)\n res.error = deserializeError(res.error);\n // return the result\n return res\n }\n\n private async exec_server(code: string){\n // this function will send the node a code to be run in the client\n // set the status to working\n try {\n this.handleStatusChange('working');\n let res = await this.send('_exec', code);\n // set the status to idle\n this.handleStatusChange('idle');\n // if there is an error\n if(res.isError === true)\n res.error = deserializeError(res.error);\n // return the result\n return res;\n } catch (error) {\n this.handleStatusChange('idle'); // Make sure to return to idle state\n log(`[Node][${this.id}] Error in exec_server: ${error}`);\n return { isError: true, error: serializeError(error) };\n }\n }\n\n private async setServices_server(services: ServiceAddress[]){\n // this function will send send a list of services to the client node\n try {\n return await this.send('_set_services', services);\n } catch (error) {\n log(`[Node][${this.id}] Error in setServices_server: ${error}`);\n throw error;\n }\n }\n\n public async ping_server(){\n // this function will ping the client node\n try {\n let res = await this.send('_ping');\n if(res === 'pong') this.updateLastHeardOf();\n return true;\n } catch (error) {\n log(`[Node][${this.id}] Error in ping_server: ${error}`);\n return false;\n }\n }\n\n public async exit_server(){\n // this function tell the node client to exit\n try {\n let res = await this.send('_exit', null)\n // we catch the timeout erro scince the client node will exit\n .catch((error) => { \n if(error === 'timeout') return true; \n log(`[Node][${this.id}] Error in exit_server: ${error}`);\n return false;\n });\n return res;\n } catch (error) {\n log(`[Node][${this.id}] Error in exit_server: ${error}`);\n return false;\n }\n }\n\n public async send(method: string, parameter: any = null){\n // fucntion for sending a method to the client node\n if(this.network === undefined) throw new Error('The network has not been set');\n if(this.id === undefined) throw new Error('The id has not been set');\n if(this.mode === undefined) throw new Error('The mode has not been set');\n // get the connection of which we will send the method\n let connection: Connection | undefined = undefined;\n if(this.mode === 'server')\n connection = this.network.getNode(this.id);\n else if(this.mode === 'client')\n connection = this.network.getService('master');\n if(connection === undefined)\n throw new Error('Could not get the conenction from the network');\n // send the method to the node\n return await connection.send(method, parameter);\n }\n\n /* this function will be called when the client node tells us that it is working */\n public async start_client(){\n // conenct the master process which will tell us what to do\n // create an id for the node\n this.id = this.id || Math.random().toString(36).substring(4);\n this.network = new Network({\n name: 'node',\n id: this.id,\n options: {\n timeout: this.options.timeout || 5 * 60 * 1000,\n }\n });\n // check if the network is defined\n if(this.master_host === undefined || this.master_port === undefined)\n throw new Error('The master host and port have not been set');\n // form the conenction with the master\n this.network.connect({ host: this.master_host, port: this.master_port, as: 'master' });\n // verify that the connection is established\n \n // set the listeners which we will us on the and the master can call on\n this.listeners = [\n { event: '_run', parameters: ['method', 'parameter'], callback: this.run_client.bind(this) },\n { event: '_exec', parameters: ['code_string'], callback: this.exec_client.bind(this) },\n { event: '_set_services', parameters: ['services'], callback: this.setServices_client.bind(this) },\n { event: '_is_idle', parameters: [], callback: this.isIdle.bind(this) },\n { event: '_is_busy', parameters: [], callback: this.isBusy.bind(this) },\n { event: '_has_done', parameters: ['method'], callback: this.hasDone.bind(this) },\n { event: '_ping', parameters: [], callback: () => 'pong' },\n { event: '_exit', parameters: [], callback: this.exit_client.bind(this) }\n ];\n // register the listeners on the network\n this.network.registerListeners(this.listeners);\n // if we have not recvied the services from the master yet ask for them\n await await_interval({ \n condition: () => this.servicesConnected, timeout: 1000\n }).catch(async () => {\n let services = await this.get_sevices_address();\n this.setServices_client(services);\n })\n // run startup method\n await this.run_startup();\n }\n\n private async run_client({method, parameter}: {method: string, parameter: any}){\n // this function will be called by the a service or another node to run a function\n // wait until services are connected, with timeout of 10 seconds\n await await_interval({\n condition: () => this.servicesConnected, timeout: 10000, interval: 10\n }).catch(() => { throw new Error(`slavery-js: [Node][${this.id}] run method, because it could not connect to services`) })\n await await_interval({\n condition: () => this.hasStartupFinished, timeout: 60 * 1000, interval: 1\n }).catch(() => { throw new Error(`slavery-js: [Node][${this.id}] run method, because the startup method did not finish`) })\n await await_interval({\n condition: () => this.isIdle(), timeout: 60 * 1000, interval: 1\n }).catch(() => { throw new Error(`slavery-js: [Node][${this.id}] run method, because the node timed for becoming idle`) })\n try {\n // set the status to working\n this.updateStatus('working');\n // get the services that we have connected to\n let services = await this.get_services();\n let services_params = { ...services, slave: this, self: this };\n // run method\n const result = await this.methods[method](parameter, services_params);\n // set has done method\n this.doneMethods[method] = true;\n // return the result\n return { result, isError: false };\n } catch(error){ // serilize the error\n this.updateStatus('error');\n // return the error\n return { error: serializeError(error), isError: true };\n } finally {\n // set the status to idle\n this.updateStatus('idle');\n }\n }\n\n\n private async exec_client(code_string: string){\n /* this function will execute some passed albitrary code */\n // check if the code_string is a string\n if(typeof code_string !== 'string')\n return { isError: true, error: serializeError(new Error('Code string is not a string')) }\n // await until service is connected\n await await_interval({\n condition: () => this.servicesConnected,\n timeout: 20 * 1000\n }).catch(() => {\n throw new Error(`slavery-js: [Node][${this.id}] executing code, because it could not connect to services`);\n })\n let services = await this.get_services();\n let parameter = { ...services, slave: this, self: this };\n try {\n // run the albitrary code\n let result = await execAsyncCode(code_string, parameter);\n return { result: result, isError: false };\n } catch(e) {\n return { isError: true, error: serializeError(e) }\n }\n }\n\n private async run_startup(){\n // make sure that we have the services connected\n await await_interval({\n condition: () => this.servicesConnected,\n timeout: 20 * 1000\n }).catch(() => {\n throw new Error(`slavery-js: [Node][${this.id}] Could not startup Node becasue it could not connect to services`);\n })\n if(this.methods['_startup'] === undefined){\n // if there is no startup method we just return\n this.hasStartupFinished = true;\n return true;\n }\n try {\n // set the status to working\n let services = await this.get_services();\n let parameter = { ...services, slave: this, self: this };\n // run method\n const result = await this.methods['_startup'](null, parameter);\n // set has done method\n this.doneMethods['_startup'] = true;\n this.hasStartupFinished = true;\n // return the result\n return { result, isError: false };\n } catch(error){ // serilize the error\n this.updateStatus('error');\n // return the error\n throw new Error(`[Node][${this.id}] Could not run startup method: ${error}`);\n }\n }\n\n private async get_services(){\n // get the services that we have connected with their respective clients\n let services = this.services.map(\n (s: ServiceAddress) => new ServiceClient(s.name, this.network as Network)\n ).reduce((acc: any, s: ServiceClient) => {\n acc[s.name] = s;\n return acc;\n }, {})\n return services;\n }\n\n\n // this function will communicate with the master node and set the stash in that moment\n public setStash = async (key: any, value: any = null) => await this.send('_set_stash', { key, value });\n public getStash = async (key: string = '') => await this.send('_get_stash', key);\n\n public addMethods(methods: { [key: string]: (parameter: any) => any }){\n // we add the methods to this class\n this.methods = methods;\n // populate methods done\n for(let method in methods)\n this.doneMethods[method] = false;\n }\n\n\n private async setServices_client(services: ServiceAddress[]){\n // we get the list of services that we need to connect to\n this.services = services;\n // connect to the services\n for(let service of services){\n let res = await this.connectService(service);\n if(!res){\n console.error('slavery-js: [Node] Client could not connect to the service, ', service.name);\n return false;\n }else\n log(`[Node][${this.id}] Connected to the service, ${service.name}`);\n }\n this.servicesConnected = true;\n return true\n }\n\n public async connectService({ name, host, port }: ServiceAddress){\n /* this is the client inplementation.\n * it will connect to the service and create methods\n * for every listener that the service has */\n if(!host || !port)\n throw new Error('The service information is not complete');\n // check if there is a service already running on the port and host\n if(this.network === undefined)\n throw new Error('The network has not been set');\n return await this.network.connect({name, host, port});\n }\n\n private async get_sevices_address(){\n // get the services that we have connected with their respective clients\n let res = await this.send('_get_services_address');\n this.services = res;\n return res;\n }\n\n private async ping_client(){\n // this function will ping the master node\n let res = await this.send('_ping');\n if(res === '_pong') this.updateLastHeardOf();\n return true;\n }\n\n private async exit_client(){\n // before we bail we must be nice enough to close our connections\n setTimeout(async () => {\n // if there is a _cleanup method defined\n if(this.methods['_cleanup'] !== undefined)\n await this.run_client({ method: '_cleanup', parameter: null });\n // we close the connections we have,\n if(this.network !== undefined) this.network.close();\n // then we exit the process\n process.exit(0);\n }, 1000);\n return true\n }\n\n public getListeners(){\n if(this.network === undefined) throw new Error('The network has not been set');\n if(this.id === undefined) throw new Error('The id has not been set');\n let listeners = [];\n let connection: Connection | undefined = undefined;\n if(this.mode === 'server'){\n connection = this.network.getNode(this.id);\n listeners = connection.getListeners();\n }else if(this.mode === 'client'){\n connection = this.network.getNode('master');\n listeners = connection.getListeners();\n if(connection === undefined)\n throw new Error('Could not get the conenction from the network');\n }\n return listeners;\n }\n\n public hasDone(method: string){\n return this.doneMethods[method] || false;\n }\n\n /* method synonims */\n public isBusy = this.isWorking;\n public hasFinished = this.hasDone;\n public hasError = this.isError;\n public toFinish = this.untilFinish;\n public set = this.setStash;\n public get = this.getStash;\n public stash = this.setStash;\n public unstash = this.getStash;\n}\n\n\nexport default Node;\n"],"mappings":"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","names":["Network"]}