{"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"]}