@nxtedition/lib 26.0.28 → 26.0.30
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 +64 -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,62 @@ export function makeApp(appConfig, onTerminate) {
|
|
|
310
316
|
}
|
|
311
317
|
}
|
|
312
318
|
|
|
319
|
+
let affinity = null
|
|
320
|
+
if (
|
|
321
|
+
process.platform === 'linux' &&
|
|
322
|
+
(isMainThread || appConfig.affinity != null) &&
|
|
323
|
+
appConfig.affinity !== false
|
|
324
|
+
) {
|
|
325
|
+
const allNodes = []
|
|
326
|
+
for (const entry of fs.readdirSync('/sys/devices/system/node')) {
|
|
327
|
+
if (!entry.startsWith('node')) {
|
|
328
|
+
continue
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
const cpulist = fs
|
|
332
|
+
.readFileSync(path.join('/sys/devices/system/node', entry, 'cpulist'), 'utf8')
|
|
333
|
+
.trim()
|
|
334
|
+
const cpus = []
|
|
335
|
+
for (const part of cpulist.split(',')) {
|
|
336
|
+
if (part.includes('-')) {
|
|
337
|
+
const [start, end] = part.split('-').map(Number)
|
|
338
|
+
for (let i = start; i <= end; i++) {
|
|
339
|
+
cpus.push(i)
|
|
340
|
+
}
|
|
341
|
+
} else {
|
|
342
|
+
cpus.push(Number(part))
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
allNodes.push(cpus)
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
if (Number.isInteger(appConfig.affinity) && appConfig.affinity >= 0) {
|
|
349
|
+
affinity = allNodes[appConfig.affinity % allNodes.length]
|
|
350
|
+
} else if (appConfig.affinity == null) {
|
|
351
|
+
affinity = allNodes[hashString(serviceName) % allNodes.length]
|
|
352
|
+
} else {
|
|
353
|
+
throw new Error('invalid affinity configuration: ' + appConfig.affinity)
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
affinity = fp.uniq(affinity)
|
|
357
|
+
affinity = fp.intersection(affinity, sched_getaffinity(0))
|
|
358
|
+
|
|
359
|
+
if (
|
|
360
|
+
!Array.isArray(affinity) ||
|
|
361
|
+
affinity.length === 0 ||
|
|
362
|
+
affinity.some((x) => typeof x !== 'number' || x < 0)
|
|
363
|
+
) {
|
|
364
|
+
throw new Error('invalid affinity configuration: ' + appConfig.affinity)
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
try {
|
|
368
|
+
sched_setaffinity(0, affinity)
|
|
369
|
+
logger.debug({ data: { value: appConfig.affinity, affinity } }, 'sched_setaffinity succeeded')
|
|
370
|
+
} catch (err) {
|
|
371
|
+
logger.error({ err }, 'sched_setaffinity failed')
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
313
375
|
if (appConfig.toobusy) {
|
|
314
376
|
const resolution = appConfig.toobusy.resolution ?? 10
|
|
315
377
|
const interval = appConfig.toobusy.interval ?? 500
|
|
@@ -1275,5 +1337,6 @@ export function makeApp(appConfig, onTerminate) {
|
|
|
1275
1337
|
serviceInstanceId,
|
|
1276
1338
|
serviceWorkerId,
|
|
1277
1339
|
signal: ac.signal,
|
|
1340
|
+
affinity,
|
|
1278
1341
|
})
|
|
1279
1342
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nxtedition/lib",
|
|
3
|
-
"version": "26.0.
|
|
3
|
+
"version": "26.0.30",
|
|
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",
|