spiceflow 1.17.6 → 1.17.7
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.
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { AnySpiceflow } from './spiceflow.js';
|
|
2
1
|
interface GracefulShutdownOptions {
|
|
3
2
|
maxWaitSeconds?: number;
|
|
4
3
|
checkIntervalMs?: number;
|
|
@@ -12,6 +11,6 @@ interface GracefulShutdownOptions {
|
|
|
12
11
|
* @param options.checkIntervalMs - Interval to check if requests are complete (default: 250)
|
|
13
12
|
* @returns Spiceflow app that can be mounted with .use()
|
|
14
13
|
*/
|
|
15
|
-
export declare function preventProcessExitIfBusy(options?: GracefulShutdownOptions):
|
|
14
|
+
export declare function preventProcessExitIfBusy(options?: GracefulShutdownOptions): any;
|
|
16
15
|
export {};
|
|
17
16
|
//# sourceMappingURL=prevent-process-exit-if-busy.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prevent-process-exit-if-busy.d.ts","sourceRoot":"","sources":["../src/prevent-process-exit-if-busy.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"prevent-process-exit-if-busy.d.ts","sourceRoot":"","sources":["../src/prevent-process-exit-if-busy.ts"],"names":[],"mappings":"AAGA,UAAU,uBAAuB;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,eAAe,CAAC,EAAE,MAAM,CAAA;CACzB;AAED;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,GAAE,uBAA4B,GACpC,GAAG,CAqDL"}
|
|
@@ -14,14 +14,14 @@ export function preventProcessExitIfBusy(options = {}) {
|
|
|
14
14
|
let inFlightRequests = 0;
|
|
15
15
|
let isShuttingDown = false;
|
|
16
16
|
// Sleep utility
|
|
17
|
-
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
|
17
|
+
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
18
18
|
// Graceful shutdown handler
|
|
19
19
|
async function handleShutdown(signal) {
|
|
20
20
|
if (isShuttingDown)
|
|
21
21
|
return; // Prevent multiple shutdown attempts
|
|
22
22
|
isShuttingDown = true;
|
|
23
23
|
console.log(`${signal} received – waiting for ${inFlightRequests} request(s) to complete...`);
|
|
24
|
-
const deadline = Date.now() +
|
|
24
|
+
const deadline = Date.now() + maxWaitSeconds * 1000;
|
|
25
25
|
while (inFlightRequests > 0 && Date.now() < deadline) {
|
|
26
26
|
await sleep(checkIntervalMs);
|
|
27
27
|
}
|
|
@@ -36,7 +36,7 @@ export function preventProcessExitIfBusy(options = {}) {
|
|
|
36
36
|
// Register shutdown handlers only in Node.js environments
|
|
37
37
|
if (typeof process !== 'undefined' && process.prependListener) {
|
|
38
38
|
;
|
|
39
|
-
['SIGINT', 'SIGTERM'].forEach(sig => {
|
|
39
|
+
['SIGINT', 'SIGTERM'].forEach((sig) => {
|
|
40
40
|
process.prependListener(sig, handleShutdown);
|
|
41
41
|
});
|
|
42
42
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prevent-process-exit-if-busy.js","sourceRoot":"","sources":["../src/prevent-process-exit-if-busy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAQ1C;;;;;;;;GAQG;AACH,MAAM,UAAU,wBAAwB,
|
|
1
|
+
{"version":3,"file":"prevent-process-exit-if-busy.js","sourceRoot":"","sources":["../src/prevent-process-exit-if-busy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAQ1C;;;;;;;;GAQG;AACH,MAAM,UAAU,wBAAwB,CACtC,UAAmC,EAAE;IAErC,MAAM,EAAE,cAAc,GAAG,GAAG,EAAE,eAAe,GAAG,GAAG,EAAE,GAAG,OAAO,CAAA;IAE/D,sCAAsC;IACtC,IAAI,gBAAgB,GAAG,CAAC,CAAA;IACxB,IAAI,cAAc,GAAG,KAAK,CAAA;IAE1B,gBAAgB;IAChB,MAAM,KAAK,GAAG,CAAC,EAAU,EAAE,EAAE,CAC3B,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAA;IAEzD,4BAA4B;IAC5B,KAAK,UAAU,cAAc,CAAC,MAAsB;QAClD,IAAI,cAAc;YAAE,OAAM,CAAC,qCAAqC;QAChE,cAAc,GAAG,IAAI,CAAA;QAErB,OAAO,CAAC,GAAG,CACT,GAAG,MAAM,2BAA2B,gBAAgB,4BAA4B,CACjF,CAAA;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,cAAc,GAAG,IAAI,CAAA;QAEnD,OAAO,gBAAgB,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;YACrD,MAAM,KAAK,CAAC,eAAe,CAAC,CAAA;QAC9B,CAAC;QAED,IAAI,gBAAgB,GAAG,CAAC,EAAE,CAAC;YACzB,OAAO,CAAC,GAAG,CACT,6BAA6B,gBAAgB,+BAA+B,CAC7E,CAAA;QACH,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAA;QACvC,CAAC;QAED,OAAO,CAAC,IAAI,CAAC,gBAAgB,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IAC5C,CAAC;IAED,0DAA0D;IAC1D,IAAI,OAAO,OAAO,KAAK,WAAW,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;QAC9D,CAAC;QAAA,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;YACrC,OAAO,CAAC,eAAe,CAAC,GAAqB,EAAE,cAAc,CAAC,CAAA;QAChE,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,iDAAiD;IACjD,OAAO,IAAI,SAAS,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE;QAC5D,gBAAgB,EAAE,CAAA;QAClB,IAAI,CAAC;YACH,MAAM,IAAI,EAAE,CAAA;QACd,CAAC;gBAAS,CAAC;YACT,gBAAgB,EAAE,CAAA;QACpB,CAAC;IACH,CAAC,CAAC,CAAA;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -2,65 +2,72 @@ import { Spiceflow } from './spiceflow.js'
|
|
|
2
2
|
import type { AnySpiceflow } from './spiceflow.js'
|
|
3
3
|
|
|
4
4
|
interface GracefulShutdownOptions {
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
maxWaitSeconds?: number
|
|
6
|
+
checkIntervalMs?: number
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Creates a Spiceflow middleware that tracks in-flight requests and prevents
|
|
11
11
|
* the process from exiting while requests are being processed.
|
|
12
|
-
*
|
|
12
|
+
*
|
|
13
13
|
* @param options - Configuration options
|
|
14
14
|
* @param options.maxWaitSeconds - Maximum time to wait for requests to complete (default: 300)
|
|
15
15
|
* @param options.checkIntervalMs - Interval to check if requests are complete (default: 250)
|
|
16
16
|
* @returns Spiceflow app that can be mounted with .use()
|
|
17
17
|
*/
|
|
18
|
-
export function preventProcessExitIfBusy(
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
console.log('All requests completed')
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
process.exit(inFlightRequests > 0 ? 1 : 0)
|
|
18
|
+
export function preventProcessExitIfBusy(
|
|
19
|
+
options: GracefulShutdownOptions = {},
|
|
20
|
+
): any {
|
|
21
|
+
const { maxWaitSeconds = 300, checkIntervalMs = 250 } = options
|
|
22
|
+
|
|
23
|
+
// Track in-flight requests in closure
|
|
24
|
+
let inFlightRequests = 0
|
|
25
|
+
let isShuttingDown = false
|
|
26
|
+
|
|
27
|
+
// Sleep utility
|
|
28
|
+
const sleep = (ms: number) =>
|
|
29
|
+
new Promise<void>((resolve) => setTimeout(resolve, ms))
|
|
30
|
+
|
|
31
|
+
// Graceful shutdown handler
|
|
32
|
+
async function handleShutdown(signal: NodeJS.Signals) {
|
|
33
|
+
if (isShuttingDown) return // Prevent multiple shutdown attempts
|
|
34
|
+
isShuttingDown = true
|
|
35
|
+
|
|
36
|
+
console.log(
|
|
37
|
+
`${signal} received – waiting for ${inFlightRequests} request(s) to complete...`,
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
const deadline = Date.now() + maxWaitSeconds * 1000
|
|
41
|
+
|
|
42
|
+
while (inFlightRequests > 0 && Date.now() < deadline) {
|
|
43
|
+
await sleep(checkIntervalMs)
|
|
48
44
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
;
|
|
53
|
-
|
|
54
|
-
|
|
45
|
+
|
|
46
|
+
if (inFlightRequests > 0) {
|
|
47
|
+
console.log(
|
|
48
|
+
`Shutdown timeout reached; ${inFlightRequests} request(s) still in progress`,
|
|
49
|
+
)
|
|
50
|
+
} else {
|
|
51
|
+
console.log('All requests completed')
|
|
55
52
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}
|
|
53
|
+
|
|
54
|
+
process.exit(inFlightRequests > 0 ? 1 : 0)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Register shutdown handlers only in Node.js environments
|
|
58
|
+
if (typeof process !== 'undefined' && process.prependListener) {
|
|
59
|
+
;['SIGINT', 'SIGTERM'].forEach((sig) => {
|
|
60
|
+
process.prependListener(sig as NodeJS.Signals, handleShutdown)
|
|
65
61
|
})
|
|
66
|
-
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Return Spiceflow middleware with scoped: false
|
|
65
|
+
return new Spiceflow({ scoped: false }).use(async (_, next) => {
|
|
66
|
+
inFlightRequests++
|
|
67
|
+
try {
|
|
68
|
+
await next()
|
|
69
|
+
} finally {
|
|
70
|
+
inFlightRequests--
|
|
71
|
+
}
|
|
72
|
+
})
|
|
73
|
+
}
|