slavery-js
Version:
A simple clustering app that allows you to scale an application on multiple thread, containers or machines
1 lines • 29.6 kB
Source Map (JSON)
{"version":3,"sources":["../../src/service/Service.ts"],"sourcesContent":["import Network, { Listener, Connection } from '../network/index.js';\nimport Node, { NodeManager } from '../nodes/index.js';\nimport Cluster from '../cluster/index.js';\nimport { PeerDiscoveryClient } from '../app/peerDiscovery/index.js';\nimport RequestQueue from './RequestQueue.js';\nimport ProcessBalancer from './ProcessBalancer.js';\nimport ServiceClient from './ServiceClient.js';\nimport Stash from './Stash.js';\nimport { toListeners, log, getPort, isServerActive, execAsyncCode, await_interval } from '../utils/index.js';\nimport type { ServiceAddress, SlaveMethods, Request, Options } from './types/index.js';\nimport { serializeError } from 'serialize-error';\n\n// the paramer the service will take\ntype Parameters = {\n // the name of the service\n service_name: string,\n // the address of the service will take\n peerServicesAddresses?: ServiceAddress[],\n // the adderess of the peer discovery service used to find the other services\n peerDiscoveryAddress?: { host: string, port: number },\n // the master callback that will be called by the master process\n mastercallback?: (...args: any[]) => any,\n // the slave callbacks that will be called by the slaves\n slaveMethods?: SlaveMethods,\n // the options that will be passed to the service\n options?: Options\n};\n\nclass Service {\n /* This will be the based class for the service which salvery will call to create proceses */\n public name: string;\n public host: string;\n public port: number;\n private nodes?: NodeManager;\n private stash: Stash = new Stash();\n private processBalancer?: ProcessBalancer | null = null;\n private requestQueue: RequestQueue | null = null;\n public nm_host: string;\n public nm_port: number;\n public number_of_nodes: number;\n private masterCallback?: (...args: any[]) => any;\n private slaveMethods: SlaveMethods;\n private peerAddresses: ServiceAddress[];\n private peerDiscoveryAddress?: { host: string, port: number };\n private peerDiscovery?: PeerDiscoveryClient;\n private cluster?: Cluster;\n private network?: Network;\n private options: Options;\n private servicesConnected: boolean = false;\n\n constructor(params: Parameters) {\n this.name = params.service_name;\n // the address of the service will take\n this.host = params.options?.host || 'localhost';\n this.port = params?.options?.port || 0;\n // the host of the node manager\n this.nm_host = params.options?.nm_host || 'localhost';\n this.nm_port = params.options?.nm_port || 0;\n // the call that will run the master process\n this.masterCallback = params.mastercallback || undefined;\n // the method that we will use ont he slave\n this.slaveMethods = params.slaveMethods || {};\n // other sevices that we conenct to\n this.peerAddresses = params.peerServicesAddresses || [];\n // the peer discovery service\n this.peerDiscoveryAddress = params.peerDiscoveryAddress || undefined;\n this.peerDiscovery = undefined;\n // if both the peerAddresses and the peerDiscoveryServiceAddress are not defined,\n // we will throw an error\n if(this.peerAddresses === undefined && this.peerDiscoveryAddress === undefined)\n throw new Error('Peer Addresses or Peer Discovery Service Address must be defined');\n // the options that will be passed to the service\n this.options = params.options || {};\n // smallest number of processes need to run\n // the master and a slave\n if(this.options.number_of_nodes === undefined){\n this.number_of_nodes = 1;\n if(this.options.auto_scale === undefined)\n this.options.auto_scale = true;\n }else{\n this.number_of_nodes = this.options.number_of_nodes;\n if(this.options.auto_scale === undefined)\n this.options.auto_scale = false\n }\n }\n\n public async start() { // this will start the service\n // let initlize the cluster so that we can start the service\n this.cluster = new Cluster(this.options);\n // create a new process for the master process\n this.cluster.spawn('master_' + this.name, {\n allowedToSpawn: true, // give the ability to spawn new processes\n spawnOnlyFromPrimary: true // make sure that only one master process is created\n });\n // run the code for the master process\n if(this.cluster.is('master_' + this.name)) {\n // initialize the master process\n await this.initialize_master();\n }\n // if the cluster is a slave we initialize the process\n if(this.cluster.is('slave_' + this.name)) {\n await this.initialize_slaves();\n }\n }\n\n private async initialize_master() {\n // initialize the master and all the services\n // get the port for the service\n if(this.port === 0) this.port = await getPort({host: this.host});\n // if we have a peer discovery service we will try to connect to it\n if(this.peerDiscoveryAddress !== undefined) await this.handle_peer_discovery();\n log('peer addresses', this.peerAddresses);\n // initialize the node manager\n await this.initlize_node_manager();\n // initialize the request queue\n this.initialize_request_queue();\n // initlieze the network and create a service\n this.network = new Network({name: this.name + '_service_network'});\n // list the listeners we have for the other services to request\n let listeners = toListeners(this.slaveMethods).map(\n // add out handle request function to the listener\n l => ({ ...l, callback: this.handle_request(l, 'run') })\n );\n // add the _exec listner, we have to add it here as the listners in \n // this.getServiceListeners strips the selector\n let exec_listener : Listener = { event: '_exec', callback: ()=>{} };\n listeners.push({ ...exec_listener, callback: this.handle_request(exec_listener, 'exec') });\n // add the local service listener\n listeners = listeners.concat(this.getServiceListeners());\n // create the server\n this.network.createServer(this.name, this.host, this.port, listeners);\n // initilze the process balancer\n this.initialize_process_balancer();\n // remover self address from the peer addresses by name\n this.peerAddresses = this.peerAddresses.filter((p: ServiceAddress) => p.name !== this.name);\n // connect to the services\n let connections = await this.network.connectAll(this.peerAddresses);\n // create a service client for the services\n let services = connections.map( (c: Connection) => {\n let name = c.getTargetName();\n if(name === undefined) throw new Error('Service name is undefined');\n return new ServiceClient(name, this.network as Network, this.options);\n }).reduce((acc: any, s: ServiceClient) => {\n acc[s.name] = s;\n return acc;\n }, {})\n // set service as connected\n this.servicesConnected = true;\n // run the callback for the master process\n if(this.masterCallback !== undefined)\n this.masterCallback({ ...services, slaves: this.nodes, master: this, self: this });\n }\n\n private async initialize_slaves() {\n let node = new Node();\n // TODO: Need to find a better way to pass the host and port\n // to the slave process, so far I am only able to pass it through\n // the metadata in the cluster\n // get the nm_host and nm_port from the metadata\n let metadata = process.env.metadata;\n if(metadata === undefined)\n throw new Error('could not get post and host of the node manager, metadata is undefined');\n let { host, port } = JSON.parse(metadata)['metadata'];\n // connect with the master process\n await node.connectToMaster(host, port);\n // add services to the node\n await node.setServices(this.peerAddresses);\n // read the methods to be used\n node.addMethods(this.slaveMethods)\n // run _startup method\n await node._startup();\n }\n\n private async initlize_node_manager() {\n /* the node manage will be used to conenct to and manage the nodes */\n // if the slave methods is an empty object we will not make any nodes\n if(Object.keys(this.slaveMethods).length === 0) return null;\n // get the port for the node manager\n if(this.nm_port === 0)\n this.nm_port = await getPort({host: this.nm_host});\n // make a node manager\n this.nodes = new NodeManager({\n name: this.name,\n host: this.nm_host,\n port: this.nm_port,\n stash: this.stash, // set the stash\n })\n // spawn the nodes from the node Manager\n await this.nodes.spawnNodes('slave_' + this.name, this.number_of_nodes, {\n metadata: { host: this.nm_host, port: this.nm_port }\n });\n // register the services in the nodes\n await this.nodes.registerServices(this.peerAddresses);\n // get the nodes\n return this.nodes;\n }\n\n private initialize_request_queue() {\n /* this function will give the request queue all the values an callback it need tow work */\n // if there are no nodes to make don't create a request queue\n if(Object.keys(this.slaveMethods).length === 0) return null\n // if node manager is not defined throw an error\n if(this.nodes === undefined) throw new Error('Node Manager is not defined');\n // create a new request queue\n this.requestQueue = new RequestQueue({\n // we pass the functions that the request queue will use\n get_slave: this.nodes.getIdle.bind(this.nodes),\n process_request:\n async (node: Node, request: Request) => await node[request.type](request.method, request.parameters)\n \n });\n }\n\n private initialize_process_balancer() {\n /* this function will initialize the process balancer */\n if(Object.keys(this.slaveMethods).length === 0) return null;\n // if the auto scale is true we will create a process balancer\n if(this.options.auto_scale === true){\n this.processBalancer = new ProcessBalancer({\n // pass the functions need for the balancer to know the hwo to balance\n checkQueueSize: this.requestQueue?.queueSize.bind(this.requestQueue),\n checkSlaves: () => ({ idleCount: this.nodes?.getIdleCount(), workingCount: this.nodes?.getBusyCount() }),\n addSlave: () => this.nodes?.spawnNodes( 'slave_' + this.name, 1, { metadata: { host: this.nm_host, port: this.nm_port } }),\n removeSlave: () => this.nodes?.killNode()\n });\n }\n }\n\n\n private getServiceListeners() {\n // let add the listeners which we this service will respond\n // lets ignore the selector field\n let listeners = [{\n // get number of nodes\n event: '_get_nodes_count',\n callback: () => ({ result: this.nodes?.getNodeCount() })\n },{\n event: '_get_nodes',\n callback: () => this.nodes?.getNodes().map((n: Node) => ({ status: n.status, id: n.id }))\n },{\n event: '_get_idle_nodes', // wee need to filter this array of objects\n callback: () => ({ result: this.nodes?.getIdleNodes() })\n },{\n event: '_get_busy_nodes', // this one too\n callback: () =>({ result: this.nodes?.getBusyNodes() })\n },{\n event: '_number_of_nodes_connected',\n params: ['node_num'],\n callback: async (node_num: number) => await this.nodes?.numberOfNodesConnected(node_num)\n },{ // select individual nodes, or groups of nodes\n event: '_select',\n params: ['node_num'],\n callback: async (node_num: number) => {\n if(this.nodes === undefined) throw new Error('Nodes are undefined');\n // get the idle nodes\n let count = this.nodes?.getNodeCount();\n if(count === undefined) return { isError: true, error: serializeError(new Error('Nodes are undefined')) }\n // if the number of nodes is greater than the number of nodes we have\n if(node_num > count) return { isError: true, error: serializeError(new Error('Not enough nodes')) }\n if(node_num === 0) node_num = count;\n // select the nodes\n let selected_nodes = [];\n for(let i = 0; i < node_num; i++){\n let node = this.nodes?.nextNode();\n if(node === null) throw new Error('could not get node');\n selected_nodes.push(node.id);\n }\n // return the selected nodes\n return { result: selected_nodes }\n }\n },{ // spawn or kill a node\n event: '_add_node',\n params: ['number_of_nodes'],\n callback: (number_of_nodes: number) =>\n ({ result: this.nodes?.spawnNodes(\n 'slave_' + this.name,\n number_of_nodes,\n { metadata: { host: this.nm_host, port: this.nm_port } }\n ) })\n },{ // kill a node\n event: '_kill_node',\n params: ['node_id'],\n callback: async(node_ids: string[] | string | undefined | number) => {\n let res;\n if(node_ids === undefined){\n res = await this.nodes?.killNode();\n }else if(typeof node_ids === 'string'){\n res = await this.nodes?.killNode(node_ids);\n }else if(typeof node_ids === 'number'){\n for(let i = 0; i < node_ids; i++) await this.nodes?.killNode();\n }else if(node_ids.length === 0){\n res = await this.nodes?.killNode();\n }else if(node_ids.length >= 1){\n res = await this.nodes?.killNodes(node_ids);\n }else {\n return { isError: true, error: serializeError(new Error('Invalid node id')) }\n }\n return ({result: res});\n }\n },{ // exit the service\n event: '_queue_size',\n callback: () => ({ result: this.requestQueue?.queueSize() })\n },{\n event: '_turn_over_ratio',\n callback: () => ({ result: this.requestQueue?.getTurnoverRatio() })\n },{\n event: '_exec_master',\n params: ['code_string'],\n callback: async (code_string: any) => {\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(() => this.servicesConnected, 10000).catch(() => {\n throw new Error(`[Service] Could not connect to the services`);\n })\n let service = this.getServices();\n let parameter = { ...service, master: this, self: this };\n try {\n // run the albitrary code\n let result = await execAsyncCode(code_string, parameter);\n return { result: result }\n } catch(e) {\n return { isError: true, error: serializeError(e) }\n }\n }\n },{\n event: 'new_service',\n params: ['service_address'],\n callback: async (service_address: ServiceAddress) => {\n if(this.network === undefined) throw new Error('Network is not defined');\n await this.network?.connect(service_address);\n }\n },{\n event: 'exit',\n callback: () => ({ result: this.exit() })\n }];\n // get only the paramters, diregar the rest\n return listeners.map(l => {\n return { ...l, callback: ({ parameters }: any) => l.callback(parameters) }\n });\n }\n\n private handle_request(l: Listener, type: 'run' | 'exec'): Function {\n /* this function will take a listener triggered by another a request\n * it will set the request in the request queue, and return a promise\n * which resolves once the request is processed.\n * the queue will processs the request when it finds an idle node\n * and the node returns the result. */\n return async (data: any) => {\n if(this.slaveMethods === undefined) throw new Error('Slave Methods are not defined');\n if(this.requestQueue === null)\n throw new Error('Request Queue is not defined');\n let promise = this.requestQueue.addRequest({\n method: l.event,\n type: type,\n parameters: data.parameters,\n selector: data.selection,\n completed: false,\n result: null\n });\n // wait until the request is processed\n let result = await promise;\n if(result.isError === true) // if there is an error serialize it\n result.error = serializeError(result.error);\n return result;\n }\n }\n\n private async handle_peer_discovery() {\n if(this.peerDiscoveryAddress === undefined) throw new Error('Peer Discovery Address is not defined');\n if(this.cluster === undefined) throw new Error('Cluster is not defined');\n // check if the peer discovery service is active\n log(`[${this.name}] > Service > Checking if Peer Discovery Service is active`);\n log(`[${this.name}] > Service > Peer Discovery Address: ${this.peerDiscoveryAddress.host}:${this.peerDiscoveryAddress.port}`);\n if(await isServerActive(this.peerDiscoveryAddress) === false)\n throw new Error('Peer Discovery Service is not active');\n // if it is active we will register to it\n this.peerDiscovery = new PeerDiscoveryClient(this.peerDiscoveryAddress);\n await this.peerDiscovery.connect();\n // register the service to the peer discovery service\n this.peerDiscovery.register({ name: this.name, host: this.host, port: this.port });\n // get the services that we will connect to\n this.peerAddresses = await this.peerDiscovery.getServices();\n }\n\n private getServices(): { [serviceName: string]: ServiceClient } {\n // get the service from the network\n if(this.network === undefined) throw new Error('Network is not defined');\n let services = this.network.getServices()\n return services.map( (c: Connection) => {\n let name = c.getTargetName();\n if(name === undefined) throw new Error('Service name is undefined');\n return new ServiceClient(name, this.network as Network, this.options);\n }).reduce((acc: any, s: ServiceClient) => {\n acc[s.name] = s;\n return acc;\n }, {})\n }\n\n public exit(){\n //log(`[${this.name}] will exit in 1 seconds`);\n setTimeout(() => {\n // first we close the ProcessBalancer if we have one\n if(this.processBalancer) this.processBalancer.exit();\n // request queue will be closed\n if(this.requestQueue) this.requestQueue.exit();\n // if peer discovery is defined we will close it\n if(this.peerDiscovery) this.peerDiscovery.exit();\n // then we close the nodes Manager\n if(this.nodes) this.nodes.exit();\n // then we close the connections we have,\n if(this.network) this.network.close();\n // lastly we close ourselves, how sad\n process.exit(0);\n }, 1000);\n return true\n }\n\n public set = async (key: any, value: any = null) =>\n await this.stash.set(key, value);\n\n public get = async (key: string = '') =>\n await this.stash.get(key);\n}\n\n\n\nexport default Service;\n"],"mappings":"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","names":["Stash","Cluster","Network","ServiceClient","Node","RequestQueue","ProcessBalancer"]}