@proteinjs/server 3.5.3 → 3.7.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/CHANGELOG.md +22 -0
- package/dist/generated/index.js +1 -1
- package/dist/generated/index.js.map +1 -1
- package/dist/src/DevClientBuild.d.ts +6 -0
- package/dist/src/DevClientBuild.d.ts.map +1 -1
- package/dist/src/DevClientBuild.js.map +1 -1
- package/dist/src/GracefulShutdown.d.ts +56 -3
- package/dist/src/GracefulShutdown.d.ts.map +1 -1
- package/dist/src/GracefulShutdown.js +148 -7
- package/dist/src/GracefulShutdown.js.map +1 -1
- package/dist/src/routes/reactApp.d.ts.map +1 -1
- package/dist/src/routes/reactApp.js +65 -60
- package/dist/src/routes/reactApp.js.map +1 -1
- package/dist/src/startServer.js +17 -2
- package/dist/src/startServer.js.map +1 -1
- package/generated/index.ts +1 -1
- package/package.json +3 -3
- package/src/DevClientBuild.ts +6 -0
- package/src/GracefulShutdown.ts +133 -5
- package/src/routes/reactApp.ts +57 -31
- package/src/startServer.ts +16 -2
- package/test/fixture/gracefulShutdownServer.js +21 -2
- package/test/gracefulShutdown.test.ts +68 -1
- package/test/holdSeam.test.ts +82 -0
- package/test/reactAppBoot.test.ts +168 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,28 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
# [3.7.0](https://github.com/proteinjs/server/compare/@proteinjs/server@3.6.0...@proteinjs/server@3.7.0) (2026-09-12)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* **server:** the react app page boots in one round — the server-rendered scripts render concurrently (emitted in registration order), the bundles are deferred and preloaded from the head, and the dev page renders the compile's own entrypoint files (DevClientBuild.assets) stamped ?v=<hash> instead of a hard-coded app.js + vendor.js pair ([206412a](https://github.com/proteinjs/server/commit/206412a0f4176d0052d3ed95b24c4ce5c08c5e06))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# [3.6.0](https://github.com/proteinjs/server/compare/@proteinjs/server@3.5.3...@proteinjs/server@3.6.0) (2026-09-10)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Features
|
|
21
|
+
|
|
22
|
+
* **server:** GracefulShutdown holds — the SIGTERM drain waits for work no connection represents (a detached chat turn), bounded by shutdown.turnDrainMs ([b534d68](https://github.com/proteinjs/server/commit/b534d68ab14f925a686cb338466ebabd4b40ef75))
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
6
28
|
## [3.5.3](https://github.com/proteinjs/server/compare/@proteinjs/server@3.5.2...@proteinjs/server@3.5.3) (2026-09-01)
|
|
7
29
|
|
|
8
30
|
|
package/dist/generated/index.js
CHANGED
|
@@ -33,7 +33,7 @@ require("react-helmet");
|
|
|
33
33
|
require("socket.io");
|
|
34
34
|
require("typescript");
|
|
35
35
|
/** Generate Source Graph */
|
|
36
|
-
var sourceGraph = "{\"options\":{\"directed\":true,\"multigraph\":false,\"compound\":false},\"nodes\":[{\"v\":\"@proteinjs/server/NodeGlobalDataStorage\",\"value\":{\"packageName\":\"@proteinjs/server\",\"name\":\"NodeGlobalDataStorage\",\"filePath\":\"/home/runner/work/server/server/packages/server/src/NodeGlobalDataStorage.ts\",\"qualifiedName\":\"@proteinjs/server/NodeGlobalDataStorage\",\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"properties\":[{\"name\":\"HOOK_INITIALIZED\",\"type\":null,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":true,\"visibility\":\"private\"},{\"name\":\"GLOBAL_DATA\",\"type\":{\"packageName\":\"@proteinjs/server\",\"name\":\"{ [id: string]: GlobalData }\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server/{ [id: string]: GlobalData }\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":false,\"isAbstract\":false,\"isStatic\":true,\"visibility\":\"private\"},{\"name\":\"environment\",\"type\":null,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"}],\"methods\":[{\"name\":\"setData\",\"returnType\":null,\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[{\"name\":\"data\",\"type\":{\"packageName\":\"@proteinjs/server-api\",\"name\":\"GlobalData\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/GlobalData\",\"typeParameters\":null,\"directParents\":null}}]},{\"name\":\"getData\",\"returnType\":{\"packageName\":\"@proteinjs/server-api\",\"name\":\"GlobalData\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/GlobalData\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[]},{\"name\":\"initHook\",\"returnType\":null,\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\",\"parameters\":[]}],\"typeParameters\":[],\"directParentInterfaces\":[{\"packageName\":\"@proteinjs/server-api\",\"name\":\"GlobalDataStorage\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/GlobalDataStorage\",\"properties\":[],\"methods\":[],\"typeParameters\":[],\"directParents\":[]}],\"directParentClasses\":[],\"sourceType\":2}},{\"v\":\"@proteinjs/server-api/GlobalDataStorage\"},{\"v\":\"@proteinjs/server/NodeSessionDataStorage\",\"value\":{\"packageName\":\"@proteinjs/server\",\"name\":\"NodeSessionDataStorage\",\"filePath\":\"/home/runner/work/server/server/packages/server/src/NodeSessionDataStorage.ts\",\"qualifiedName\":\"@proteinjs/server/NodeSessionDataStorage\",\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"properties\":[{\"name\":\"HOOK_INITIALIZED\",\"type\":null,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":true,\"visibility\":\"private\"},{\"name\":\"SESSION_DATA\",\"type\":{\"packageName\":\"@proteinjs/server\",\"name\":\"{ [id: string]: SessionData }\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server/{ [id: string]: SessionData }\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":false,\"isAbstract\":false,\"isStatic\":true,\"visibility\":\"private\"},{\"name\":\"environment\",\"type\":null,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"}],\"methods\":[{\"name\":\"setData\",\"returnType\":null,\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[{\"name\":\"data\",\"type\":{\"packageName\":\"@proteinjs/server-api\",\"name\":\"SessionData\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/SessionData\",\"typeParameters\":null,\"directParents\":null}}]},{\"name\":\"getData\",\"returnType\":{\"packageName\":\"@proteinjs/server-api\",\"name\":\"SessionData\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/SessionData\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[]},{\"name\":\"clearData\",\"returnType\":{\"packageName\":\"\",\"name\":\"void\",\"filePath\":null,\"qualifiedName\":\"/void\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[]},{\"name\":\"initHook\",\"returnType\":null,\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\",\"parameters\":[]}],\"typeParameters\":[],\"directParentInterfaces\":[{\"packageName\":\"@proteinjs/server-api\",\"name\":\"SessionDataStorage\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/SessionDataStorage\",\"properties\":[],\"methods\":[],\"typeParameters\":[],\"directParents\":[]}],\"directParentClasses\":[],\"sourceType\":2}},{\"v\":\"@proteinjs/server-api/SessionDataStorage\"},{\"v\":\"@proteinjs/server/ExtendedIncomingMessage\",\"value\":{\"packageName\":\"@proteinjs/server\",\"name\":\"ExtendedIncomingMessage\",\"filePath\":\"/home/runner/work/server/server/packages/server/src/SocketIOServerRepo.ts\",\"qualifiedName\":\"@proteinjs/server/ExtendedIncomingMessage\",\"properties\":[{\"name\":\"sessionID\",\"type\":{\"packageName\":\"\",\"name\":\"string\",\"filePath\":null,\"qualifiedName\":\"/string\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":true,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"},{\"name\":\"user\",\"type\":{\"packageName\":\"\",\"name\":\"string\",\"filePath\":null,\"qualifiedName\":\"/string\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":true,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"}],\"methods\":[],\"typeParameters\":[],\"directParents\":[{\"packageName\":\"http\",\"name\":\"IncomingMessage\",\"filePath\":null,\"qualifiedName\":\"http/IncomingMessage\",\"properties\":[],\"methods\":[],\"typeParameters\":[],\"directParents\":[]}],\"sourceType\":3}},{\"v\":\"http/IncomingMessage\"},{\"v\":\"@proteinjs/server/ExtendedSocket\",\"value\":{\"packageName\":\"@proteinjs/server\",\"name\":\"ExtendedSocket\",\"filePath\":\"/home/runner/work/server/server/packages/server/src/SocketIOServerRepo.ts\",\"qualifiedName\":\"@proteinjs/server/ExtendedSocket\",\"properties\":[{\"name\":\"request\",\"type\":{\"packageName\":\"@proteinjs/server\",\"name\":\"ExtendedIncomingMessage\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server/ExtendedIncomingMessage\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"}],\"methods\":[],\"typeParameters\":[],\"directParents\":[{\"packageName\":\"socket.io\",\"name\":\"Socket\",\"filePath\":null,\"qualifiedName\":\"socket.io/Socket\",\"properties\":[],\"methods\":[],\"typeParameters\":[],\"directParents\":[]}],\"sourceType\":3}},{\"v\":\"socket.io/Socket\"},{\"v\":\"@proteinjs/server/environmentCache\",\"value\":{\"packageName\":\"@proteinjs/server\",\"name\":\"environmentCache\",\"filePath\":\"/home/runner/work/server/server/packages/server/src/envCache.ts\",\"qualifiedName\":\"@proteinjs/server/environmentCache\",\"type\":{\"packageName\":\"\",\"name\":\"GlobalDataCache<Env>\",\"filePath\":null,\"qualifiedName\":\"/GlobalDataCache<Env>\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/server-api\",\"name\":\"GlobalDataCache\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/GlobalDataCache\",\"typeParameters\":[\"@proteinjs/server-api/Env\"],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}},{\"v\":\"@proteinjs/server-api/GlobalDataCache\"},{\"v\":\"@proteinjs/server/healthCheck\",\"value\":{\"packageName\":\"@proteinjs/server\",\"name\":\"healthCheck\",\"filePath\":\"/home/runner/work/server/server/packages/server/src/routes/healthCheck.ts\",\"qualifiedName\":\"@proteinjs/server/healthCheck\",\"type\":{\"packageName\":\"@proteinjs/server-api\",\"name\":\"Route\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/Route\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/server-api\",\"name\":\"Route\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/Route\",\"typeParameters\":[],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}},{\"v\":\"@proteinjs/server-api/Route\"}],\"edges\":[{\"v\":\"@proteinjs/server/NodeGlobalDataStorage\",\"w\":\"@proteinjs/server-api/GlobalDataStorage\",\"value\":\"implements interface\"},{\"v\":\"@proteinjs/server/NodeSessionDataStorage\",\"w\":\"@proteinjs/server-api/SessionDataStorage\",\"value\":\"implements interface\"},{\"v\":\"@proteinjs/server/ExtendedIncomingMessage\",\"w\":\"http/IncomingMessage\",\"value\":\"extends interface\"},{\"v\":\"@proteinjs/server/ExtendedSocket\",\"w\":\"socket.io/Socket\",\"value\":\"extends interface\"},{\"v\":\"@proteinjs/server/environmentCache\",\"w\":\"@proteinjs/server-api/GlobalDataCache\",\"value\":\"has type\"},{\"v\":\"@proteinjs/server/healthCheck\",\"w\":\"@proteinjs/server-api/Route\",\"value\":\"has type\"}]}";
|
|
36
|
+
var sourceGraph = "{\"options\":{\"directed\":true,\"multigraph\":false,\"compound\":false},\"nodes\":[{\"v\":\"/() => void\"},{\"v\":\"@proteinjs/server/NodeGlobalDataStorage\",\"value\":{\"packageName\":\"@proteinjs/server\",\"name\":\"NodeGlobalDataStorage\",\"filePath\":\"/home/runner/work/server/server/packages/server/src/NodeGlobalDataStorage.ts\",\"qualifiedName\":\"@proteinjs/server/NodeGlobalDataStorage\",\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"properties\":[{\"name\":\"HOOK_INITIALIZED\",\"type\":null,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":true,\"visibility\":\"private\"},{\"name\":\"GLOBAL_DATA\",\"type\":{\"packageName\":\"@proteinjs/server\",\"name\":\"{ [id: string]: GlobalData }\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server/{ [id: string]: GlobalData }\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":false,\"isAbstract\":false,\"isStatic\":true,\"visibility\":\"private\"},{\"name\":\"environment\",\"type\":null,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"}],\"methods\":[{\"name\":\"setData\",\"returnType\":null,\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[{\"name\":\"data\",\"type\":{\"packageName\":\"@proteinjs/server-api\",\"name\":\"GlobalData\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/GlobalData\",\"typeParameters\":null,\"directParents\":null}}]},{\"name\":\"getData\",\"returnType\":{\"packageName\":\"@proteinjs/server-api\",\"name\":\"GlobalData\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/GlobalData\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[]},{\"name\":\"initHook\",\"returnType\":null,\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\",\"parameters\":[]}],\"typeParameters\":[],\"directParentInterfaces\":[{\"packageName\":\"@proteinjs/server-api\",\"name\":\"GlobalDataStorage\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/GlobalDataStorage\",\"properties\":[],\"methods\":[],\"typeParameters\":[],\"directParents\":[]}],\"directParentClasses\":[],\"sourceType\":2}},{\"v\":\"@proteinjs/server-api/GlobalDataStorage\"},{\"v\":\"@proteinjs/server/NodeSessionDataStorage\",\"value\":{\"packageName\":\"@proteinjs/server\",\"name\":\"NodeSessionDataStorage\",\"filePath\":\"/home/runner/work/server/server/packages/server/src/NodeSessionDataStorage.ts\",\"qualifiedName\":\"@proteinjs/server/NodeSessionDataStorage\",\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"properties\":[{\"name\":\"HOOK_INITIALIZED\",\"type\":null,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":true,\"visibility\":\"private\"},{\"name\":\"SESSION_DATA\",\"type\":{\"packageName\":\"@proteinjs/server\",\"name\":\"{ [id: string]: SessionData }\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server/{ [id: string]: SessionData }\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":false,\"isAbstract\":false,\"isStatic\":true,\"visibility\":\"private\"},{\"name\":\"environment\",\"type\":null,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"}],\"methods\":[{\"name\":\"setData\",\"returnType\":null,\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[{\"name\":\"data\",\"type\":{\"packageName\":\"@proteinjs/server-api\",\"name\":\"SessionData\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/SessionData\",\"typeParameters\":null,\"directParents\":null}}]},{\"name\":\"getData\",\"returnType\":{\"packageName\":\"@proteinjs/server-api\",\"name\":\"SessionData\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/SessionData\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[]},{\"name\":\"clearData\",\"returnType\":{\"packageName\":\"\",\"name\":\"void\",\"filePath\":null,\"qualifiedName\":\"/void\",\"typeParameters\":null,\"directParents\":null},\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\",\"parameters\":[]},{\"name\":\"initHook\",\"returnType\":null,\"isAsync\":false,\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"private\",\"parameters\":[]}],\"typeParameters\":[],\"directParentInterfaces\":[{\"packageName\":\"@proteinjs/server-api\",\"name\":\"SessionDataStorage\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/SessionDataStorage\",\"properties\":[],\"methods\":[],\"typeParameters\":[],\"directParents\":[]}],\"directParentClasses\":[],\"sourceType\":2}},{\"v\":\"@proteinjs/server-api/SessionDataStorage\"},{\"v\":\"@proteinjs/server/ExtendedIncomingMessage\",\"value\":{\"packageName\":\"@proteinjs/server\",\"name\":\"ExtendedIncomingMessage\",\"filePath\":\"/home/runner/work/server/server/packages/server/src/SocketIOServerRepo.ts\",\"qualifiedName\":\"@proteinjs/server/ExtendedIncomingMessage\",\"properties\":[{\"name\":\"sessionID\",\"type\":{\"packageName\":\"\",\"name\":\"string\",\"filePath\":null,\"qualifiedName\":\"/string\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":true,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"},{\"name\":\"user\",\"type\":{\"packageName\":\"\",\"name\":\"string\",\"filePath\":null,\"qualifiedName\":\"/string\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":true,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"}],\"methods\":[],\"typeParameters\":[],\"directParents\":[{\"packageName\":\"http\",\"name\":\"IncomingMessage\",\"filePath\":null,\"qualifiedName\":\"http/IncomingMessage\",\"properties\":[],\"methods\":[],\"typeParameters\":[],\"directParents\":[]}],\"sourceType\":3}},{\"v\":\"http/IncomingMessage\"},{\"v\":\"@proteinjs/server/ExtendedSocket\",\"value\":{\"packageName\":\"@proteinjs/server\",\"name\":\"ExtendedSocket\",\"filePath\":\"/home/runner/work/server/server/packages/server/src/SocketIOServerRepo.ts\",\"qualifiedName\":\"@proteinjs/server/ExtendedSocket\",\"properties\":[{\"name\":\"request\",\"type\":{\"packageName\":\"@proteinjs/server\",\"name\":\"ExtendedIncomingMessage\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server/ExtendedIncomingMessage\",\"typeParameters\":null,\"directParents\":null},\"isOptional\":false,\"isAbstract\":false,\"isStatic\":false,\"visibility\":\"public\"}],\"methods\":[],\"typeParameters\":[],\"directParents\":[{\"packageName\":\"socket.io\",\"name\":\"Socket\",\"filePath\":null,\"qualifiedName\":\"socket.io/Socket\",\"properties\":[],\"methods\":[],\"typeParameters\":[],\"directParents\":[]}],\"sourceType\":3}},{\"v\":\"socket.io/Socket\"},{\"v\":\"@proteinjs/server/environmentCache\",\"value\":{\"packageName\":\"@proteinjs/server\",\"name\":\"environmentCache\",\"filePath\":\"/home/runner/work/server/server/packages/server/src/envCache.ts\",\"qualifiedName\":\"@proteinjs/server/environmentCache\",\"type\":{\"packageName\":\"\",\"name\":\"GlobalDataCache<Env>\",\"filePath\":null,\"qualifiedName\":\"/GlobalDataCache<Env>\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/server-api\",\"name\":\"GlobalDataCache\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/GlobalDataCache\",\"typeParameters\":[\"@proteinjs/server-api/Env\"],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}},{\"v\":\"@proteinjs/server-api/GlobalDataCache\"},{\"v\":\"@proteinjs/server/healthCheck\",\"value\":{\"packageName\":\"@proteinjs/server\",\"name\":\"healthCheck\",\"filePath\":\"/home/runner/work/server/server/packages/server/src/routes/healthCheck.ts\",\"qualifiedName\":\"@proteinjs/server/healthCheck\",\"type\":{\"packageName\":\"@proteinjs/server-api\",\"name\":\"Route\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/Route\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/server-api\",\"name\":\"Route\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/server-api/Route\",\"typeParameters\":[],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}},{\"v\":\"@proteinjs/server-api/Route\"}],\"edges\":[{\"v\":\"@proteinjs/server/NodeGlobalDataStorage\",\"w\":\"@proteinjs/server-api/GlobalDataStorage\",\"value\":\"implements interface\"},{\"v\":\"@proteinjs/server/NodeSessionDataStorage\",\"w\":\"@proteinjs/server-api/SessionDataStorage\",\"value\":\"implements interface\"},{\"v\":\"@proteinjs/server/ExtendedIncomingMessage\",\"w\":\"http/IncomingMessage\",\"value\":\"extends interface\"},{\"v\":\"@proteinjs/server/ExtendedSocket\",\"w\":\"socket.io/Socket\",\"value\":\"extends interface\"},{\"v\":\"@proteinjs/server/environmentCache\",\"w\":\"@proteinjs/server-api/GlobalDataCache\",\"value\":\"has type\"},{\"v\":\"@proteinjs/server/healthCheck\",\"w\":\"@proteinjs/server-api/Route\",\"value\":\"has type\"}]}";
|
|
37
37
|
/** Generate Source Links */
|
|
38
38
|
var NodeGlobalDataStorage_1 = require("../src/NodeGlobalDataStorage");
|
|
39
39
|
var NodeSessionDataStorage_1 = require("../src/NodeSessionDataStorage");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../generated/index.ts"],"names":[],"mappings":";AAAA,oCAAoC;;;;;;;;;;;;;;;;AAEpC,4BAA0B;AAC1B,6BAA2B;AAC3B,iCAA+B;AAC/B,iCAA+B;AAC/B,gCAA8B;AAC9B,uBAAqB;AACrB,yBAAuB;AACvB,kBAAgB;AAChB,mBAAiB;AACjB,2BAAyB;AACzB,oBAAkB;AAClB,0BAAwB;AACxB,mBAAiB;AACjB,iBAAe;AACf,wBAAsB;AACtB,qBAAmB;AACnB,sBAAoB;AAGpB,4BAA4B;AAE5B,IAAM,WAAW,GAAG,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../generated/index.ts"],"names":[],"mappings":";AAAA,oCAAoC;;;;;;;;;;;;;;;;AAEpC,4BAA0B;AAC1B,6BAA2B;AAC3B,iCAA+B;AAC/B,iCAA+B;AAC/B,gCAA8B;AAC9B,uBAAqB;AACrB,yBAAuB;AACvB,kBAAgB;AAChB,mBAAiB;AACjB,2BAAyB;AACzB,oBAAkB;AAClB,0BAAwB;AACxB,mBAAiB;AACjB,iBAAe;AACf,wBAAsB;AACtB,qBAAmB;AACnB,sBAAoB;AAGpB,4BAA4B;AAE5B,IAAM,WAAW,GAAG,i+RAAi+R,CAAC;AAGt/R,4BAA4B;AAE5B,sEAAqE;AACrE,wEAAuE;AACvE,4CAAmD;AACnD,yDAAwD;AAExD,IAAM,WAAW,GAAG;IACnB,yCAAyC,EAAE,6CAAqB;IAChE,0CAA0C,EAAE,+CAAsB;IAClE,oCAAoC,EAAE,2BAAgB;IACtD,+BAA+B,EAAE,yBAAW;CAC5C,CAAC;AAGF,kCAAkC;AAElC,oDAAyD;AACzD,6BAAgB,CAAC,KAAK,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;AAGjD,2CAAyB"}
|
|
@@ -13,6 +13,12 @@ export type DevClientBuildInfo = {
|
|
|
13
13
|
builtAt: string;
|
|
14
14
|
durationMs?: number;
|
|
15
15
|
errorCount: number;
|
|
16
|
+
/**
|
|
17
|
+
* The entrypoint's script files (`app.js`, `vendor.js`, …) in the compile's own load order —
|
|
18
|
+
* the dev page's bundle tags are rendered from THIS list (reactApp.ts), so the page follows the
|
|
19
|
+
* chunk graph the webpack config declares instead of a hard-coded pair of names.
|
|
20
|
+
*/
|
|
21
|
+
assets: string[];
|
|
16
22
|
};
|
|
17
23
|
export declare class DevClientBuild {
|
|
18
24
|
private static current;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DevClientBuild.d.ts","sourceRoot":"","sources":["../../src/DevClientBuild.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B,2EAA2E;IAC3E,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"DevClientBuild.d.ts","sourceRoot":"","sources":["../../src/DevClientBuild.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B,2EAA2E;IAC3E,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CAAC;AAEF,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAC,OAAO,CAAiC;IAEvD,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,kBAAkB,GAAG,IAAI;IAI7C,MAAM,CAAC,GAAG,IAAI,kBAAkB,GAAG,SAAS;CAG7C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DevClientBuild.js","sourceRoot":"","sources":["../../src/DevClientBuild.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"DevClientBuild.js","sourceRoot":"","sources":["../../src/DevClientBuild.ts"],"names":[],"mappings":";;;AAuBA;IAAA;IAUA,CAAC;IAPQ,qBAAM,GAAb,UAAc,IAAwB;QACpC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;IACtB,CAAC;IAEM,kBAAG,GAAV;QACE,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IACH,qBAAC;AAAD,CAAC,AAVD,IAUC;AAVY,wCAAc"}
|
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import { Server as HttpServer } from 'http';
|
|
3
3
|
import { ServerConfig } from '@proteinjs/server-api';
|
|
4
|
+
/** Releases a hold taken with {@link GracefulShutdown.hold}. Idempotent. */
|
|
5
|
+
export type HoldRelease = () => void;
|
|
6
|
+
/** A hold outstanding on the process: its label plus whatever the holder attached for the logs. */
|
|
7
|
+
export type Hold = {
|
|
8
|
+
label: string;
|
|
9
|
+
context?: Record<string, unknown>;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Follows the process's holds as they come and go — the dev supervisor's lease projection
|
|
13
|
+
* (@n3xah/util-server's ServePackageHold) is the one consumer; it never decides anything here.
|
|
14
|
+
*/
|
|
15
|
+
export type HoldObserver = {
|
|
16
|
+
acquired?: (label: string) => void;
|
|
17
|
+
released?: (label: string) => void;
|
|
18
|
+
};
|
|
4
19
|
/**
|
|
5
20
|
* The one owner of the server's shutdown state. Installed by `startServer` before the listener
|
|
6
21
|
* opens; the `/health-check` route reads `isShuttingDown()` — no other flag system exists.
|
|
@@ -15,25 +30,48 @@ import { ServerConfig } from '@proteinjs/server-api';
|
|
|
15
30
|
* 2. The listener closes (socket.io clients are disconnected, and `io.close()` closes the
|
|
16
31
|
* http server it is attached to), idle keep-alive connections are closed, and in-flight
|
|
17
32
|
* requests run to completion.
|
|
18
|
-
* 3. The
|
|
19
|
-
*
|
|
33
|
+
* 3. The process WAITS for its HOLDS (`hold(label)` below) to release, bounded by
|
|
34
|
+
* `shutdown.turnDrainMs`: work that must not die with the process and that no HTTP
|
|
35
|
+
* connection represents — the canonical holder is a chat turn whose client has gone
|
|
36
|
+
* (the response detached, the model still writing, nothing persisted yet). Past the
|
|
37
|
+
* bound every hold still outstanding is logged by label and abandoned.
|
|
38
|
+
* 4. The connection drain is BOUNDED by `shutdown.drainTimeoutMs`: past it, remaining
|
|
39
|
+
* connections are force-closed. Either way the exit code is 0 — a drained shutdown is
|
|
40
|
+
* not a crash.
|
|
20
41
|
* SIGINT → exit 0 immediately (dev ctrl-C: fast and quiet; nothing needs flushing).
|
|
21
42
|
* exit 86 → NOT this class's concern: `process.exit(86)` is the ServePackageSupervisor
|
|
22
43
|
* restart-request contract (a liveness monitor giving up on a dependency); it is not
|
|
23
44
|
* signal-driven and is untouched by these handlers.
|
|
24
45
|
*
|
|
46
|
+
* Holds are a process-wide static seam so a holder never needs the server instance (a turn
|
|
47
|
+
* registry, a suite with no listener): `hold(label, context)` returns the release; the same
|
|
48
|
+
* label held twice is one hold (the release is shared — the turn registry's idempotence);
|
|
49
|
+
* `holds()` lists what is outstanding, in acquisition order; `observeHolds` lets the dev
|
|
50
|
+
* supervisor's lease follow the same set, so a holder declares itself ONCE and both the
|
|
51
|
+
* pre-signal restart deferral (dev) and the post-SIGTERM drain (prod) honor it.
|
|
52
|
+
*
|
|
53
|
+
* Why holds and not connections: the 2026-09-05 prod kill — a phone locked mid-turn, the route
|
|
54
|
+
* detached the dead response and the turn ran on to persist, GKE's autoscaler evicted the pod,
|
|
55
|
+
* and this drain saw NO connection in flight, so `process.exit(0)` ran 5 s after SIGTERM with the
|
|
56
|
+
* model call 32 s in. Nothing persisted, nothing logged (plans/FREE_AGENT.md §M.14).
|
|
57
|
+
*
|
|
25
58
|
* A SIGTERM before the listener is open (mid-boot kill) exits 0 immediately — nothing is
|
|
26
59
|
* registered anywhere and nothing is in flight.
|
|
27
60
|
*
|
|
28
61
|
* Supervisor compatibility (dev): ServePackageSupervisor SIGTERMs the child's process group and
|
|
29
62
|
* escalates to SIGKILL after its grace period (default 10s); its exit handler ignores exit codes
|
|
30
63
|
* for kills it initiated, so the drain-then-exit-0 shape cannot be misread. DEVELOPMENT defaults
|
|
31
|
-
* `drainDelayMs` to 0 so supervised restarts stay fast
|
|
64
|
+
* `drainDelayMs` to 0 so supervised restarts stay fast; a turn in flight under the supervisor is
|
|
65
|
+
* covered BEFORE the signal by its lease (the hold projection), not by this drain.
|
|
32
66
|
*/
|
|
33
67
|
export declare class GracefulShutdown {
|
|
34
68
|
private server;
|
|
35
69
|
private config;
|
|
36
70
|
private static instance?;
|
|
71
|
+
private static holds;
|
|
72
|
+
private static holdObservers;
|
|
73
|
+
private static holdWaiters;
|
|
74
|
+
private static staticLogger;
|
|
37
75
|
private shuttingDown;
|
|
38
76
|
private logger;
|
|
39
77
|
private constructor();
|
|
@@ -41,10 +79,25 @@ export declare class GracefulShutdown {
|
|
|
41
79
|
static install(server: HttpServer, config: ServerConfig): void;
|
|
42
80
|
/** The readiness seam: `/health-check` reports 503 whenever this is true. */
|
|
43
81
|
static isShuttingDown(): boolean;
|
|
82
|
+
/**
|
|
83
|
+
* Keep the process alive through a SIGTERM drain until the returned release is called (bounded
|
|
84
|
+
* by `shutdown.turnDrainMs`). `label` names the work in the drain's logs (`chat-turn:<id>`);
|
|
85
|
+
* `context` rides beside it (chat id, user id). Holding a label already held returns the
|
|
86
|
+
* existing release — one hold per label.
|
|
87
|
+
*/
|
|
88
|
+
static hold(label: string, context?: Record<string, unknown>): HoldRelease;
|
|
89
|
+
/** Every hold outstanding right now, in acquisition order. */
|
|
90
|
+
static outstandingHolds(): Hold[];
|
|
91
|
+
/** Follow holds as they are acquired and released. Returns the unsubscribe. */
|
|
92
|
+
static observeHolds(observer: HoldObserver): () => void;
|
|
44
93
|
private drainAndExit;
|
|
94
|
+
private drainHolds;
|
|
45
95
|
private exitNow;
|
|
46
96
|
private drainDelayMs;
|
|
47
97
|
private drainTimeoutMs;
|
|
98
|
+
private turnDrainMs;
|
|
99
|
+
private static whenNoHolds;
|
|
100
|
+
private static notify;
|
|
48
101
|
/** Await a promise with a deadline; true if it settled in time. */
|
|
49
102
|
private settled;
|
|
50
103
|
private sleep;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GracefulShutdown.d.ts","sourceRoot":"","sources":["../../src/GracefulShutdown.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,MAAM,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAIrD
|
|
1
|
+
{"version":3,"file":"GracefulShutdown.d.ts","sourceRoot":"","sources":["../../src/GracefulShutdown.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,MAAM,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAIrD,4EAA4E;AAC5E,MAAM,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC;AAErC,mGAAmG;AACnG,MAAM,MAAM,IAAI,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAAC;AAExE;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG;IAAE,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAAC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;CAAE,CAAC;AAEtG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AACH,qBAAa,gBAAgB;IAUzB,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,MAAM;IAVhB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAmB;IAC3C,OAAO,CAAC,MAAM,CAAC,KAAK,CAA2D;IAC/E,OAAO,CAAC,MAAM,CAAC,aAAa,CAA2B;IACvD,OAAO,CAAC,MAAM,CAAC,WAAW,CAAyB;IACnD,OAAO,CAAC,MAAM,CAAC,YAAY,CAA4C;IACvE,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,MAAM,CAA4C;IAE1D,OAAO;IAKP,iFAAiF;IACjF,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,YAAY,GAAG,IAAI;IAU9D,6EAA6E;IAC7E,MAAM,CAAC,cAAc,IAAI,OAAO;IAIhC;;;;;OAKG;IACH,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,WAAW;IAuB1E,8DAA8D;IAC9D,MAAM,CAAC,gBAAgB,IAAI,IAAI,EAAE;IAIjC,+EAA+E;IAC/E,MAAM,CAAC,YAAY,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM,IAAI;YAOzC,YAAY;YA6CZ,UAAU;IAqBxB,OAAO,CAAC,OAAO;IAMf,OAAO,CAAC,YAAY;IAOpB,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,MAAM,CAAC,WAAW;IAO1B,OAAO,CAAC,MAAM,CAAC,MAAM;IAcrB,mEAAmE;YACrD,OAAO;IAUrB,OAAO,CAAC,KAAK;CAGd"}
|
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __assign = (this && this.__assign) || function () {
|
|
3
|
+
__assign = Object.assign || function(t) {
|
|
4
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
+
s = arguments[i];
|
|
6
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
+
t[p] = s[p];
|
|
8
|
+
}
|
|
9
|
+
return t;
|
|
10
|
+
};
|
|
11
|
+
return __assign.apply(this, arguments);
|
|
12
|
+
};
|
|
2
13
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
14
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
15
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -53,20 +64,39 @@ var SocketIOServerRepo_1 = require("./SocketIOServerRepo");
|
|
|
53
64
|
* 2. The listener closes (socket.io clients are disconnected, and `io.close()` closes the
|
|
54
65
|
* http server it is attached to), idle keep-alive connections are closed, and in-flight
|
|
55
66
|
* requests run to completion.
|
|
56
|
-
* 3. The
|
|
57
|
-
*
|
|
67
|
+
* 3. The process WAITS for its HOLDS (`hold(label)` below) to release, bounded by
|
|
68
|
+
* `shutdown.turnDrainMs`: work that must not die with the process and that no HTTP
|
|
69
|
+
* connection represents — the canonical holder is a chat turn whose client has gone
|
|
70
|
+
* (the response detached, the model still writing, nothing persisted yet). Past the
|
|
71
|
+
* bound every hold still outstanding is logged by label and abandoned.
|
|
72
|
+
* 4. The connection drain is BOUNDED by `shutdown.drainTimeoutMs`: past it, remaining
|
|
73
|
+
* connections are force-closed. Either way the exit code is 0 — a drained shutdown is
|
|
74
|
+
* not a crash.
|
|
58
75
|
* SIGINT → exit 0 immediately (dev ctrl-C: fast and quiet; nothing needs flushing).
|
|
59
76
|
* exit 86 → NOT this class's concern: `process.exit(86)` is the ServePackageSupervisor
|
|
60
77
|
* restart-request contract (a liveness monitor giving up on a dependency); it is not
|
|
61
78
|
* signal-driven and is untouched by these handlers.
|
|
62
79
|
*
|
|
80
|
+
* Holds are a process-wide static seam so a holder never needs the server instance (a turn
|
|
81
|
+
* registry, a suite with no listener): `hold(label, context)` returns the release; the same
|
|
82
|
+
* label held twice is one hold (the release is shared — the turn registry's idempotence);
|
|
83
|
+
* `holds()` lists what is outstanding, in acquisition order; `observeHolds` lets the dev
|
|
84
|
+
* supervisor's lease follow the same set, so a holder declares itself ONCE and both the
|
|
85
|
+
* pre-signal restart deferral (dev) and the post-SIGTERM drain (prod) honor it.
|
|
86
|
+
*
|
|
87
|
+
* Why holds and not connections: the 2026-09-05 prod kill — a phone locked mid-turn, the route
|
|
88
|
+
* detached the dead response and the turn ran on to persist, GKE's autoscaler evicted the pod,
|
|
89
|
+
* and this drain saw NO connection in flight, so `process.exit(0)` ran 5 s after SIGTERM with the
|
|
90
|
+
* model call 32 s in. Nothing persisted, nothing logged (plans/FREE_AGENT.md §M.14).
|
|
91
|
+
*
|
|
63
92
|
* A SIGTERM before the listener is open (mid-boot kill) exits 0 immediately — nothing is
|
|
64
93
|
* registered anywhere and nothing is in flight.
|
|
65
94
|
*
|
|
66
95
|
* Supervisor compatibility (dev): ServePackageSupervisor SIGTERMs the child's process group and
|
|
67
96
|
* escalates to SIGKILL after its grace period (default 10s); its exit handler ignores exit codes
|
|
68
97
|
* for kills it initiated, so the drain-then-exit-0 shape cannot be misread. DEVELOPMENT defaults
|
|
69
|
-
* `drainDelayMs` to 0 so supervised restarts stay fast
|
|
98
|
+
* `drainDelayMs` to 0 so supervised restarts stay fast; a turn in flight under the supervisor is
|
|
99
|
+
* covered BEFORE the signal by its lease (the hold projection), not by this drain.
|
|
70
100
|
*/
|
|
71
101
|
var GracefulShutdown = /** @class */ (function () {
|
|
72
102
|
function GracefulShutdown(server, config) {
|
|
@@ -90,9 +120,50 @@ var GracefulShutdown = /** @class */ (function () {
|
|
|
90
120
|
var _a, _b;
|
|
91
121
|
return (_b = (_a = GracefulShutdown.instance) === null || _a === void 0 ? void 0 : _a.shuttingDown) !== null && _b !== void 0 ? _b : false;
|
|
92
122
|
};
|
|
123
|
+
/**
|
|
124
|
+
* Keep the process alive through a SIGTERM drain until the returned release is called (bounded
|
|
125
|
+
* by `shutdown.turnDrainMs`). `label` names the work in the drain's logs (`chat-turn:<id>`);
|
|
126
|
+
* `context` rides beside it (chat id, user id). Holding a label already held returns the
|
|
127
|
+
* existing release — one hold per label.
|
|
128
|
+
*/
|
|
129
|
+
GracefulShutdown.hold = function (label, context) {
|
|
130
|
+
var existing = GracefulShutdown.holds.get(label);
|
|
131
|
+
if (existing) {
|
|
132
|
+
return existing.release;
|
|
133
|
+
}
|
|
134
|
+
var release = function () {
|
|
135
|
+
var _a;
|
|
136
|
+
if (((_a = GracefulShutdown.holds.get(label)) === null || _a === void 0 ? void 0 : _a.release) !== release) {
|
|
137
|
+
return; // already released (or the label re-held since — that hold has its own release)
|
|
138
|
+
}
|
|
139
|
+
GracefulShutdown.holds.delete(label);
|
|
140
|
+
GracefulShutdown.notify('released', label);
|
|
141
|
+
if (GracefulShutdown.holds.size === 0) {
|
|
142
|
+
var waiters = GracefulShutdown.holdWaiters.splice(0, GracefulShutdown.holdWaiters.length);
|
|
143
|
+
for (var _i = 0, waiters_1 = waiters; _i < waiters_1.length; _i++) {
|
|
144
|
+
var resolve = waiters_1[_i];
|
|
145
|
+
resolve();
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
GracefulShutdown.holds.set(label, { hold: context ? { label: label, context: context } : { label: label }, release: release });
|
|
150
|
+
GracefulShutdown.notify('acquired', label);
|
|
151
|
+
return release;
|
|
152
|
+
};
|
|
153
|
+
/** Every hold outstanding right now, in acquisition order. */
|
|
154
|
+
GracefulShutdown.outstandingHolds = function () {
|
|
155
|
+
return Array.from(GracefulShutdown.holds.values()).map(function (entry) { return (__assign({}, entry.hold)); });
|
|
156
|
+
};
|
|
157
|
+
/** Follow holds as they are acquired and released. Returns the unsubscribe. */
|
|
158
|
+
GracefulShutdown.observeHolds = function (observer) {
|
|
159
|
+
GracefulShutdown.holdObservers.add(observer);
|
|
160
|
+
return function () {
|
|
161
|
+
GracefulShutdown.holdObservers.delete(observer);
|
|
162
|
+
};
|
|
163
|
+
};
|
|
93
164
|
GracefulShutdown.prototype.drainAndExit = function () {
|
|
94
165
|
return __awaiter(this, void 0, void 0, function () {
|
|
95
|
-
var drainDelayMs, drainTimeoutMs, drained, io;
|
|
166
|
+
var drainDelayMs, drainTimeoutMs, turnDrainMs, drained, io;
|
|
96
167
|
var _this = this;
|
|
97
168
|
return __generator(this, function (_a) {
|
|
98
169
|
switch (_a.label) {
|
|
@@ -107,8 +178,10 @@ var GracefulShutdown = /** @class */ (function () {
|
|
|
107
178
|
}
|
|
108
179
|
drainDelayMs = this.drainDelayMs();
|
|
109
180
|
drainTimeoutMs = this.drainTimeoutMs();
|
|
181
|
+
turnDrainMs = this.turnDrainMs();
|
|
110
182
|
this.logger.info({
|
|
111
|
-
message: "Received SIGTERM \u2014 /health-check now reports 503; accepting connections for another ".concat(drainDelayMs, "ms, then draining in-flight requests (bound: ").concat(drainTimeoutMs, "ms)"),
|
|
183
|
+
message: "Received SIGTERM \u2014 /health-check now reports 503; accepting connections for another ".concat(drainDelayMs, "ms, then draining in-flight requests (bound: ").concat(drainTimeoutMs, "ms) and ").concat(GracefulShutdown.holds.size, " hold(s) (bound: ").concat(turnDrainMs, "ms)"),
|
|
184
|
+
obj: { holds: GracefulShutdown.outstandingHolds() },
|
|
112
185
|
});
|
|
113
186
|
// 1. Readiness-propagation window: the LB observes the 503 while we still serve normally.
|
|
114
187
|
return [4 /*yield*/, this.sleep(drainDelayMs)];
|
|
@@ -124,9 +197,16 @@ var GracefulShutdown = /** @class */ (function () {
|
|
|
124
197
|
this.server.close();
|
|
125
198
|
}
|
|
126
199
|
this.server.closeIdleConnections();
|
|
127
|
-
|
|
200
|
+
// 3. Holds: work no connection represents (a detached chat turn). In-flight requests keep
|
|
201
|
+
// running meanwhile — the listener is closed, existing connections are not. Bounded.
|
|
202
|
+
return [4 /*yield*/, this.drainHolds(turnDrainMs)];
|
|
128
203
|
case 2:
|
|
129
|
-
// 3.
|
|
204
|
+
// 3. Holds: work no connection represents (a detached chat turn). In-flight requests keep
|
|
205
|
+
// running meanwhile — the listener is closed, existing connections are not. Bounded.
|
|
206
|
+
_a.sent();
|
|
207
|
+
return [4 /*yield*/, this.settled(drained, drainTimeoutMs)];
|
|
208
|
+
case 3:
|
|
209
|
+
// 4. Bounded: past the drain timeout, force-close what remains. Exit 0 either way.
|
|
130
210
|
if (!(_a.sent())) {
|
|
131
211
|
this.logger.warn({
|
|
132
212
|
message: "Drain exceeded its ".concat(drainTimeoutMs, "ms bound \u2014 force-closing the remaining connections"),
|
|
@@ -140,6 +220,37 @@ var GracefulShutdown = /** @class */ (function () {
|
|
|
140
220
|
});
|
|
141
221
|
});
|
|
142
222
|
};
|
|
223
|
+
GracefulShutdown.prototype.drainHolds = function (turnDrainMs) {
|
|
224
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
225
|
+
var abandoned;
|
|
226
|
+
return __generator(this, function (_a) {
|
|
227
|
+
switch (_a.label) {
|
|
228
|
+
case 0:
|
|
229
|
+
if (GracefulShutdown.holds.size === 0) {
|
|
230
|
+
return [2 /*return*/];
|
|
231
|
+
}
|
|
232
|
+
this.logger.info({
|
|
233
|
+
message: "Listener closed \u2014 waiting for ".concat(GracefulShutdown.holds.size, " hold(s) to release (bound: ").concat(turnDrainMs, "ms)"),
|
|
234
|
+
obj: { holds: GracefulShutdown.outstandingHolds() },
|
|
235
|
+
});
|
|
236
|
+
return [4 /*yield*/, this.settled(GracefulShutdown.whenNoHolds(), turnDrainMs)];
|
|
237
|
+
case 1:
|
|
238
|
+
if (_a.sent()) {
|
|
239
|
+
this.logger.info({ message: "Every hold released \u2014 continuing the drain" });
|
|
240
|
+
return [2 /*return*/];
|
|
241
|
+
}
|
|
242
|
+
abandoned = GracefulShutdown.outstandingHolds();
|
|
243
|
+
this.logger.warn({
|
|
244
|
+
message: "Hold drain exceeded its ".concat(turnDrainMs, "ms bound \u2014 abandoning ").concat(abandoned.length, " hold(s): ").concat(abandoned
|
|
245
|
+
.map(function (hold) { return hold.label; })
|
|
246
|
+
.join(', ')),
|
|
247
|
+
obj: { holds: abandoned },
|
|
248
|
+
});
|
|
249
|
+
return [2 /*return*/];
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
});
|
|
253
|
+
};
|
|
143
254
|
GracefulShutdown.prototype.exitNow = function () {
|
|
144
255
|
this.shuttingDown = true;
|
|
145
256
|
this.logger.info({ message: "Received SIGINT \u2014 exiting immediately" });
|
|
@@ -156,6 +267,32 @@ var GracefulShutdown = /** @class */ (function () {
|
|
|
156
267
|
var _a, _b;
|
|
157
268
|
return (_b = (_a = this.config.shutdown) === null || _a === void 0 ? void 0 : _a.drainTimeoutMs) !== null && _b !== void 0 ? _b : 30000;
|
|
158
269
|
};
|
|
270
|
+
GracefulShutdown.prototype.turnDrainMs = function () {
|
|
271
|
+
var _a, _b;
|
|
272
|
+
return (_b = (_a = this.config.shutdown) === null || _a === void 0 ? void 0 : _a.turnDrainMs) !== null && _b !== void 0 ? _b : 240000;
|
|
273
|
+
};
|
|
274
|
+
GracefulShutdown.whenNoHolds = function () {
|
|
275
|
+
if (GracefulShutdown.holds.size === 0) {
|
|
276
|
+
return Promise.resolve();
|
|
277
|
+
}
|
|
278
|
+
return new Promise(function (resolve) { return GracefulShutdown.holdWaiters.push(resolve); });
|
|
279
|
+
};
|
|
280
|
+
GracefulShutdown.notify = function (event, label) {
|
|
281
|
+
var _a;
|
|
282
|
+
for (var _i = 0, _b = Array.from(GracefulShutdown.holdObservers); _i < _b.length; _i++) {
|
|
283
|
+
var observer = _b[_i];
|
|
284
|
+
try {
|
|
285
|
+
(_a = observer[event]) === null || _a === void 0 ? void 0 : _a.call(observer, label);
|
|
286
|
+
}
|
|
287
|
+
catch (error) {
|
|
288
|
+
// An observer follows the holds; its failure never touches the hold itself.
|
|
289
|
+
GracefulShutdown.staticLogger.warn({
|
|
290
|
+
message: "A hold observer threw on ".concat(event),
|
|
291
|
+
obj: { label: label, error: error === null || error === void 0 ? void 0 : error.message },
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
};
|
|
159
296
|
/** Await a promise with a deadline; true if it settled in time. */
|
|
160
297
|
GracefulShutdown.prototype.settled = function (promise, ms) {
|
|
161
298
|
return __awaiter(this, void 0, void 0, function () {
|
|
@@ -178,6 +315,10 @@ var GracefulShutdown = /** @class */ (function () {
|
|
|
178
315
|
GracefulShutdown.prototype.sleep = function (ms) {
|
|
179
316
|
return new Promise(function (resolve) { return setTimeout(resolve, ms); });
|
|
180
317
|
};
|
|
318
|
+
GracefulShutdown.holds = new Map();
|
|
319
|
+
GracefulShutdown.holdObservers = new Set();
|
|
320
|
+
GracefulShutdown.holdWaiters = [];
|
|
321
|
+
GracefulShutdown.staticLogger = new logger_1.Logger({ name: 'GracefulShutdown' });
|
|
181
322
|
return GracefulShutdown;
|
|
182
323
|
}());
|
|
183
324
|
exports.GracefulShutdown = GracefulShutdown;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GracefulShutdown.js","sourceRoot":"","sources":["../../src/GracefulShutdown.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"GracefulShutdown.js","sourceRoot":"","sources":["../../src/GracefulShutdown.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reactApp.d.ts","sourceRoot":"","sources":["../../../src/routes/reactApp.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAA4B,MAAM,uBAAuB,CAAC;AAU/E,eAAO,MAAM,cAAc,iBAAkB,YAAY;;;yBAI1B,GAAG,YAAY,GAAG,KAAG,QAAQ,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"reactApp.d.ts","sourceRoot":"","sources":["../../../src/routes/reactApp.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAA4B,MAAM,uBAAuB,CAAC;AAU/E,eAAO,MAAM,cAAc,iBAAkB,YAAY;;;yBAI1B,GAAG,YAAY,GAAG,KAAG,QAAQ,IAAI,CAAC;CA+ChE,CAAC"}
|