@naturalcycles/backend-lib 9.64.0 → 9.66.0
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/dist/admin/adminMiddleware.js +2 -2
- package/dist/deploy/deployInfo.util.js +2 -2
- package/dist/server/eventLoop.util.d.ts +5 -4
- package/dist/server/eventLoop.util.js +14 -2
- package/package.json +2 -2
- package/src/admin/adminMiddleware.ts +2 -2
- package/src/deploy/deployInfo.util.ts +2 -2
- package/src/server/eventLoop.util.ts +28 -9
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { _memoized } from '@naturalcycles/js-lib/decorators';
|
|
2
2
|
import { AppError } from '@naturalcycles/js-lib/error/error.util.js';
|
|
3
3
|
import { fs2 } from '@naturalcycles/nodejs-lib/fs2';
|
|
4
4
|
import { srcDir } from '../paths.cnst.js';
|
|
@@ -45,7 +45,7 @@ export function loginHtml(firebaseServiceCfg) {
|
|
|
45
45
|
}));
|
|
46
46
|
};
|
|
47
47
|
}
|
|
48
|
-
const getLoginHtml =
|
|
48
|
+
const getLoginHtml = _memoized((cfg) => {
|
|
49
49
|
console.log(`reading login.html`);
|
|
50
50
|
return fs2
|
|
51
51
|
.readText(`${srcDir}/admin/login.html`)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { localTime } from '@naturalcycles/js-lib/datetime/localTime.js';
|
|
2
|
-
import {
|
|
2
|
+
import { _memoized } from '@naturalcycles/js-lib/decorators';
|
|
3
3
|
import { fs2 } from '@naturalcycles/nodejs-lib/fs2';
|
|
4
|
-
export const getDeployInfo =
|
|
4
|
+
export const getDeployInfo = _memoized((projectDir) => {
|
|
5
5
|
const deployInfoPath = `${projectDir}/deployInfo.json`;
|
|
6
6
|
try {
|
|
7
7
|
return fs2.readJson(deployInfoPath);
|
|
@@ -5,6 +5,11 @@ import type { Integer, NonNegativeInteger, NumberOfMilliseconds, NumberOfPercent
|
|
|
5
5
|
* Also, monitors GC performance.
|
|
6
6
|
* Once per `measureInterval` sends a callback with stats.
|
|
7
7
|
*
|
|
8
|
+
* On Node >=24.19 (or >=26.5) delays are sampled once per event loop iteration
|
|
9
|
+
* (`samplePerIteration`), so stats reflect true per-iteration delay:
|
|
10
|
+
* expect p50/mean near 0 on a healthy service, instead of the ~`resolution` baseline
|
|
11
|
+
* reported by older interval-based sampling.
|
|
12
|
+
*
|
|
8
13
|
* @experimental
|
|
9
14
|
*/
|
|
10
15
|
export declare class EventLoopMonitor {
|
|
@@ -22,10 +27,6 @@ export declare class EventLoopMonitor {
|
|
|
22
27
|
stop(): void;
|
|
23
28
|
}
|
|
24
29
|
export interface EventLoopMonitorCfg {
|
|
25
|
-
/**
|
|
26
|
-
* Defaults to 20.
|
|
27
|
-
*/
|
|
28
|
-
resolution?: NumberOfMilliseconds;
|
|
29
30
|
/**
|
|
30
31
|
* Defaults to 60_000 ms
|
|
31
32
|
*/
|
|
@@ -21,12 +21,24 @@ import { monitorEventLoopDelay, performance, PerformanceObserver } from 'node:pe
|
|
|
21
21
|
* Also, monitors GC performance.
|
|
22
22
|
* Once per `measureInterval` sends a callback with stats.
|
|
23
23
|
*
|
|
24
|
+
* On Node >=24.19 (or >=26.5) delays are sampled once per event loop iteration
|
|
25
|
+
* (`samplePerIteration`), so stats reflect true per-iteration delay:
|
|
26
|
+
* expect p50/mean near 0 on a healthy service, instead of the ~`resolution` baseline
|
|
27
|
+
* reported by older interval-based sampling.
|
|
28
|
+
*
|
|
24
29
|
* @experimental
|
|
25
30
|
*/
|
|
26
31
|
export class EventLoopMonitor {
|
|
27
32
|
constructor(cfg = {}) {
|
|
28
|
-
const {
|
|
29
|
-
|
|
33
|
+
const { measureInterval = 60_000 } = cfg;
|
|
34
|
+
const eldOptions = {
|
|
35
|
+
// Node >=24.19 / >=26.5: sample once per event loop iteration (uv_prepare/uv_check hooks),
|
|
36
|
+
// which measures actual per-iteration delay instead of timer jitter.
|
|
37
|
+
// More accurate (no `resolution` offset baked into every percentile) and cheaper.
|
|
38
|
+
// Older Node silently ignores this option and falls back to interval-based sampling.
|
|
39
|
+
samplePerIteration: true,
|
|
40
|
+
};
|
|
41
|
+
this.eld = monitorEventLoopDelay(eldOptions);
|
|
30
42
|
this.eld.enable();
|
|
31
43
|
this.lastElu = performance.eventLoopUtilization();
|
|
32
44
|
this.po = new PerformanceObserver(list => {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@naturalcycles/backend-lib",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "9.
|
|
4
|
+
"version": "9.66.0",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"@naturalcycles/db-lib": "^10",
|
|
7
7
|
"@naturalcycles/js-lib": "^15",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@sentry/node-core": "^10",
|
|
47
47
|
"@types/busboy": "^1",
|
|
48
|
-
"typescript": "
|
|
48
|
+
"typescript": "^7",
|
|
49
49
|
"fastify": "^5",
|
|
50
50
|
"@naturalcycles/dev-lib": "0.0.0"
|
|
51
51
|
},
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { _memoized } from '@naturalcycles/js-lib/decorators'
|
|
2
2
|
import { AppError } from '@naturalcycles/js-lib/error/error.util.js'
|
|
3
3
|
import { fs2 } from '@naturalcycles/nodejs-lib/fs2'
|
|
4
4
|
import { srcDir } from '../paths.cnst.js'
|
|
@@ -114,7 +114,7 @@ export function loginHtml(firebaseServiceCfg: FirebaseSharedServiceCfg): Backend
|
|
|
114
114
|
}
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
-
const getLoginHtml =
|
|
117
|
+
const getLoginHtml = _memoized((cfg: LoginHtmlCfg) => {
|
|
118
118
|
console.log(`reading login.html`)
|
|
119
119
|
return fs2
|
|
120
120
|
.readText(`${srcDir}/admin/login.html`)
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { localTime } from '@naturalcycles/js-lib/datetime/localTime.js'
|
|
2
|
-
import {
|
|
2
|
+
import { _memoized } from '@naturalcycles/js-lib/decorators'
|
|
3
3
|
import { fs2 } from '@naturalcycles/nodejs-lib/fs2'
|
|
4
4
|
import type { DeployInfo } from './deploy.model.js'
|
|
5
5
|
|
|
6
|
-
export const getDeployInfo =
|
|
6
|
+
export const getDeployInfo = _memoized((projectDir: string): DeployInfo => {
|
|
7
7
|
const deployInfoPath = `${projectDir}/deployInfo.json`
|
|
8
8
|
try {
|
|
9
9
|
return fs2.readJson(deployInfoPath)
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
EventLoopMonitorOptions,
|
|
3
|
+
EventLoopUtilization,
|
|
4
|
+
IntervalHistogram,
|
|
5
|
+
} from 'node:perf_hooks'
|
|
2
6
|
import { monitorEventLoopDelay, performance, PerformanceObserver } from 'node:perf_hooks'
|
|
3
7
|
import type {
|
|
4
8
|
Integer,
|
|
@@ -30,13 +34,25 @@ import type {
|
|
|
30
34
|
* Also, monitors GC performance.
|
|
31
35
|
* Once per `measureInterval` sends a callback with stats.
|
|
32
36
|
*
|
|
37
|
+
* On Node >=24.19 (or >=26.5) delays are sampled once per event loop iteration
|
|
38
|
+
* (`samplePerIteration`), so stats reflect true per-iteration delay:
|
|
39
|
+
* expect p50/mean near 0 on a healthy service, instead of the ~`resolution` baseline
|
|
40
|
+
* reported by older interval-based sampling.
|
|
41
|
+
*
|
|
33
42
|
* @experimental
|
|
34
43
|
*/
|
|
35
44
|
export class EventLoopMonitor {
|
|
36
45
|
constructor(cfg: EventLoopMonitorCfg = {}) {
|
|
37
|
-
const {
|
|
38
|
-
|
|
39
|
-
|
|
46
|
+
const { measureInterval = 60_000 } = cfg
|
|
47
|
+
|
|
48
|
+
const eldOptions: EventLoopMonitorOptions2 = {
|
|
49
|
+
// Node >=24.19 / >=26.5: sample once per event loop iteration (uv_prepare/uv_check hooks),
|
|
50
|
+
// which measures actual per-iteration delay instead of timer jitter.
|
|
51
|
+
// More accurate (no `resolution` offset baked into every percentile) and cheaper.
|
|
52
|
+
// Older Node silently ignores this option and falls back to interval-based sampling.
|
|
53
|
+
samplePerIteration: true,
|
|
54
|
+
}
|
|
55
|
+
this.eld = monitorEventLoopDelay(eldOptions)
|
|
40
56
|
this.eld.enable()
|
|
41
57
|
|
|
42
58
|
this.lastElu = performance.eventLoopUtilization()
|
|
@@ -107,11 +123,6 @@ export class EventLoopMonitor {
|
|
|
107
123
|
}
|
|
108
124
|
|
|
109
125
|
export interface EventLoopMonitorCfg {
|
|
110
|
-
/**
|
|
111
|
-
* Defaults to 20.
|
|
112
|
-
*/
|
|
113
|
-
resolution?: NumberOfMilliseconds
|
|
114
|
-
|
|
115
126
|
/**
|
|
116
127
|
* Defaults to 60_000 ms
|
|
117
128
|
*/
|
|
@@ -156,3 +167,11 @@ export interface EventLoopStats {
|
|
|
156
167
|
*/
|
|
157
168
|
gcCPU: Integer
|
|
158
169
|
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Extends the Node types with `samplePerIteration` (added in Node 24.19 / 26.5).
|
|
173
|
+
* Remove once @types/node declares it.
|
|
174
|
+
*/
|
|
175
|
+
interface EventLoopMonitorOptions2 extends EventLoopMonitorOptions {
|
|
176
|
+
samplePerIteration?: boolean
|
|
177
|
+
}
|