@nxtedition/lib 26.0.28 → 26.0.29
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/app.js +60 -1
- package/package.json +2 -1
package/app.js
CHANGED
|
@@ -38,6 +38,8 @@ import makeUnderPressure from './under-pressure.js'
|
|
|
38
38
|
import undici from '@nxtedition/undici'
|
|
39
39
|
import { isPrimary } from 'node:cluster'
|
|
40
40
|
import { nice } from '@napi-rs/nice'
|
|
41
|
+
import path from 'node:path'
|
|
42
|
+
import { sched_getaffinity, sched_setaffinity } from '@nxtedition/sched'
|
|
41
43
|
|
|
42
44
|
export function makeApp(appConfig, onTerminate) {
|
|
43
45
|
let ds
|
|
@@ -124,13 +126,17 @@ export function makeApp(appConfig, onTerminate) {
|
|
|
124
126
|
const appDestroyers = []
|
|
125
127
|
|
|
126
128
|
const serviceName = appConfig.name
|
|
127
|
-
const serviceModule = appConfig.module ?? 'main'
|
|
128
129
|
const serviceVersion = appConfig.version
|
|
130
|
+
const serviceModule = appConfig.module ?? 'main'
|
|
129
131
|
const serviceWorkerId = appConfig.workerId ?? threadId
|
|
130
132
|
const serviceInstanceId =
|
|
131
133
|
// process.env.name is the pm2 name of the process
|
|
132
134
|
appConfig.instanceId ?? appConfig.containerId ?? process.env.name ?? os.hostname()
|
|
133
135
|
|
|
136
|
+
if (!serviceName) {
|
|
137
|
+
throw new Error('Service name is required')
|
|
138
|
+
}
|
|
139
|
+
|
|
134
140
|
const userAgent = (globalThis.userAgent =
|
|
135
141
|
appConfig.userAgent ??
|
|
136
142
|
(serviceName &&
|
|
@@ -310,6 +316,58 @@ export function makeApp(appConfig, onTerminate) {
|
|
|
310
316
|
}
|
|
311
317
|
}
|
|
312
318
|
|
|
319
|
+
let affinity = null
|
|
320
|
+
if (isMainThread && appConfig.affinity !== false && process.platform === 'linux') {
|
|
321
|
+
const allNodes = []
|
|
322
|
+
for (const entry of fs.readdirSync('/sys/devices/system/node')) {
|
|
323
|
+
if (!entry.startsWith('node')) {
|
|
324
|
+
continue
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
const cpulist = fs
|
|
328
|
+
.readFileSync(path.join('/sys/devices/system/node', entry, 'cpulist'), 'utf8')
|
|
329
|
+
.trim()
|
|
330
|
+
const cpus = []
|
|
331
|
+
for (const part of cpulist.split(',')) {
|
|
332
|
+
if (part.includes('-')) {
|
|
333
|
+
const [start, end] = part.split('-').map(Number)
|
|
334
|
+
for (let i = start; i <= end; i++) {
|
|
335
|
+
cpus.push(i)
|
|
336
|
+
}
|
|
337
|
+
} else {
|
|
338
|
+
cpus.push(Number(part))
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
allNodes.push(cpus)
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
if (Number.isInteger(appConfig.affinity) && appConfig.affinity >= 0) {
|
|
345
|
+
affinity = allNodes[appConfig.affinity % allNodes.length]
|
|
346
|
+
} else if (appConfig.affinity == null) {
|
|
347
|
+
affinity = allNodes[hashString(serviceName) % allNodes.length]
|
|
348
|
+
} else {
|
|
349
|
+
throw new Error('invalid affinity configuration: ' + appConfig.affinity)
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
affinity = fp.uniq(affinity)
|
|
353
|
+
affinity = fp.intersection(affinity, sched_getaffinity(0))
|
|
354
|
+
|
|
355
|
+
if (
|
|
356
|
+
!Array.isArray(affinity) ||
|
|
357
|
+
affinity.length === 0 ||
|
|
358
|
+
affinity.some((x) => typeof x !== 'number' || x < 0)
|
|
359
|
+
) {
|
|
360
|
+
throw new Error('invalid affinity configuration: ' + appConfig.affinity)
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
try {
|
|
364
|
+
sched_setaffinity(0, affinity)
|
|
365
|
+
logger.debug({ data: { value: appConfig.affinity, affinity } }, 'sched_setaffinity succeeded')
|
|
366
|
+
} catch (err) {
|
|
367
|
+
logger.error({ err }, 'sched_setaffinity failed')
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
313
371
|
if (appConfig.toobusy) {
|
|
314
372
|
const resolution = appConfig.toobusy.resolution ?? 10
|
|
315
373
|
const interval = appConfig.toobusy.interval ?? 500
|
|
@@ -1275,5 +1333,6 @@ export function makeApp(appConfig, onTerminate) {
|
|
|
1275
1333
|
serviceInstanceId,
|
|
1276
1334
|
serviceWorkerId,
|
|
1277
1335
|
signal: ac.signal,
|
|
1336
|
+
affinity,
|
|
1278
1337
|
})
|
|
1279
1338
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nxtedition/lib",
|
|
3
|
-
"version": "26.0.
|
|
3
|
+
"version": "26.0.29",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "Robert Nagy <robert.nagy@boffins.se>",
|
|
6
6
|
"type": "module",
|
|
@@ -68,6 +68,7 @@
|
|
|
68
68
|
"@elastic/transport": "^8.9.3",
|
|
69
69
|
"@napi-rs/nice": "^1.1.1",
|
|
70
70
|
"@nxtedition/nxt-undici": "^6.4.0",
|
|
71
|
+
"@nxtedition/sched": "^1.0.1",
|
|
71
72
|
"@smithy/node-http-handler": "^4.1.1",
|
|
72
73
|
"acorn": "^8.15.0",
|
|
73
74
|
"astring": "^1.9.0",
|