UNPKG

slavery-js

Version:

A simple clustering app that allows you to scale an application on multiple thread, containers or machines

1 lines 10.9 kB
{"version":3,"sources":["../../src/network/Server.ts"],"sourcesContent":["import { Server } from \"socket.io\";\nimport http from \"http\";\nimport { createServer } from \"http\";\nimport { Socket } from \"socket.io\";\nimport { log, Pool } from '../utils/index.js';\nimport type Listener from './types/Listener.js';\nimport Connection from \"./Connection.js\";\n\n\nclass NetworkServer {\n /* this class will handle the logic managing the server conenctions with clilent,\n * it will keep track of the node id and it will handle connection and dicoections */\n private io: Server;\n private host: string;\n private port: number;\n private maxTransferSize: number;\n private clients: Pool<Connection>;\n public name: string;\n public isLan: boolean;\n public connectionCallback: any;\n public disconnectCallback: any;\n public listeners: Listener[];\n public httpServer?: http.Server;\n public isReady: boolean;\n public timeout: number;\n private ioOptions: any;\n\n constructor({ name, host, port, listeners } : {\n name: string, host: string, port: number, listeners: Listener[],\n }, options?: { timeout: number, maxTransferSize: number }) {\n this.host = host || \"localhost\";\n this.isLan = this.host !== 'localhost'\n this.port = port || 0; // zero means random port\n this.isReady = false;\n this.maxTransferSize = options?.maxTransferSize || 1e9; // default 1GB\n this.name = name? name : \"server\";\n this.connectionCallback = null;\n this.disconnectCallback = null;\n this.clients = new Pool<Connection>();\n this.listeners = listeners || [];\n this.ioOptions = {\n maxHttpBufferSize: this.maxTransferSize,\n };\n this.timeout = options?.timeout || 5 * 60 * 1000; // default 5 minutes\n // initiate with the server\n if(this.isLan){ // if we are in a over lan\n // create a http server\n this.httpServer = createServer();\n this.io = new Server(this.httpServer, this.ioOptions);\n // check if io server was created\n if(this.io.httpServer.address() === null)\n throw new Error(\"Host and port already in use or invalid\");\n this.httpServer.listen(this.port, this.host, () => {\n let address = this.httpServer?.address();\n if(!address || typeof address === \"string\") {\n console.error(\"Server is not running\");\n return;\n }\n this.isReady = true;\n this.port = address.port\n });\n }else{ // if we are in localhost\n this.io = new Server(this.port, this.ioOptions);\n // check is io server was created\n if(this.io.httpServer.address() === null)\n throw new Error(\"Host and port already in use or invalid\");\n // get the port number\n this.port = (this.io as any).httpServer.address().port;\n }\n // create a new socket.io client instance\n this.io.on(\"connection\", this.handleConnection.bind(this));\n this.io.on(\"reconnect\", () => log(\"[Server] on reconnect triggered\"));\n this.io.on(\"disconnect\", this.handleDisconnection.bind(this));\n // set the listener on the server socket\n this.setListeners(this.listeners);\n }\n\n private async handleConnection(socket: Socket) {\n log(\"[Server] got new connection\");\n // make a new connectection instance\n let connection = new Connection({\n socket, name: this.name,\n options: {\n listeners: this.listeners,\n timeout: this.timeout,\n }\n });\n // await fo connection to be established\n await connection.connected();\n // get the id of the connection\n let id = connection.getTargetId();\n log(\"[Server] connection id: \", id);\n // check if id is null\n if(id == null) throw new Error(\"Connection id is null\");\n // check if connection already exists\n if(this.clients.has(id)) {\n let client = this.clients.remove(id);\n client && client.close();\n }\n // give server listeners to the connection\n // await connection.setListeners(this.listeners);\n // add connection to pool\n this.clients.add(id, connection);\n // run callback\n if(this.connectionCallback)\n this.connectionCallback(connection);\n }\n\n private handleDisconnection(socket: Socket) {\n let socketId = socket.id\n // filter every client based on the socket id\n let conn = this.clients.toArray()\n .filter((client: Connection) => client.socketId === socketId)[0];\n // cast conn as type Connection\n if(conn) {\n // close the connection\n conn.close();\n let id = conn.getTargetId();\n if(id === undefined)\n throw new Error(\"Connection id is undefined\");\n this.clients.remove(conn.getTargetId() as string);\n // run the disconnect callback\n if(this.disconnectCallback)\n this.disconnectCallback(conn);\n }\n }\n\n public setListeners(listeners: Listener[]) {\n // set the listeners on the server socket\n listeners.forEach((listener: Listener) => {\n // run the listener callback and emit the result to the client\n let callback = async ( ...args: any[] ) => {\n // run the listener callback\n let result = await listener.callback(...args);\n // emit the result to the client\n this.io.emit(listener.event, result);\n }\n // remove any previous listeners\n this.io.removeAllListeners(listener.event);\n // set the new listener\n this.io.on(listener.event, callback);\n });\n // store the listeners\n this.listeners = listeners;\n // broadcast the new listeners to all clients\n this.io.emit('_set_listeners', this.listeners);\n }\n\n public broadcast(event: string, data: any) {\n // broadcast an event to all clients\n this.io.emit(event, data);\n }\n\n public addListeners(listeners: Listener[]) {\n // add a new listener to the server\n // if we have the same event name, we will overwrite it\n const eventMap = new Map(this.listeners.map(l => [l.event, l]));\n listeners.forEach(l => eventMap.set(l.event, l));\n listeners = Array.from(eventMap.values());\n // set the listener on the server socket\n this.setListeners(this.listeners);\n }\n\n public getClient(id: string) : Connection | null {\n return this.clients.get(id);\n }\n\n public getClients() : Connection[] {\n return this.clients.toArray();\n }\n\n public onConnection(callback: any) {\n this.connectionCallback = callback;\n }\n\n public onDisconnect(callback: any) {\n this.disconnectCallback = callback;\n }\n\n public getListeners() {\n // the the listneres from the first client\n let client = this.clients.toArray()[0];\n // if client is null return an empty array\n if(!client) return [];\n // return the listeners\n return client.getListeners();\n }\n\n async close() {\n // close all sockets\n this.io.close();\n }\n\n}\n\nexport default NetworkServer;\n"],"mappings":"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","names":["import_http","Connection"]}