@nxtedition/lib 26.0.27 → 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 +46 -39
- package/package.json +1 -1
package/app.js
CHANGED
|
@@ -39,8 +39,7 @@ import undici from '@nxtedition/undici'
|
|
|
39
39
|
import { isPrimary } from 'node:cluster'
|
|
40
40
|
import { nice } from '@napi-rs/nice'
|
|
41
41
|
import path from 'node:path'
|
|
42
|
-
|
|
43
|
-
import { sched_setaffinity, sched_getaffinity } from '@nxtedition/sched'
|
|
42
|
+
import { sched_getaffinity, sched_setaffinity } from '@nxtedition/sched'
|
|
44
43
|
|
|
45
44
|
export function makeApp(appConfig, onTerminate) {
|
|
46
45
|
let ds
|
|
@@ -127,13 +126,17 @@ export function makeApp(appConfig, onTerminate) {
|
|
|
127
126
|
const appDestroyers = []
|
|
128
127
|
|
|
129
128
|
const serviceName = appConfig.name
|
|
130
|
-
const serviceModule = appConfig.module ?? 'main'
|
|
131
129
|
const serviceVersion = appConfig.version
|
|
130
|
+
const serviceModule = appConfig.module ?? 'main'
|
|
132
131
|
const serviceWorkerId = appConfig.workerId ?? threadId
|
|
133
132
|
const serviceInstanceId =
|
|
134
133
|
// process.env.name is the pm2 name of the process
|
|
135
134
|
appConfig.instanceId ?? appConfig.containerId ?? process.env.name ?? os.hostname()
|
|
136
135
|
|
|
136
|
+
if (!serviceName) {
|
|
137
|
+
throw new Error('Service name is required')
|
|
138
|
+
}
|
|
139
|
+
|
|
137
140
|
const userAgent = (globalThis.userAgent =
|
|
138
141
|
appConfig.userAgent ??
|
|
139
142
|
(serviceName &&
|
|
@@ -313,50 +316,53 @@ export function makeApp(appConfig, onTerminate) {
|
|
|
313
316
|
}
|
|
314
317
|
}
|
|
315
318
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
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
|
+
}
|
|
323
326
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
cpus.push(Number(part))
|
|
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)
|
|
334
336
|
}
|
|
337
|
+
} else {
|
|
338
|
+
cpus.push(Number(part))
|
|
335
339
|
}
|
|
336
|
-
nodes.push(cpus)
|
|
337
340
|
}
|
|
341
|
+
allNodes.push(cpus)
|
|
342
|
+
}
|
|
338
343
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
}
|
|
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
|
+
}
|
|
347
351
|
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
for (const index of indices) {
|
|
351
|
-
affinity = fp.union(affinity, nodes[index % nodes.length])
|
|
352
|
-
}
|
|
352
|
+
affinity = fp.uniq(affinity)
|
|
353
|
+
affinity = fp.intersection(affinity, sched_getaffinity(0))
|
|
353
354
|
|
|
354
|
-
|
|
355
|
-
|
|
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
|
+
}
|
|
356
362
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
}
|
|
363
|
+
try {
|
|
364
|
+
sched_setaffinity(0, affinity)
|
|
365
|
+
logger.debug({ data: { value: appConfig.affinity, affinity } }, 'sched_setaffinity succeeded')
|
|
360
366
|
} catch (err) {
|
|
361
367
|
logger.error({ err }, 'sched_setaffinity failed')
|
|
362
368
|
}
|
|
@@ -1327,5 +1333,6 @@ export function makeApp(appConfig, onTerminate) {
|
|
|
1327
1333
|
serviceInstanceId,
|
|
1328
1334
|
serviceWorkerId,
|
|
1329
1335
|
signal: ac.signal,
|
|
1336
|
+
affinity,
|
|
1330
1337
|
})
|
|
1331
1338
|
}
|