@colyseus/tools 0.16.8 → 0.16.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/index.js +10 -6
- package/build/index.js.map +2 -2
- package/build/index.mjs +10 -13
- package/build/index.mjs.map +2 -2
- package/package.json +6 -3
- package/system-boot.js +31 -22
package/build/index.js
CHANGED
|
@@ -42,7 +42,13 @@ var import_express = __toESM(require("express"));
|
|
|
42
42
|
var import_core = require("@colyseus/core");
|
|
43
43
|
var import_ws_transport = require("@colyseus/ws-transport");
|
|
44
44
|
let BunWebSockets = void 0;
|
|
45
|
-
import("@colyseus/bun-websockets").then((module2) => BunWebSockets = module2).catch(() => {
|
|
45
|
+
import("@colyseus/bun-websockets").then((module2) => BunWebSockets = module2.BunWebSockets).catch(() => {
|
|
46
|
+
});
|
|
47
|
+
let RedisDriver;
|
|
48
|
+
import("@colyseus/redis-driver").then((module2) => RedisDriver = module2.RedisDriver).catch(() => {
|
|
49
|
+
});
|
|
50
|
+
let RedisPresence;
|
|
51
|
+
import("@colyseus/redis-presence").then((module2) => RedisPresence = module2.RedisPresence).catch(() => {
|
|
46
52
|
});
|
|
47
53
|
const ALLOWED_KEYS = {
|
|
48
54
|
"displayLogs": "boolean",
|
|
@@ -102,11 +108,10 @@ async function buildServerFromOptions(options, port) {
|
|
|
102
108
|
if (process.env.COLYSEUS_CLOUD !== void 0) {
|
|
103
109
|
const useRedisConfig = import_os.default.cpus().length > 1 || process.env.REDIS_URI !== void 0;
|
|
104
110
|
if (!serverOptions.driver && useRedisConfig) {
|
|
105
|
-
let RedisDriver = void 0;
|
|
106
111
|
try {
|
|
107
|
-
RedisDriver = require("@colyseus/redis-driver").RedisDriver;
|
|
108
112
|
serverOptions.driver = new RedisDriver(process.env.REDIS_URI);
|
|
109
113
|
} catch (e) {
|
|
114
|
+
console.error(e);
|
|
110
115
|
import_core.logger.warn("");
|
|
111
116
|
import_core.logger.warn("\u274C could not initialize RedisDriver.");
|
|
112
117
|
import_core.logger.warn("\u{1F449} npm install --save @colyseus/redis-driver");
|
|
@@ -114,11 +119,10 @@ async function buildServerFromOptions(options, port) {
|
|
|
114
119
|
}
|
|
115
120
|
}
|
|
116
121
|
if (!serverOptions.presence && useRedisConfig) {
|
|
117
|
-
let RedisPresence = void 0;
|
|
118
122
|
try {
|
|
119
|
-
RedisPresence = require("@colyseus/redis-presence").RedisPresence;
|
|
120
123
|
serverOptions.presence = new RedisPresence(process.env.REDIS_URI);
|
|
121
124
|
} catch (e) {
|
|
125
|
+
console.error(e);
|
|
122
126
|
import_core.logger.warn("");
|
|
123
127
|
import_core.logger.warn("\u274C could not initialize RedisPresence.");
|
|
124
128
|
import_core.logger.warn("\u{1F449} npm install --save @colyseus/redis-presence");
|
|
@@ -140,7 +144,7 @@ async function getTransport(options) {
|
|
|
140
144
|
let transport;
|
|
141
145
|
if (!options.initializeTransport) {
|
|
142
146
|
if (BunWebSockets !== void 0) {
|
|
143
|
-
options.initializeTransport = (options2) => new BunWebSockets
|
|
147
|
+
options.initializeTransport = (options2) => new BunWebSockets(options2);
|
|
144
148
|
} else {
|
|
145
149
|
options.initializeTransport = (options2) => new import_ws_transport.WebSocketTransport(options2);
|
|
146
150
|
}
|
package/build/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/index.ts"],
|
|
4
|
-
"sourcesContent": ["import './loadenv.js';\nimport os from 'os';\nimport fs from \"fs\";\nimport net from \"net\";\nimport http from 'http';\nimport cors from 'cors';\nimport express from 'express';\nimport { logger, Server, ServerOptions, Transport, matchMaker } from '@colyseus/core';\nimport { WebSocketTransport } from '@colyseus/ws-transport';\n\nlet BunWebSockets:
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAAO;AACP,gBAAe;AACf,gBAAe;AACf,iBAAgB;AAChB,kBAAiB;AACjB,kBAAiB;AACjB,qBAAoB;AACpB,kBAAqE;AACrE,0BAAmC;
|
|
4
|
+
"sourcesContent": ["import './loadenv.js';\nimport os from 'os';\nimport fs from \"fs\";\nimport net from \"net\";\nimport http from 'http';\nimport cors from 'cors';\nimport express from 'express';\nimport { logger, Server, ServerOptions, Transport, matchMaker } from '@colyseus/core';\nimport { WebSocketTransport } from '@colyseus/ws-transport';\n\nimport { type BunWebSockets as TBunWebSockets } from '@colyseus/bun-websockets';\nimport { type RedisDriver as TRedisDriver } from '@colyseus/redis-driver';\nimport { type RedisPresence as TRedisPresence } from '@colyseus/redis-presence';\n\nlet BunWebSockets: typeof TBunWebSockets = undefined;\nimport('@colyseus/bun-websockets').then((module) => BunWebSockets = module.BunWebSockets).catch(() => { });\n\nlet RedisDriver: typeof TRedisDriver;\nimport('@colyseus/redis-driver').then((module) => RedisDriver = module.RedisDriver).catch(() => { });\n\nlet RedisPresence: typeof TRedisPresence;\nimport('@colyseus/redis-presence').then((module) => RedisPresence = module.RedisPresence).catch(() => { });\n\nexport interface ConfigOptions {\n options?: ServerOptions,\n displayLogs?: boolean,\n getId?: () => string,\n initializeTransport?: (options: any) => Transport,\n initializeExpress?: (app: express.Express) => void,\n initializeGameServer?: (app: Server) => void,\n beforeListen?: () => void,\n}\n\nconst ALLOWED_KEYS: { [key in keyof ConfigOptions]: string } = {\n 'displayLogs': \"boolean\",\n 'options': \"object\",\n 'getId': \"function\",\n 'initializeTransport': \"function\",\n 'initializeExpress': \"function\",\n 'initializeGameServer': \"function\",\n 'beforeListen': \"function\"\n};\n\nexport default function (options: ConfigOptions) {\n for (const option in options) {\n if (!ALLOWED_KEYS[option]) {\n throw new Error(`\u274C Invalid option '${option}'. Allowed options are: ${Object.keys(ALLOWED_KEYS).join(\", \")}`);\n }\n if(options[option] !== undefined && typeof(options[option]) !== ALLOWED_KEYS[option]) {\n throw new Error(`\u274C Invalid type for ${option}: please provide a ${ALLOWED_KEYS[option]} value.`);\n }\n }\n\n return options;\n}\n\n/**\n * Listen on your development environment\n * @param options Application options\n * @param port Port number to bind Colyseus + Express\n */\nexport async function listen(\n options: ConfigOptions | Server,\n port: number = Number(process.env.PORT || 2567),\n) {\n // Force 2567 port on Colyseus Cloud\n if (process.env.COLYSEUS_CLOUD !== undefined) {\n port = 2567;\n }\n\n //\n // Handling multiple processes\n // Use NODE_APP_INSTANCE to play nicely with pm2\n //\n const processNumber = Number(process.env.NODE_APP_INSTANCE || \"0\");\n port += processNumber;\n\n let gameServer: Server;\n let displayLogs = true;\n\n if (options instanceof Server) {\n gameServer = options;\n\n } else {\n gameServer = await buildServerFromOptions(options, port);\n displayLogs = options.displayLogs;\n\n await options.initializeGameServer?.(gameServer);\n await matchMaker.onReady;\n await options.beforeListen?.();\n }\n\n if (process.env.COLYSEUS_CLOUD !== undefined) {\n // listening on socket\n const socketPath: any = `/run/colyseus/${port}.sock`;\n\n // check if .sock file is active\n // (fixes \"ADDRINUSE\" issue when restarting the server)\n await checkInactiveSocketFile(socketPath);\n\n await gameServer.listen(socketPath);\n\n } else {\n // listening on port\n await gameServer.listen(port);\n }\n\n // notify process manager (production)\n if (typeof(process.send) === \"function\") {\n process.send('ready');\n }\n\n if (displayLogs) {\n logger.info(`\u2694\uFE0F Listening on http://localhost:${port}`);\n }\n\n return gameServer;\n}\n\nasync function buildServerFromOptions(options: ConfigOptions, port: number) {\n const serverOptions = options.options || {};\n options.displayLogs = options.displayLogs ?? true;\n\n // automatically configure for production under Colyseus Cloud\n if (process.env.COLYSEUS_CLOUD !== undefined) {\n\n // special configuration is required when using multiple processes\n const useRedisConfig = (os.cpus().length > 1) || (process.env.REDIS_URI !== undefined);\n\n if (!serverOptions.driver && useRedisConfig) {\n try {\n serverOptions.driver = new RedisDriver(process.env.REDIS_URI);\n } catch (e) {\n console.error(e);\n logger.warn(\"\");\n logger.warn(\"\u274C could not initialize RedisDriver.\");\n logger.warn(\"\uD83D\uDC49 npm install --save @colyseus/redis-driver\");\n logger.warn(\"\");\n }\n }\n\n if (!serverOptions.presence && useRedisConfig) {\n try {\n serverOptions.presence = new RedisPresence(process.env.REDIS_URI);\n } catch (e) {\n console.error(e);\n logger.warn(\"\");\n logger.warn(\"\u274C could not initialize RedisPresence.\");\n logger.warn(\"\uD83D\uDC49 npm install --save @colyseus/redis-presence\");\n logger.warn(\"\");\n }\n }\n\n if (useRedisConfig) {\n // force \"publicAddress\" when more than 1 process is available\n serverOptions.publicAddress = process.env.SUBDOMAIN + \".\" + process.env.SERVER_NAME;\n\n // nginx is responsible for forwarding /{port}/ to this process\n serverOptions.publicAddress += \"/\" + port;\n }\n }\n\n const transport = await getTransport(options);\n return new Server({\n ...serverOptions,\n transport,\n });\n}\n\nexport async function getTransport(options: ConfigOptions) {\n let transport: Transport;\n\n if (!options.initializeTransport) {\n if (BunWebSockets !== undefined) {\n // @colyseus/bun-websockets\n options.initializeTransport = (options: any) => new BunWebSockets(options);\n\n } else {\n // use WebSocketTransport by default\n options.initializeTransport = (options: any) => new WebSocketTransport(options);\n }\n }\n\n let app: express.Express | undefined = express();\n let server = http.createServer(app);\n\n transport = await options.initializeTransport({ server, app });\n\n //\n // TODO: refactor me!\n // BunWebSockets: There's no need to instantiate \"app\" and \"server\" above\n //\n if (transport['expressApp']) {\n app = transport['expressApp'];\n }\n\n if (app) {\n // Enable CORS\n app.use(cors({ origin: true, credentials: true, }));\n\n // Enable JSON parsing.\n app.use(express.json());\n\n if (options.initializeExpress) {\n await options.initializeExpress(app);\n }\n\n // health check for load balancers\n app.get(\"/__healthcheck\", (req, res) => {\n res.status(200).end();\n });\n\n if (options.displayLogs) {\n logger.info(\"\u2705 Express initialized\");\n }\n }\n\n return transport;\n}\n\n/**\n * Check if a socket file is active and remove it if it's not.\n */\nfunction checkInactiveSocketFile(sockFilePath: string) {\n return new Promise((resolve, reject) => {\n const client = net.createConnection({ path: sockFilePath })\n .on('connect', () => {\n // socket file is active, close the connection\n client.end();\n throw new Error(`EADDRINUSE: Already listening on '${sockFilePath}'`);\n })\n .on('error', () => {\n // socket file is inactive, remove it\n fs.unlink(sockFilePath, () => resolve(true));\n });\n });\n}"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["module", "os", "options", "express", "http", "cors", "net", "fs"]
|
|
7
7
|
}
|
package/build/index.mjs
CHANGED
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
-
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
-
}) : x)(function(x) {
|
|
4
|
-
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
|
-
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
|
-
});
|
|
7
|
-
|
|
8
1
|
// packages/tools/src/index.ts
|
|
9
2
|
import "./loadenv.mjs";
|
|
10
3
|
import os from "os";
|
|
@@ -16,7 +9,13 @@ import express from "express";
|
|
|
16
9
|
import { logger, Server, matchMaker } from "@colyseus/core";
|
|
17
10
|
import { WebSocketTransport } from "@colyseus/ws-transport";
|
|
18
11
|
var BunWebSockets = void 0;
|
|
19
|
-
import("@colyseus/bun-websockets").then((module) => BunWebSockets = module).catch(() => {
|
|
12
|
+
import("@colyseus/bun-websockets").then((module) => BunWebSockets = module.BunWebSockets).catch(() => {
|
|
13
|
+
});
|
|
14
|
+
var RedisDriver;
|
|
15
|
+
import("@colyseus/redis-driver").then((module) => RedisDriver = module.RedisDriver).catch(() => {
|
|
16
|
+
});
|
|
17
|
+
var RedisPresence;
|
|
18
|
+
import("@colyseus/redis-presence").then((module) => RedisPresence = module.RedisPresence).catch(() => {
|
|
20
19
|
});
|
|
21
20
|
var ALLOWED_KEYS = {
|
|
22
21
|
"displayLogs": "boolean",
|
|
@@ -76,11 +75,10 @@ async function buildServerFromOptions(options, port) {
|
|
|
76
75
|
if (process.env.COLYSEUS_CLOUD !== void 0) {
|
|
77
76
|
const useRedisConfig = os.cpus().length > 1 || process.env.REDIS_URI !== void 0;
|
|
78
77
|
if (!serverOptions.driver && useRedisConfig) {
|
|
79
|
-
let RedisDriver = void 0;
|
|
80
78
|
try {
|
|
81
|
-
RedisDriver = __require("@colyseus/redis-driver").RedisDriver;
|
|
82
79
|
serverOptions.driver = new RedisDriver(process.env.REDIS_URI);
|
|
83
80
|
} catch (e) {
|
|
81
|
+
console.error(e);
|
|
84
82
|
logger.warn("");
|
|
85
83
|
logger.warn("\u274C could not initialize RedisDriver.");
|
|
86
84
|
logger.warn("\u{1F449} npm install --save @colyseus/redis-driver");
|
|
@@ -88,11 +86,10 @@ async function buildServerFromOptions(options, port) {
|
|
|
88
86
|
}
|
|
89
87
|
}
|
|
90
88
|
if (!serverOptions.presence && useRedisConfig) {
|
|
91
|
-
let RedisPresence = void 0;
|
|
92
89
|
try {
|
|
93
|
-
RedisPresence = __require("@colyseus/redis-presence").RedisPresence;
|
|
94
90
|
serverOptions.presence = new RedisPresence(process.env.REDIS_URI);
|
|
95
91
|
} catch (e) {
|
|
92
|
+
console.error(e);
|
|
96
93
|
logger.warn("");
|
|
97
94
|
logger.warn("\u274C could not initialize RedisPresence.");
|
|
98
95
|
logger.warn("\u{1F449} npm install --save @colyseus/redis-presence");
|
|
@@ -114,7 +111,7 @@ async function getTransport(options) {
|
|
|
114
111
|
let transport;
|
|
115
112
|
if (!options.initializeTransport) {
|
|
116
113
|
if (BunWebSockets !== void 0) {
|
|
117
|
-
options.initializeTransport = (options2) => new BunWebSockets
|
|
114
|
+
options.initializeTransport = (options2) => new BunWebSockets(options2);
|
|
118
115
|
} else {
|
|
119
116
|
options.initializeTransport = (options2) => new WebSocketTransport(options2);
|
|
120
117
|
}
|
package/build/index.mjs.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/index.ts"],
|
|
4
|
-
"sourcesContent": ["import './loadenv.js';\nimport os from 'os';\nimport fs from \"fs\";\nimport net from \"net\";\nimport http from 'http';\nimport cors from 'cors';\nimport express from 'express';\nimport { logger, Server, ServerOptions, Transport, matchMaker } from '@colyseus/core';\nimport { WebSocketTransport } from '@colyseus/ws-transport';\n\nlet BunWebSockets:
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["import './loadenv.js';\nimport os from 'os';\nimport fs from \"fs\";\nimport net from \"net\";\nimport http from 'http';\nimport cors from 'cors';\nimport express from 'express';\nimport { logger, Server, ServerOptions, Transport, matchMaker } from '@colyseus/core';\nimport { WebSocketTransport } from '@colyseus/ws-transport';\n\nimport { type BunWebSockets as TBunWebSockets } from '@colyseus/bun-websockets';\nimport { type RedisDriver as TRedisDriver } from '@colyseus/redis-driver';\nimport { type RedisPresence as TRedisPresence } from '@colyseus/redis-presence';\n\nlet BunWebSockets: typeof TBunWebSockets = undefined;\nimport('@colyseus/bun-websockets').then((module) => BunWebSockets = module.BunWebSockets).catch(() => { });\n\nlet RedisDriver: typeof TRedisDriver;\nimport('@colyseus/redis-driver').then((module) => RedisDriver = module.RedisDriver).catch(() => { });\n\nlet RedisPresence: typeof TRedisPresence;\nimport('@colyseus/redis-presence').then((module) => RedisPresence = module.RedisPresence).catch(() => { });\n\nexport interface ConfigOptions {\n options?: ServerOptions,\n displayLogs?: boolean,\n getId?: () => string,\n initializeTransport?: (options: any) => Transport,\n initializeExpress?: (app: express.Express) => void,\n initializeGameServer?: (app: Server) => void,\n beforeListen?: () => void,\n}\n\nconst ALLOWED_KEYS: { [key in keyof ConfigOptions]: string } = {\n 'displayLogs': \"boolean\",\n 'options': \"object\",\n 'getId': \"function\",\n 'initializeTransport': \"function\",\n 'initializeExpress': \"function\",\n 'initializeGameServer': \"function\",\n 'beforeListen': \"function\"\n};\n\nexport default function (options: ConfigOptions) {\n for (const option in options) {\n if (!ALLOWED_KEYS[option]) {\n throw new Error(`\u274C Invalid option '${option}'. Allowed options are: ${Object.keys(ALLOWED_KEYS).join(\", \")}`);\n }\n if(options[option] !== undefined && typeof(options[option]) !== ALLOWED_KEYS[option]) {\n throw new Error(`\u274C Invalid type for ${option}: please provide a ${ALLOWED_KEYS[option]} value.`);\n }\n }\n\n return options;\n}\n\n/**\n * Listen on your development environment\n * @param options Application options\n * @param port Port number to bind Colyseus + Express\n */\nexport async function listen(\n options: ConfigOptions | Server,\n port: number = Number(process.env.PORT || 2567),\n) {\n // Force 2567 port on Colyseus Cloud\n if (process.env.COLYSEUS_CLOUD !== undefined) {\n port = 2567;\n }\n\n //\n // Handling multiple processes\n // Use NODE_APP_INSTANCE to play nicely with pm2\n //\n const processNumber = Number(process.env.NODE_APP_INSTANCE || \"0\");\n port += processNumber;\n\n let gameServer: Server;\n let displayLogs = true;\n\n if (options instanceof Server) {\n gameServer = options;\n\n } else {\n gameServer = await buildServerFromOptions(options, port);\n displayLogs = options.displayLogs;\n\n await options.initializeGameServer?.(gameServer);\n await matchMaker.onReady;\n await options.beforeListen?.();\n }\n\n if (process.env.COLYSEUS_CLOUD !== undefined) {\n // listening on socket\n const socketPath: any = `/run/colyseus/${port}.sock`;\n\n // check if .sock file is active\n // (fixes \"ADDRINUSE\" issue when restarting the server)\n await checkInactiveSocketFile(socketPath);\n\n await gameServer.listen(socketPath);\n\n } else {\n // listening on port\n await gameServer.listen(port);\n }\n\n // notify process manager (production)\n if (typeof(process.send) === \"function\") {\n process.send('ready');\n }\n\n if (displayLogs) {\n logger.info(`\u2694\uFE0F Listening on http://localhost:${port}`);\n }\n\n return gameServer;\n}\n\nasync function buildServerFromOptions(options: ConfigOptions, port: number) {\n const serverOptions = options.options || {};\n options.displayLogs = options.displayLogs ?? true;\n\n // automatically configure for production under Colyseus Cloud\n if (process.env.COLYSEUS_CLOUD !== undefined) {\n\n // special configuration is required when using multiple processes\n const useRedisConfig = (os.cpus().length > 1) || (process.env.REDIS_URI !== undefined);\n\n if (!serverOptions.driver && useRedisConfig) {\n try {\n serverOptions.driver = new RedisDriver(process.env.REDIS_URI);\n } catch (e) {\n console.error(e);\n logger.warn(\"\");\n logger.warn(\"\u274C could not initialize RedisDriver.\");\n logger.warn(\"\uD83D\uDC49 npm install --save @colyseus/redis-driver\");\n logger.warn(\"\");\n }\n }\n\n if (!serverOptions.presence && useRedisConfig) {\n try {\n serverOptions.presence = new RedisPresence(process.env.REDIS_URI);\n } catch (e) {\n console.error(e);\n logger.warn(\"\");\n logger.warn(\"\u274C could not initialize RedisPresence.\");\n logger.warn(\"\uD83D\uDC49 npm install --save @colyseus/redis-presence\");\n logger.warn(\"\");\n }\n }\n\n if (useRedisConfig) {\n // force \"publicAddress\" when more than 1 process is available\n serverOptions.publicAddress = process.env.SUBDOMAIN + \".\" + process.env.SERVER_NAME;\n\n // nginx is responsible for forwarding /{port}/ to this process\n serverOptions.publicAddress += \"/\" + port;\n }\n }\n\n const transport = await getTransport(options);\n return new Server({\n ...serverOptions,\n transport,\n });\n}\n\nexport async function getTransport(options: ConfigOptions) {\n let transport: Transport;\n\n if (!options.initializeTransport) {\n if (BunWebSockets !== undefined) {\n // @colyseus/bun-websockets\n options.initializeTransport = (options: any) => new BunWebSockets(options);\n\n } else {\n // use WebSocketTransport by default\n options.initializeTransport = (options: any) => new WebSocketTransport(options);\n }\n }\n\n let app: express.Express | undefined = express();\n let server = http.createServer(app);\n\n transport = await options.initializeTransport({ server, app });\n\n //\n // TODO: refactor me!\n // BunWebSockets: There's no need to instantiate \"app\" and \"server\" above\n //\n if (transport['expressApp']) {\n app = transport['expressApp'];\n }\n\n if (app) {\n // Enable CORS\n app.use(cors({ origin: true, credentials: true, }));\n\n // Enable JSON parsing.\n app.use(express.json());\n\n if (options.initializeExpress) {\n await options.initializeExpress(app);\n }\n\n // health check for load balancers\n app.get(\"/__healthcheck\", (req, res) => {\n res.status(200).end();\n });\n\n if (options.displayLogs) {\n logger.info(\"\u2705 Express initialized\");\n }\n }\n\n return transport;\n}\n\n/**\n * Check if a socket file is active and remove it if it's not.\n */\nfunction checkInactiveSocketFile(sockFilePath: string) {\n return new Promise((resolve, reject) => {\n const client = net.createConnection({ path: sockFilePath })\n .on('connect', () => {\n // socket file is active, close the connection\n client.end();\n throw new Error(`EADDRINUSE: Already listening on '${sockFilePath}'`);\n })\n .on('error', () => {\n // socket file is inactive, remove it\n fs.unlink(sockFilePath, () => resolve(true));\n });\n });\n}"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["options"]
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@colyseus/tools",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.10",
|
|
4
4
|
"description": "Simplify the development and production settings for your Colyseus project.",
|
|
5
5
|
"input": "./src/index.ts",
|
|
6
6
|
"main": "./build/index.js",
|
|
@@ -50,9 +50,12 @@
|
|
|
50
50
|
"@types/cors": "^2.8.10",
|
|
51
51
|
"@types/dotenv": "^8.2.0",
|
|
52
52
|
"uwebsockets-express": "^1.1.10",
|
|
53
|
-
"@colyseus/
|
|
53
|
+
"@colyseus/bun-websockets": "^0.16.4",
|
|
54
|
+
"@colyseus/redis-driver": "^0.16.1",
|
|
54
55
|
"@colyseus/ws-transport": "^0.16.5",
|
|
55
|
-
"@colyseus/
|
|
56
|
+
"@colyseus/core": "^0.16.18",
|
|
57
|
+
"@colyseus/uwebsockets-transport": "^0.16.9",
|
|
58
|
+
"@colyseus/redis-presence": "^0.16.3"
|
|
56
59
|
},
|
|
57
60
|
"peerDependencies": {
|
|
58
61
|
"@colyseus/core": "0.16.x",
|
package/system-boot.js
CHANGED
|
@@ -6,57 +6,63 @@ const { execSync } = require('child_process');
|
|
|
6
6
|
|
|
7
7
|
const NGINX_LIMITS_CONFIG_FILE = '/etc/nginx/colyseus_limits.conf';
|
|
8
8
|
const LIMITS_CONF_FILE = '/etc/security/limits.d/colyseus.conf';
|
|
9
|
-
const SYSCTL_FILE = '/etc/sysctl.d/local.conf'
|
|
9
|
+
const SYSCTL_FILE = '/etc/sysctl.d/local.conf';
|
|
10
10
|
|
|
11
|
-
const MAX_CCU_PER_CPU =
|
|
11
|
+
const MAX_CCU_PER_CPU = 5000;
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* System-wide limits configuration for high-CCU environments
|
|
15
15
|
* @param {Object} options
|
|
16
16
|
* @param {number} options.maxCCUPerCPU - Maximum concurrent users per CPU core
|
|
17
|
-
* @param {number} options.connectionsMultiplier - Multiplier for worker connections (default:
|
|
18
|
-
* @param {number} options.fileDescriptorMultiplier - Multiplier for max file descriptors (default:
|
|
17
|
+
* @param {number} options.connectionsMultiplier - Multiplier for worker connections (default: 2)
|
|
18
|
+
* @param {number} options.fileDescriptorMultiplier - Multiplier for max file descriptors (default: 6)
|
|
19
19
|
*/
|
|
20
20
|
function configureSystemLimits(options = {}) {
|
|
21
21
|
const {
|
|
22
|
-
connectionsMultiplier =
|
|
23
|
-
fileDescriptorMultiplier =
|
|
22
|
+
connectionsMultiplier = 2,
|
|
23
|
+
fileDescriptorMultiplier = 6
|
|
24
24
|
} = options;
|
|
25
25
|
|
|
26
26
|
const numCPU = os.cpus().length;
|
|
27
27
|
const maxCCU = numCPU * MAX_CCU_PER_CPU;
|
|
28
28
|
|
|
29
29
|
// Calculate limits
|
|
30
|
-
const workerConnections = maxCCU * connectionsMultiplier;
|
|
31
|
-
|
|
30
|
+
const workerConnections = Math.min(maxCCU * connectionsMultiplier, 65535); // Cap at max_socket_backlog (65535)
|
|
31
|
+
let maxFileDescriptors = maxCCU * fileDescriptorMultiplier;
|
|
32
|
+
const workerRlimitNofile = Math.ceil(workerConnections * 3.5); // Assume 3.5 file descriptors per connection for safety
|
|
32
33
|
|
|
33
|
-
//
|
|
34
|
-
const
|
|
34
|
+
// Calculate total file descriptors needed
|
|
35
|
+
const totalFileDescriptors = workerRlimitNofile * numCPU;
|
|
35
36
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
if (totalFileDescriptors > maxFileDescriptors) {
|
|
38
|
+
console.warn(`Warning: Total file descriptors (${totalFileDescriptors}) exceeds maxFileDescriptors (${maxFileDescriptors}). Increasing maxFileDescriptors.`);
|
|
39
|
+
maxFileDescriptors = totalFileDescriptors * 1.5; // 50% safety margin
|
|
39
40
|
}
|
|
40
41
|
|
|
41
|
-
|
|
42
|
-
|
|
42
|
+
// Check memory (rough estimate: 150 KB per connection)
|
|
43
|
+
const estimatedMemoryMB = (workerConnections * numCPU * 150) / 1024;
|
|
44
|
+
const totalMemoryMB = Number(execSync('free -m | awk \'/Mem:/ {print $2}\'').toString().trim());
|
|
45
|
+
if (estimatedMemoryMB > totalMemoryMB * 0.8) {
|
|
46
|
+
console.warn(`Warning: Estimated memory usage (${estimatedMemoryMB} MB) exceeds 80% of available memory (${totalMemoryMB} MB). Consider reducing MAX_CCU_PER_CPU.`);
|
|
43
47
|
}
|
|
44
48
|
|
|
45
49
|
if (process.argv.includes('--dry-run')) {
|
|
46
50
|
console.log({
|
|
51
|
+
numCPU,
|
|
47
52
|
maxCCU,
|
|
48
53
|
workerConnections,
|
|
49
54
|
maxFileDescriptors,
|
|
50
|
-
workerRlimitNofile
|
|
51
|
-
|
|
55
|
+
workerRlimitNofile,
|
|
56
|
+
totalFileDescriptors,
|
|
57
|
+
estimatedMemoryMB
|
|
58
|
+
});
|
|
52
59
|
process.exit();
|
|
53
60
|
}
|
|
54
61
|
|
|
55
62
|
// Configuration updates
|
|
56
63
|
try {
|
|
57
64
|
// Update Nginx limits
|
|
58
|
-
|
|
59
|
-
fs.writeFileSync(NGINX_LIMITS_CONFIG_FILE, `
|
|
65
|
+
fs.writeFileSync(NGINX_LIMITS_CONFIG_FILE, `
|
|
60
66
|
worker_rlimit_nofile ${workerRlimitNofile};
|
|
61
67
|
events {
|
|
62
68
|
use epoll;
|
|
@@ -64,7 +70,6 @@ events {
|
|
|
64
70
|
multi_accept on;
|
|
65
71
|
}
|
|
66
72
|
`);
|
|
67
|
-
}
|
|
68
73
|
|
|
69
74
|
// Update system-wide limits
|
|
70
75
|
fs.writeFileSync(LIMITS_CONF_FILE, `
|
|
@@ -74,7 +79,7 @@ nginx soft nofile ${maxFileDescriptors}
|
|
|
74
79
|
nginx hard nofile ${maxFileDescriptors}
|
|
75
80
|
`);
|
|
76
81
|
|
|
77
|
-
// Update sysctl
|
|
82
|
+
// Update sysctl
|
|
78
83
|
fs.writeFileSync(SYSCTL_FILE, `
|
|
79
84
|
# System-wide file descriptor limit
|
|
80
85
|
fs.file-max = ${maxFileDescriptors * 2}
|
|
@@ -99,7 +104,11 @@ net.ipv4.tcp_keepalive_probes = 3
|
|
|
99
104
|
`);
|
|
100
105
|
|
|
101
106
|
// Apply sysctl changes
|
|
102
|
-
execSync(
|
|
107
|
+
execSync('sysctl -p', { stdio: 'inherit' });
|
|
108
|
+
|
|
109
|
+
// Reload systemd
|
|
110
|
+
execSync('systemctl daemon-reload', { stdio: 'inherit' });
|
|
111
|
+
|
|
103
112
|
console.log(`System limits configured successfully for ${maxCCU} CCU (${MAX_CCU_PER_CPU}/CPU)`);
|
|
104
113
|
|
|
105
114
|
} catch (error) {
|