Skip to content

Commit 2cd1c5e

Browse files
authored
Merge pull request #55 from rramadhani14/allow-node-cluster-mode-as-default
Allow node cluster mode as default
2 parents dbdf403 + da6fe8e commit 2cd1c5e

3 files changed

Lines changed: 94 additions & 2 deletions

File tree

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55
"license": "MIT",
66
"scripts": {
77
"dev": "tsx --watch ./example/index.ts",
8-
"test": "bun run test:node",
8+
"test": "bun run test:node && bun run test:node-cluster",
99
"test:node": "npm install --prefix ./test/node/cjs/ && npm install --prefix ./test/node/esm/ && node ./test/node/cjs/index.js && node ./test/node/esm/index.js",
10+
"test:node-cluster": "node ./test/cluster/cluster.cjs port && node ./test/cluster/cluster.cjs object && node ./test/cluster/cluster.cjs true && node ./test/cluster/cluster.cjs false",
1011
"build": "bun build.ts",
1112
"release": "npm run build && npm run test && npm publish --access public"
1213
},

src/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,11 @@ export const node = () => {
107107
port: options,
108108
silent: true,
109109
websocket,
110-
fetch: app.fetch
110+
fetch: app.fetch,
111+
reusePort: true
111112
}
112113
: {
114+
reusePort: true,
113115
...options,
114116
silent: true,
115117
websocket,

test/cluster/cluster.cjs

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
const cluster = require('node:cluster')
2+
const { Elysia } = require('elysia')
3+
const { exit, pid } = require('node:process')
4+
const { node } = require('@elysiajs/node')
5+
6+
const workersAmount = 5
7+
const port = 3000
8+
// Use args to differentiate parameter
9+
// So code is more compact
10+
const arg2 = process.argv[2]
11+
let parameter
12+
if (arg2 === 'port') {
13+
parameter = port
14+
} else if (arg2 === 'object') {
15+
parameter = {
16+
port
17+
}
18+
} else if (arg2 === 'true') {
19+
parameter = {
20+
port,
21+
reusePort: true
22+
}
23+
} else if (arg2 === 'false') {
24+
parameter = {
25+
port,
26+
reusePort: false
27+
}
28+
} else {
29+
console.error(`Unknown argument: ${arg2}. Expected: port, object, true, false`)
30+
exit(1)
31+
}
32+
33+
/**
34+
* Method to stop workers and then exit the current program
35+
* @param {Worker[]} workers list of workers
36+
* @param {number} code exit code
37+
*/
38+
function shutdown(workers, code) {
39+
workers.forEach((it) => {
40+
it.kill()
41+
})
42+
exit(code)
43+
}
44+
45+
/**
46+
* Start primary node
47+
* This will create workers and then send request to primary which will then
48+
* spread the requests to the workers. After that it will check for the result.
49+
*/
50+
async function startPrimary() {
51+
let workers = []
52+
for (let i = 0; i < workersAmount; i++) {
53+
workers.push(cluster.fork())
54+
}
55+
// we need some delay to allow Elysia to initialize
56+
await new Promise((resolve) => setTimeout(resolve, 2000))
57+
58+
// Make n API calls, we should receive n different PIDs back
59+
// Checking if a server is run can only be done this way at the moment
60+
// because error is really deep in srvx and async
61+
// Even callback in Elysia.listen will be still be run even on error
62+
const promises = workers.map(async (it) => {
63+
const result = await fetch(`http://localhost:${port}`)
64+
const workerPid = await result.text()
65+
return workerPid
66+
})
67+
const result = await Promise.all(promises)
68+
const pidsCount = new Set(result).size;
69+
if (arg2 === 'false') {
70+
if (pidsCount !== 1) {
71+
console.error('❌ Server should return 1 pid.')
72+
shutdown(workers, 1)
73+
}
74+
console.log('✅ Test exclusive mode succeed!')
75+
shutdown(workers, 0)
76+
}
77+
if (pidsCount !== workersAmount) {
78+
console.error("❌ Clustering error, number of pids doesn't match.")
79+
shutdown(workers, 1)
80+
}
81+
console.log('✅ Test cluster mode succeed!')
82+
shutdown(workers, 0)
83+
}
84+
85+
if (cluster.isPrimary) {
86+
startPrimary()
87+
} else {
88+
new Elysia({ adapter: node() }).get(`/`, pid).listen(parameter)
89+
}

0 commit comments

Comments
 (0)