@fnndsc/cumin 3.8.1 → 3.10.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/README.md +2 -2
- package/dist/cache/index.d.ts +5 -1
- package/dist/cache/index.js +9 -1
- package/dist/cache/index.js.map +1 -1
- package/dist/cache/listCache.d.ts +11 -0
- package/dist/cache/listCache.js +19 -0
- package/dist/cache/listCache.js.map +1 -1
- package/dist/cache/procCache.d.ts +118 -5
- package/dist/cache/procCache.js +213 -6
- package/dist/cache/procCache.js.map +1 -1
- package/dist/cache/procCheckpoint.d.ts +47 -0
- package/dist/cache/procCheckpoint.js +217 -0
- package/dist/cache/procCheckpoint.js.map +1 -0
- package/dist/cache/procPrompt.d.ts +34 -0
- package/dist/cache/procPrompt.js +25 -0
- package/dist/cache/procPrompt.js.map +1 -0
- package/dist/chrisapi/adapter.d.ts +23 -1
- package/dist/chrisapi/adapter.js +39 -0
- package/dist/chrisapi/adapter.js.map +1 -1
- package/dist/chrisapi/contract.d.ts +336 -0
- package/dist/chrisapi/contract.js +219 -0
- package/dist/chrisapi/contract.js.map +1 -0
- package/dist/connect/chrisConnection.d.ts +20 -0
- package/dist/connect/chrisConnection.js +33 -0
- package/dist/connect/chrisConnection.js.map +1 -1
- package/dist/feeds/chrisFeed.js +2 -1
- package/dist/feeds/chrisFeed.js.map +1 -1
- package/dist/groups/chrisGroups.d.ts +67 -1
- package/dist/groups/chrisGroups.js +171 -1
- package/dist/groups/chrisGroups.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.js +13 -1
- package/dist/index.js.map +1 -1
- package/dist/io/chrisIO.d.ts +14 -0
- package/dist/io/chrisIO.js +31 -2
- package/dist/io/chrisIO.js.map +1 -1
- package/dist/jobs/chrisJob.js +4 -0
- package/dist/jobs/chrisJob.js.map +1 -1
- package/dist/output/runtimeOutput.d.ts +49 -0
- package/dist/output/runtimeOutput.js +51 -0
- package/dist/output/runtimeOutput.js.map +1 -0
- package/dist/pacs/chrisPACS.d.ts +28 -0
- package/dist/pacs/chrisPACS.js +40 -21
- package/dist/pacs/chrisPACS.js.map +1 -1
- package/dist/path/chrisPath.js +3 -3
- package/dist/path/chrisPath.js.map +1 -1
- package/dist/pipelines/chrisPipeline.d.ts +4 -0
- package/dist/pipelines/chrisPipeline.js +1 -1
- package/dist/pipelines/chrisPipeline.js.map +1 -1
- package/dist/plugins/chrisPlugins.d.ts +8 -1
- package/dist/plugins/chrisPlugins.js +8 -1
- package/dist/plugins/chrisPlugins.js.map +1 -1
- package/dist/resources/chrisObjContext.d.ts +11 -0
- package/dist/resources/chrisObjContext.js +38 -2
- package/dist/resources/chrisObjContext.js.map +1 -1
- package/dist/resources/chrisResources.js +4 -0
- package/dist/resources/chrisResources.js.map +1 -1
- package/dist/users/chrisUsers.d.ts +56 -10
- package/dist/users/chrisUsers.js +149 -20
- package/dist/users/chrisUsers.js.map +1 -1
- package/dist/utils/retry.d.ts +29 -0
- package/dist/utils/retry.js +44 -0
- package/dist/utils/retry.js.map +1 -0
- package/package.json +19 -8
package/README.md
CHANGED
|
@@ -54,7 +54,7 @@ In the "Sandwich Model" architecture, `cumin` is the bottom layer (just above th
|
|
|
54
54
|
- **`ChrisIO`**: High-level IO operations, including recursive directory uploading (`uploadLocalPath`).
|
|
55
55
|
- **`ChRISResource.resources_getAll()`**: Generic pagination handler.
|
|
56
56
|
- **`ListCache`** (`listCache_get()`): Session-scoped directory listing cache for the VFS.
|
|
57
|
-
- **`ProcCache`** (`procCache_get()`): Session-scoped job monitoring
|
|
57
|
+
- **`ProcCache`** (`procCache_get()`): Session-scoped job monitoring DAG with versioned, identity-scoped daemon checkpoints. Restored topology remains usable while CUBE reconciliation runs; terminal status persists and active status refreshes on read. Powers the `/proc/jobs/` VFS provider in salsa.
|
|
58
58
|
|
|
59
59
|
## Developer Setup
|
|
60
60
|
|
|
@@ -75,4 +75,4 @@ To build the `cumin` library from source:
|
|
|
75
75
|
MIT — part of the [ChRIS Project](https://chrisproject.org).
|
|
76
76
|
|
|
77
77
|
---
|
|
78
|
-
_-30-_
|
|
78
|
+
_-30-_
|
package/dist/cache/index.d.ts
CHANGED
|
@@ -6,4 +6,8 @@
|
|
|
6
6
|
export { ListCache, listCache_get } from './listCache.js';
|
|
7
7
|
export type { CacheStats, CacheResult, CacheOptions } from './listCache.js';
|
|
8
8
|
export { ProcCache, procCache_get, status_isTerminal, PROC_TERMINAL_STATUSES } from './procCache.js';
|
|
9
|
-
export type { ProcInstance, ProcFeed, ProcFeedScopeCounts, ProcWarmupProgress } from './procCache.js';
|
|
9
|
+
export type { ProcInstance, ProcFeed, ProcFeedScopeCounts, ProcWarmupProgress, ProcCacheState, ProcCacheLifecycle, ProcCacheSnapshot, } from './procCache.js';
|
|
10
|
+
export { procPromptState_get, PROC_PROMPT_STATES } from './procPrompt.js';
|
|
11
|
+
export type { ProcPromptState, ProcPromptProgress } from './procPrompt.js';
|
|
12
|
+
export { procCheckpointPath_get, procCheckpoint_restore, procCheckpoint_save, procCheckpoint_watch, } from './procCheckpoint.js';
|
|
13
|
+
export type { ProcCheckpointRestoreResult } from './procCheckpoint.js';
|
package/dist/cache/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.PROC_TERMINAL_STATUSES = exports.status_isTerminal = exports.procCache_get = exports.ProcCache = exports.listCache_get = exports.ListCache = void 0;
|
|
3
|
+
exports.procCheckpoint_watch = exports.procCheckpoint_save = exports.procCheckpoint_restore = exports.procCheckpointPath_get = exports.PROC_PROMPT_STATES = exports.procPromptState_get = exports.PROC_TERMINAL_STATUSES = exports.status_isTerminal = exports.procCache_get = exports.ProcCache = exports.listCache_get = exports.ListCache = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* @file Cache module exports.
|
|
6
6
|
*
|
|
@@ -14,4 +14,12 @@ Object.defineProperty(exports, "ProcCache", { enumerable: true, get: function ()
|
|
|
14
14
|
Object.defineProperty(exports, "procCache_get", { enumerable: true, get: function () { return procCache_js_1.procCache_get; } });
|
|
15
15
|
Object.defineProperty(exports, "status_isTerminal", { enumerable: true, get: function () { return procCache_js_1.status_isTerminal; } });
|
|
16
16
|
Object.defineProperty(exports, "PROC_TERMINAL_STATUSES", { enumerable: true, get: function () { return procCache_js_1.PROC_TERMINAL_STATUSES; } });
|
|
17
|
+
var procPrompt_js_1 = require("./procPrompt.js");
|
|
18
|
+
Object.defineProperty(exports, "procPromptState_get", { enumerable: true, get: function () { return procPrompt_js_1.procPromptState_get; } });
|
|
19
|
+
Object.defineProperty(exports, "PROC_PROMPT_STATES", { enumerable: true, get: function () { return procPrompt_js_1.PROC_PROMPT_STATES; } });
|
|
20
|
+
var procCheckpoint_js_1 = require("./procCheckpoint.js");
|
|
21
|
+
Object.defineProperty(exports, "procCheckpointPath_get", { enumerable: true, get: function () { return procCheckpoint_js_1.procCheckpointPath_get; } });
|
|
22
|
+
Object.defineProperty(exports, "procCheckpoint_restore", { enumerable: true, get: function () { return procCheckpoint_js_1.procCheckpoint_restore; } });
|
|
23
|
+
Object.defineProperty(exports, "procCheckpoint_save", { enumerable: true, get: function () { return procCheckpoint_js_1.procCheckpoint_save; } });
|
|
24
|
+
Object.defineProperty(exports, "procCheckpoint_watch", { enumerable: true, get: function () { return procCheckpoint_js_1.procCheckpoint_watch; } });
|
|
17
25
|
//# sourceMappingURL=index.js.map
|
package/dist/cache/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cache/index.ts"],"names":[],"mappings":";;;AAAA;;;;GAIG;AACH,+CAA0D;AAAjD,yGAAA,SAAS,OAAA;AAAE,6GAAA,aAAa,OAAA;AAEjC,+CAAqG;AAA5F,yGAAA,SAAS,OAAA;AAAE,6GAAA,aAAa,OAAA;AAAE,iHAAA,iBAAiB,OAAA;AAAE,sHAAA,sBAAsB,OAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cache/index.ts"],"names":[],"mappings":";;;AAAA;;;;GAIG;AACH,+CAA0D;AAAjD,yGAAA,SAAS,OAAA;AAAE,6GAAA,aAAa,OAAA;AAEjC,+CAAqG;AAA5F,yGAAA,SAAS,OAAA;AAAE,6GAAA,aAAa,OAAA;AAAE,iHAAA,iBAAiB,OAAA;AAAE,sHAAA,sBAAsB,OAAA;AAU5E,iDAA0E;AAAjE,oHAAA,mBAAmB,OAAA;AAAE,mHAAA,kBAAkB,OAAA;AAEhD,yDAK6B;AAJ3B,2HAAA,sBAAsB,OAAA;AACtB,2HAAA,sBAAsB,OAAA;AACtB,wHAAA,mBAAmB,OAAA;AACnB,yHAAA,oBAAoB,OAAA"}
|
|
@@ -144,6 +144,17 @@ export declare class ListCache {
|
|
|
144
144
|
* @param path - Optional specific path to invalidate. If omitted, clears entire cache.
|
|
145
145
|
*/
|
|
146
146
|
cache_invalidate(path?: string): void;
|
|
147
|
+
/**
|
|
148
|
+
* Invalidates a path and every cached listing beneath it.
|
|
149
|
+
* Called by operations that remove or replace an entire directory tree
|
|
150
|
+
* (rm -r, a directory re-upload): nested listings cached before the
|
|
151
|
+
* mutation would otherwise serve the old tree's contents until their TTL
|
|
152
|
+
* expires, with no refresh hint.
|
|
153
|
+
*
|
|
154
|
+
* @param path - Root of the subtree to invalidate. The entry for the path
|
|
155
|
+
* itself is removed along with all entries under `path + '/'`.
|
|
156
|
+
*/
|
|
157
|
+
cache_invalidateTree(path: string): void;
|
|
147
158
|
/**
|
|
148
159
|
* @deprecated Use cache without cwd tracking. Cache persists across navigation.
|
|
149
160
|
* This method is kept for backward compatibility but does nothing.
|
package/dist/cache/listCache.js
CHANGED
|
@@ -178,6 +178,25 @@ class ListCache {
|
|
|
178
178
|
this.cache.clear();
|
|
179
179
|
}
|
|
180
180
|
}
|
|
181
|
+
/**
|
|
182
|
+
* Invalidates a path and every cached listing beneath it.
|
|
183
|
+
* Called by operations that remove or replace an entire directory tree
|
|
184
|
+
* (rm -r, a directory re-upload): nested listings cached before the
|
|
185
|
+
* mutation would otherwise serve the old tree's contents until their TTL
|
|
186
|
+
* expires, with no refresh hint.
|
|
187
|
+
*
|
|
188
|
+
* @param path - Root of the subtree to invalidate. The entry for the path
|
|
189
|
+
* itself is removed along with all entries under `path + '/'`.
|
|
190
|
+
*/
|
|
191
|
+
cache_invalidateTree(path) {
|
|
192
|
+
this.cache.delete(path);
|
|
193
|
+
const prefix = path.endsWith("/") ? path : `${path}/`;
|
|
194
|
+
for (const key of this.cache.keys()) {
|
|
195
|
+
if (key.startsWith(prefix)) {
|
|
196
|
+
this.cache.delete(key);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
181
200
|
/**
|
|
182
201
|
* @deprecated Use cache without cwd tracking. Cache persists across navigation.
|
|
183
202
|
* This method is kept for backward compatibility but does nothing.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"listCache.js","sourceRoot":"","sources":["../../src/cache/listCache.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;GAaG;;;
|
|
1
|
+
{"version":3,"file":"listCache.js","sourceRoot":"","sources":["../../src/cache/listCache.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;GAaG;;;AAoWH,sCAEC;AAnSD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,MAAa,SAAS;IA4BpB;;OAEG;IACH;QA5BA,mCAAmC;QAC3B,UAAK,GAAqC,IAAI,GAAG,EAAE,CAAC;QAE5D,4CAA4C;QACpC,eAAU,GAAW,GAAG,CAAC;QAEjC,sDAAsD;QAC9C,eAAU,GAAW,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;QAE3C,uCAAuC;QAC/B,cAAS,GAAwB,IAAI,GAAG,CAAC;YAC/C,CAAC,SAAS,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,EAAM,oCAAoC;YACrE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,EAAU,gCAAgC;YAClE,CAAC,MAAM,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,EAAU,iCAAiC;YACnE,CAAC,UAAU,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,EAAO,uBAAuB;SAC1D,CAAC,CAAC;QAEH,wBAAwB;QAChB,UAAK,GAAG;YACd,IAAI,EAAE,CAAC;YACP,MAAM,EAAE,CAAC;YACT,SAAS,EAAE,CAAC;YACZ,SAAS,EAAE,CAAC;SACb,CAAC;IAKqB,CAAC;IAExB;;;;OAIG;IACH,MAAM,CAAC,YAAY;QACjB,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC;YACxB,SAAS,CAAC,QAAQ,GAAG,IAAI,SAAS,EAAE,CAAC;QACvC,CAAC;QACD,OAAO,SAAS,CAAC,QAAQ,CAAC;IAC5B,CAAC;IAED;;;;;OAKG;IACH,SAAS,CAAc,IAAY;QACjC,MAAM,KAAK,GAAoC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAEpE,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YACpB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,2CAA2C;QAC3C,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACxB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAE5B,sBAAsB;QACtB,MAAM,GAAG,GAAW,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,SAAS,CAAC;QACjD,MAAM,KAAK,GAAY,CAAC,KAAK,CAAC,KAAK,IAAI,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC;QAEvD,IAAI,KAAK,EAAE,CAAC;YACV,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QACpB,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC;QACzB,CAAC;QAED,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,IAAS,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;IAC/C,CAAC;IAED;;;;;;OAMG;IACH,SAAS,CAAc,IAAY,EAAE,IAAO,EAAE,OAAsB;QAClE,mDAAmD;QACnD,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACzB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC;QAED,MAAM,GAAG,GAAW,OAAO,EAAE,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAEvD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE;YACnB,IAAI;YACJ,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,KAAK,EAAE,OAAO,EAAE,KAAK,IAAI,KAAK;YAC9B,GAAG;SACJ,CAAC,CAAC;QAEH,6BAA6B;QAC7B,IAAI,CAAC,SAAS,EAAE,CAAC;IACnB,CAAC;IAED;;;;;OAKG;IACH,eAAe,CAAC,IAAY;QAC1B,MAAM,KAAK,GAAoC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACpE,IAAI,KAAK,EAAE,CAAC;YACV,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC;QACrB,CAAC;IACH,CAAC;IAED;;;;;;OAMG;IACH,YAAY,CAAc,IAAY,EAAE,OAAuB;QAC7D,MAAM,KAAK,GAAoC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACpE,IAAI,KAAK,EAAE,CAAC;YACV,KAAK,CAAC,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,IAAS,CAAC,CAAC;YACtC,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAE,kBAAkB;YACjD,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,CAAY,qBAAqB;QACvD,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACH,gBAAgB,CAAC,IAAa;QAC5B,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACrB,CAAC;IACH,CAAC;IAED;;;;;;;;;OASG;IACH,oBAAoB,CAAC,IAAY;QAC/B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACxB,MAAM,MAAM,GAAW,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC;QAC9D,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;YACpC,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC3B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACzB,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACH,UAAU,CAAC,OAAe;QACxB,qDAAqD;QACrD,oDAAoD;IACtD,CAAC;IAED;;;;;OAKG;IACK,OAAO,CAAC,IAAY;QAC1B,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAC7B,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAE,CAAC;QACnC,CAAC;QAED,KAAK,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YAC5C,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC1B,MAAM,KAAK,GAAW,IAAI,MAAM,CAAC,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC;gBAC3E,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;oBACrB,OAAO,GAAG,CAAC;gBACb,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;IAED;;OAEG;IACK,SAAS;QACf,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;YACzC,MAAM,SAAS,GAAuB,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC;YACrE,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;gBAC5B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;gBAC7B,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC;YACzB,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAE,wCAAwC;YAClD,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,SAAS;QACP,IAAI,SAAS,GAAW,CAAC,CAAC;QAC1B,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;YACxC,qCAAqC;YACrC,SAAS,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;QACjD,CAAC;QAED,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI;YACrB,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM;YACzB,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS;YAC/B,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS;YAC/B,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI;YACxB,SAAS;SACV,CAAC;IACJ,CAAC;IAED;;;OAGG;IACH,WAAW;QACT,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC;QACpB,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;QACtB,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC;QACzB,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC;IAC3B,CAAC;CACF;AAtPD,8BAsPC;AAED;;;;GAIG;AACH,SAAgB,aAAa;IAC3B,OAAO,SAAS,CAAC,YAAY,EAAE,CAAC;AAClC,CAAC"}
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
* @file Process Cache
|
|
3
3
|
*
|
|
4
4
|
* Session-scoped cache of ChRIS feed topology. Separates permanent data
|
|
5
|
-
* (instance DAG structure) from volatile
|
|
5
|
+
* (instance DAG structure and terminal status) from volatile active status.
|
|
6
6
|
*
|
|
7
7
|
* Design decisions:
|
|
8
8
|
* - Topology (id, feedID, parentID, pluginName) is permanent once written.
|
|
9
|
-
* -
|
|
9
|
+
* - Terminal status is immutable and checkpointed; active status refreshes live.
|
|
10
10
|
* - Feed job counters (finishedJobs etc.) give aggregate feed status
|
|
11
11
|
* without per-instance API calls.
|
|
12
12
|
* - topologyLoaded distinguishes "loaded but 0 instances" from "not yet loaded".
|
|
@@ -67,6 +67,12 @@ export interface ProcInstance {
|
|
|
67
67
|
pluginType?: string;
|
|
68
68
|
/** null until first cat — immutable once populated. */
|
|
69
69
|
params: Record<string, unknown> | null;
|
|
70
|
+
/**
|
|
71
|
+
* Authoritative CUBE output directory, resolved lazily for the `/proc` data
|
|
72
|
+
* link. `undefined` means not looked up; `null` means CUBE reported none.
|
|
73
|
+
* This navigation convenience is deliberately excluded from checkpoints.
|
|
74
|
+
*/
|
|
75
|
+
outputPath?: string | null;
|
|
70
76
|
/**
|
|
71
77
|
* Last known job status. Terminal statuses (see {@link PROC_TERMINAL_STATUSES})
|
|
72
78
|
* are immutable and kept permanently; active statuses are refreshed live.
|
|
@@ -98,16 +104,39 @@ export declare function status_isTerminal(status: string | null | undefined): bo
|
|
|
98
104
|
* total is zero until the server reports the visible plugin-instance count.
|
|
99
105
|
* active becomes true when observable page progress begins, and false when the
|
|
100
106
|
* sweep completes or aborts. Use the topology lifecycle to detect an earlier
|
|
101
|
-
* running
|
|
107
|
+
* running state before the first page arrives.
|
|
102
108
|
*/
|
|
103
109
|
export interface ProcWarmupProgress {
|
|
104
110
|
loaded: number;
|
|
105
111
|
total: number;
|
|
106
112
|
active: boolean;
|
|
107
113
|
}
|
|
114
|
+
/** Availability and freshness states for the persistent process cache. */
|
|
115
|
+
export type ProcCacheState = 'empty' | 'restored' | 'reconciling' | 'current' | 'failed';
|
|
108
116
|
/**
|
|
109
|
-
*
|
|
110
|
-
*
|
|
117
|
+
* Persistent process-cache freshness metadata.
|
|
118
|
+
*
|
|
119
|
+
* @property state - Current availability and reconciliation state.
|
|
120
|
+
* @property checkpointAt - ISO timestamp of the latest durable checkpoint.
|
|
121
|
+
*/
|
|
122
|
+
export interface ProcCacheLifecycle {
|
|
123
|
+
state: ProcCacheState;
|
|
124
|
+
checkpointAt?: string;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Serializable topology retained across daemon restarts.
|
|
128
|
+
*
|
|
129
|
+
* @property feeds - Visible feed metadata.
|
|
130
|
+
* @property instances - Normalized plugin-instance topology.
|
|
131
|
+
* @property topologyLoaded - Feed IDs whose instance topology is complete.
|
|
132
|
+
*/
|
|
133
|
+
export interface ProcCacheSnapshot {
|
|
134
|
+
feeds: ProcFeed[];
|
|
135
|
+
instances: ProcInstance[];
|
|
136
|
+
topologyLoaded: number[];
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Session-scoped cache of feed and instance topology with restorable terminal state.
|
|
111
140
|
*/
|
|
112
141
|
export declare class ProcCache {
|
|
113
142
|
private static _instance;
|
|
@@ -124,10 +153,33 @@ export declare class ProcCache {
|
|
|
124
153
|
private _warmupProgress;
|
|
125
154
|
/** Whether initial feed index has been built. */
|
|
126
155
|
private _built;
|
|
156
|
+
private lifecycle;
|
|
157
|
+
private listeners;
|
|
127
158
|
private constructor();
|
|
128
159
|
static instance_get(): ProcCache;
|
|
129
160
|
get built(): boolean;
|
|
130
161
|
get warmupComplete(): boolean;
|
|
162
|
+
/**
|
|
163
|
+
* Returns a copy of the current cache lifecycle metadata.
|
|
164
|
+
*
|
|
165
|
+
* @returns Current cache state and checkpoint timestamp.
|
|
166
|
+
*/
|
|
167
|
+
lifecycle_get(): ProcCacheLifecycle;
|
|
168
|
+
/**
|
|
169
|
+
* Changes the cache freshness state.
|
|
170
|
+
*
|
|
171
|
+
* @param state - New lifecycle state.
|
|
172
|
+
* @returns Nothing.
|
|
173
|
+
*/
|
|
174
|
+
lifecycle_set(state: ProcCacheState): void;
|
|
175
|
+
/**
|
|
176
|
+
* Registers a callback for checkpoint-worthy cache mutations.
|
|
177
|
+
*
|
|
178
|
+
* @param listener - Callback invoked after a cache mutation.
|
|
179
|
+
* @returns Function that unregisters the callback.
|
|
180
|
+
*/
|
|
181
|
+
changeListener_add(listener: () => void): () => void;
|
|
182
|
+
private change_emit;
|
|
131
183
|
/**
|
|
132
184
|
* Adds or updates a feed entry.
|
|
133
185
|
*/
|
|
@@ -149,6 +201,14 @@ export declare class ProcCache {
|
|
|
149
201
|
* Removes a feed and all its instances from the cache.
|
|
150
202
|
*/
|
|
151
203
|
feed_remove(feedID: number): void;
|
|
204
|
+
/**
|
|
205
|
+
* Replaces the visible feed set while preserving topology for retained feeds.
|
|
206
|
+
*
|
|
207
|
+
* @param feeds - Authoritative feeds visible to the current identity.
|
|
208
|
+
* @returns IDs requiring topology reconciliation because they are new, their
|
|
209
|
+
* aggregate job counts changed, or they still have active work.
|
|
210
|
+
*/
|
|
211
|
+
feeds_reconcile(feeds: ProcFeed[]): number[];
|
|
152
212
|
/**
|
|
153
213
|
* Adds a plugin instance to the topology cache.
|
|
154
214
|
*/
|
|
@@ -169,10 +229,36 @@ export declare class ProcCache {
|
|
|
169
229
|
* Removes an instance from the topology cache.
|
|
170
230
|
*/
|
|
171
231
|
instance_remove(id: number): void;
|
|
232
|
+
/**
|
|
233
|
+
* Removes instances absent from an authoritative topology sweep.
|
|
234
|
+
*
|
|
235
|
+
* @param instanceIDs - Instance IDs returned by the completed CUBE sweep.
|
|
236
|
+
* @returns Nothing.
|
|
237
|
+
*/
|
|
238
|
+
topology_reconcile(instanceIDs: Set<number>): void;
|
|
172
239
|
/**
|
|
173
240
|
* Updates cached params for an instance (on first cat).
|
|
174
241
|
*/
|
|
175
242
|
params_update(id: number, params: Record<string, unknown>): void;
|
|
243
|
+
/**
|
|
244
|
+
* Stores the lazily resolved CUBE output path for one instance.
|
|
245
|
+
*
|
|
246
|
+
* @param id - Plugin-instance ID whose output location was resolved.
|
|
247
|
+
* @param outputPath - Absolute CFS output directory, or null when absent.
|
|
248
|
+
* @returns Nothing.
|
|
249
|
+
*/
|
|
250
|
+
outputPath_update(id: number, outputPath: string | null): void;
|
|
251
|
+
/**
|
|
252
|
+
* Finds the closest cached job output containing a CFS path.
|
|
253
|
+
*
|
|
254
|
+
* An output path is a directory boundary: `/home/alice/run` contains
|
|
255
|
+
* `/home/alice/run/result.txt`, but not `/home/alice/run-old`.
|
|
256
|
+
*
|
|
257
|
+
* @param cfsPath - Absolute CFS path to resolve against live-session outputs.
|
|
258
|
+
* @returns The closest producing instance, or undefined when no output path
|
|
259
|
+
* known in this session contains the path.
|
|
260
|
+
*/
|
|
261
|
+
outputPath_match(cfsPath: string): ProcInstance | undefined;
|
|
176
262
|
/**
|
|
177
263
|
* Updates the cached status for an instance. Terminal (settled) statuses are
|
|
178
264
|
* never overwritten — once finished, a job's status is immutable.
|
|
@@ -211,6 +297,12 @@ export declare class ProcCache {
|
|
|
211
297
|
warmup_abort(): void;
|
|
212
298
|
warmup_progress(loaded: number, total: number): void;
|
|
213
299
|
warmupProgress_get(): ProcWarmupProgress;
|
|
300
|
+
/**
|
|
301
|
+
* Resets reconciliation progress while retaining restored topology.
|
|
302
|
+
*
|
|
303
|
+
* @returns Nothing.
|
|
304
|
+
*/
|
|
305
|
+
warmup_reset(): void;
|
|
214
306
|
/**
|
|
215
307
|
* Reconstructs the full /proc/jobs path for a given instance ID.
|
|
216
308
|
*
|
|
@@ -233,6 +325,27 @@ export declare class ProcCache {
|
|
|
233
325
|
*/
|
|
234
326
|
instances_find(term: string): ProcInstance[];
|
|
235
327
|
built_set(): void;
|
|
328
|
+
/**
|
|
329
|
+
* Creates a persistence-safe snapshot without parameters or active statuses.
|
|
330
|
+
*
|
|
331
|
+
* @returns Serializable feed and terminal-topology state.
|
|
332
|
+
*/
|
|
333
|
+
snapshot_create(): ProcCacheSnapshot;
|
|
334
|
+
/**
|
|
335
|
+
* Replaces in-memory topology with a validated persistent snapshot.
|
|
336
|
+
*
|
|
337
|
+
* @param snapshot - Previously validated snapshot data.
|
|
338
|
+
* @param checkpointAt - ISO timestamp when the checkpoint was written.
|
|
339
|
+
* @returns Nothing.
|
|
340
|
+
*/
|
|
341
|
+
snapshot_restore(snapshot: ProcCacheSnapshot, checkpointAt: string): void;
|
|
342
|
+
/**
|
|
343
|
+
* Records the timestamp of a successful durable save.
|
|
344
|
+
*
|
|
345
|
+
* @param checkpointAt - ISO timestamp written into the checkpoint.
|
|
346
|
+
* @returns Nothing.
|
|
347
|
+
*/
|
|
348
|
+
checkpoint_mark(checkpointAt: string): void;
|
|
236
349
|
/**
|
|
237
350
|
* Clears all cache data. Called before a full rebuild.
|
|
238
351
|
*/
|
package/dist/cache/procCache.js
CHANGED
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
* @file Process Cache
|
|
4
4
|
*
|
|
5
5
|
* Session-scoped cache of ChRIS feed topology. Separates permanent data
|
|
6
|
-
* (instance DAG structure) from volatile
|
|
6
|
+
* (instance DAG structure and terminal status) from volatile active status.
|
|
7
7
|
*
|
|
8
8
|
* Design decisions:
|
|
9
9
|
* - Topology (id, feedID, parentID, pluginName) is permanent once written.
|
|
10
|
-
* -
|
|
10
|
+
* - Terminal status is immutable and checkpointed; active status refreshes live.
|
|
11
11
|
* - Feed job counters (finishedJobs etc.) give aggregate feed status
|
|
12
12
|
* without per-instance API calls.
|
|
13
13
|
* - topologyLoaded distinguishes "loaded but 0 instances" from "not yet loaded".
|
|
@@ -21,6 +21,23 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
21
21
|
exports.ProcCache = exports.PROC_TERMINAL_STATUSES = void 0;
|
|
22
22
|
exports.status_isTerminal = status_isTerminal;
|
|
23
23
|
exports.procCache_get = procCache_get;
|
|
24
|
+
/** Feed counters whose changes can alter a feed's plugin-instance topology. */
|
|
25
|
+
const FEED_TOPOLOGY_COUNTERS = [
|
|
26
|
+
'finishedJobs',
|
|
27
|
+
'erroredJobs',
|
|
28
|
+
'startedJobs',
|
|
29
|
+
'scheduledJobs',
|
|
30
|
+
'cancelledJobs',
|
|
31
|
+
'createdJobs',
|
|
32
|
+
];
|
|
33
|
+
/** Reports whether a feed has work which can still change after checkpointing. */
|
|
34
|
+
function feed_isActive(feed) {
|
|
35
|
+
return feed.startedJobs > 0 || feed.scheduledJobs > 0 || feed.createdJobs > 0;
|
|
36
|
+
}
|
|
37
|
+
/** Reports whether two feed summaries indicate different instance topology. */
|
|
38
|
+
function feedTopology_changed(previous, current) {
|
|
39
|
+
return FEED_TOPOLOGY_COUNTERS.some((counter) => previous[counter] !== current[counter]);
|
|
40
|
+
}
|
|
24
41
|
/**
|
|
25
42
|
* Job statuses that never change once reached. An instance in one of these states
|
|
26
43
|
* is settled — its status can be cached permanently rather than re-fetched.
|
|
@@ -40,8 +57,7 @@ function status_isTerminal(status) {
|
|
|
40
57
|
return status != null && exports.PROC_TERMINAL_STATUSES.has(status);
|
|
41
58
|
}
|
|
42
59
|
/**
|
|
43
|
-
* Session-scoped cache of feed and instance topology.
|
|
44
|
-
* Status is never stored — always fetched live from the API.
|
|
60
|
+
* Session-scoped cache of feed and instance topology with restorable terminal state.
|
|
45
61
|
*/
|
|
46
62
|
class ProcCache {
|
|
47
63
|
constructor() {
|
|
@@ -58,6 +74,8 @@ class ProcCache {
|
|
|
58
74
|
this._warmupProgress = { loaded: 0, total: 0, active: false };
|
|
59
75
|
/** Whether initial feed index has been built. */
|
|
60
76
|
this._built = false;
|
|
77
|
+
this.lifecycle = { state: 'empty' };
|
|
78
|
+
this.listeners = new Set();
|
|
61
79
|
}
|
|
62
80
|
static instance_get() {
|
|
63
81
|
if (!ProcCache._instance) {
|
|
@@ -67,6 +85,36 @@ class ProcCache {
|
|
|
67
85
|
}
|
|
68
86
|
get built() { return this._built; }
|
|
69
87
|
get warmupComplete() { return this._warmupComplete; }
|
|
88
|
+
/**
|
|
89
|
+
* Returns a copy of the current cache lifecycle metadata.
|
|
90
|
+
*
|
|
91
|
+
* @returns Current cache state and checkpoint timestamp.
|
|
92
|
+
*/
|
|
93
|
+
lifecycle_get() { return { ...this.lifecycle }; }
|
|
94
|
+
/**
|
|
95
|
+
* Changes the cache freshness state.
|
|
96
|
+
*
|
|
97
|
+
* @param state - New lifecycle state.
|
|
98
|
+
* @returns Nothing.
|
|
99
|
+
*/
|
|
100
|
+
lifecycle_set(state) {
|
|
101
|
+
this.lifecycle = { ...this.lifecycle, state };
|
|
102
|
+
this.change_emit();
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Registers a callback for checkpoint-worthy cache mutations.
|
|
106
|
+
*
|
|
107
|
+
* @param listener - Callback invoked after a cache mutation.
|
|
108
|
+
* @returns Function that unregisters the callback.
|
|
109
|
+
*/
|
|
110
|
+
changeListener_add(listener) {
|
|
111
|
+
this.listeners.add(listener);
|
|
112
|
+
return () => { this.listeners.delete(listener); };
|
|
113
|
+
}
|
|
114
|
+
change_emit() {
|
|
115
|
+
for (const listener of this.listeners)
|
|
116
|
+
listener();
|
|
117
|
+
}
|
|
70
118
|
// ── Feed ──────────────────────────────────────────────────────────────────
|
|
71
119
|
/**
|
|
72
120
|
* Adds or updates a feed entry.
|
|
@@ -76,6 +124,7 @@ class ProcCache {
|
|
|
76
124
|
if (!this.feedRoots.has(feed.id)) {
|
|
77
125
|
this.feedRoots.set(feed.id, []);
|
|
78
126
|
}
|
|
127
|
+
this.change_emit();
|
|
79
128
|
}
|
|
80
129
|
feed_get(feedID) {
|
|
81
130
|
return this.feeds.get(feedID);
|
|
@@ -119,6 +168,30 @@ class ProcCache {
|
|
|
119
168
|
this.instance_remove(inst.id);
|
|
120
169
|
}
|
|
121
170
|
this.feedRoots.delete(feedID);
|
|
171
|
+
this.change_emit();
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Replaces the visible feed set while preserving topology for retained feeds.
|
|
175
|
+
*
|
|
176
|
+
* @param feeds - Authoritative feeds visible to the current identity.
|
|
177
|
+
* @returns IDs requiring topology reconciliation because they are new, their
|
|
178
|
+
* aggregate job counts changed, or they still have active work.
|
|
179
|
+
*/
|
|
180
|
+
feeds_reconcile(feeds) {
|
|
181
|
+
const reconciliationTargets = [];
|
|
182
|
+
const visible = new Set(feeds.map((feed) => feed.id));
|
|
183
|
+
for (const feedID of this.feedIDs_get()) {
|
|
184
|
+
if (!visible.has(feedID))
|
|
185
|
+
this.feed_remove(feedID);
|
|
186
|
+
}
|
|
187
|
+
for (const feed of feeds) {
|
|
188
|
+
const previous = this.feed_get(feed.id);
|
|
189
|
+
if (!previous || feedTopology_changed(previous, feed) || feed_isActive(feed)) {
|
|
190
|
+
reconciliationTargets.push(feed.id);
|
|
191
|
+
}
|
|
192
|
+
this.feed_add(feed);
|
|
193
|
+
}
|
|
194
|
+
return reconciliationTargets;
|
|
122
195
|
}
|
|
123
196
|
// ── Instance ──────────────────────────────────────────────────────────────
|
|
124
197
|
/**
|
|
@@ -140,6 +213,7 @@ class ProcCache {
|
|
|
140
213
|
this.children.set(inst.parentID, kids);
|
|
141
214
|
}
|
|
142
215
|
}
|
|
216
|
+
this.change_emit();
|
|
143
217
|
}
|
|
144
218
|
instance_get(id) {
|
|
145
219
|
return this.instances.get(id);
|
|
@@ -191,6 +265,22 @@ class ProcCache {
|
|
|
191
265
|
const kids = this.children.get(inst.parentID) ?? [];
|
|
192
266
|
this.children.set(inst.parentID, kids.filter((k) => k !== id));
|
|
193
267
|
}
|
|
268
|
+
this.change_emit();
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Removes instances absent from an authoritative topology sweep.
|
|
272
|
+
*
|
|
273
|
+
* @param instanceIDs - Instance IDs returned by the completed CUBE sweep.
|
|
274
|
+
* @returns Nothing.
|
|
275
|
+
*/
|
|
276
|
+
topology_reconcile(instanceIDs) {
|
|
277
|
+
for (const id of Array.from(this.instances.keys())) {
|
|
278
|
+
if (!instanceIDs.has(id))
|
|
279
|
+
this.instance_remove(id);
|
|
280
|
+
}
|
|
281
|
+
for (const feedID of this.feedIDs_get())
|
|
282
|
+
this.topologyLoaded.add(feedID);
|
|
283
|
+
this.change_emit();
|
|
194
284
|
}
|
|
195
285
|
/**
|
|
196
286
|
* Updates cached params for an instance (on first cat).
|
|
@@ -200,6 +290,46 @@ class ProcCache {
|
|
|
200
290
|
if (inst)
|
|
201
291
|
inst.params = params;
|
|
202
292
|
}
|
|
293
|
+
/**
|
|
294
|
+
* Stores the lazily resolved CUBE output path for one instance.
|
|
295
|
+
*
|
|
296
|
+
* @param id - Plugin-instance ID whose output location was resolved.
|
|
297
|
+
* @param outputPath - Absolute CFS output directory, or null when absent.
|
|
298
|
+
* @returns Nothing.
|
|
299
|
+
*/
|
|
300
|
+
outputPath_update(id, outputPath) {
|
|
301
|
+
const inst = this.instances.get(id);
|
|
302
|
+
if (inst)
|
|
303
|
+
inst.outputPath = outputPath;
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Finds the closest cached job output containing a CFS path.
|
|
307
|
+
*
|
|
308
|
+
* An output path is a directory boundary: `/home/alice/run` contains
|
|
309
|
+
* `/home/alice/run/result.txt`, but not `/home/alice/run-old`.
|
|
310
|
+
*
|
|
311
|
+
* @param cfsPath - Absolute CFS path to resolve against live-session outputs.
|
|
312
|
+
* @returns The closest producing instance, or undefined when no output path
|
|
313
|
+
* known in this session contains the path.
|
|
314
|
+
*/
|
|
315
|
+
outputPath_match(cfsPath) {
|
|
316
|
+
const cleanPath = cfsPath.length > 1 && cfsPath.endsWith('/')
|
|
317
|
+
? cfsPath.slice(0, -1)
|
|
318
|
+
: cfsPath;
|
|
319
|
+
let closest;
|
|
320
|
+
for (const inst of this.instances.values()) {
|
|
321
|
+
const outputPath = inst.outputPath;
|
|
322
|
+
if (!outputPath)
|
|
323
|
+
continue;
|
|
324
|
+
const isAncestor = outputPath === '/'
|
|
325
|
+
? cleanPath.startsWith('/')
|
|
326
|
+
: cleanPath === outputPath || cleanPath.startsWith(`${outputPath}/`);
|
|
327
|
+
if (isAncestor && (!closest || outputPath.length > (closest.outputPath?.length ?? 0))) {
|
|
328
|
+
closest = inst;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
return closest;
|
|
332
|
+
}
|
|
203
333
|
/**
|
|
204
334
|
* Updates the cached status for an instance. Terminal (settled) statuses are
|
|
205
335
|
* never overwritten — once finished, a job's status is immutable.
|
|
@@ -213,7 +343,10 @@ class ProcCache {
|
|
|
213
343
|
return;
|
|
214
344
|
if (status_isTerminal(inst.status))
|
|
215
345
|
return;
|
|
216
|
-
inst.status
|
|
346
|
+
if (inst.status !== status) {
|
|
347
|
+
inst.status = status;
|
|
348
|
+
this.change_emit();
|
|
349
|
+
}
|
|
217
350
|
}
|
|
218
351
|
/**
|
|
219
352
|
* Records the resolved topological-join parent IDs for a `ts` instance. Immutable
|
|
@@ -224,8 +357,10 @@ class ProcCache {
|
|
|
224
357
|
*/
|
|
225
358
|
joinParents_update(id, ids) {
|
|
226
359
|
const inst = this.instances.get(id);
|
|
227
|
-
if (inst)
|
|
360
|
+
if (inst) {
|
|
228
361
|
inst.joinParentIDs = ids;
|
|
362
|
+
this.change_emit();
|
|
363
|
+
}
|
|
229
364
|
}
|
|
230
365
|
/**
|
|
231
366
|
* Returns the resolved join parent IDs for an instance, or an empty array when the
|
|
@@ -240,6 +375,7 @@ class ProcCache {
|
|
|
240
375
|
// ── Topology loaded tracking ───────────────────────────────────────────────
|
|
241
376
|
topologyLoaded_mark(feedID) {
|
|
242
377
|
this.topologyLoaded.add(feedID);
|
|
378
|
+
this.change_emit();
|
|
243
379
|
}
|
|
244
380
|
topologyLoaded_has(feedID) {
|
|
245
381
|
return this.topologyLoaded.has(feedID);
|
|
@@ -258,6 +394,8 @@ class ProcCache {
|
|
|
258
394
|
warmup_complete() {
|
|
259
395
|
this._warmupComplete = true;
|
|
260
396
|
this._warmupProgress = { ...this._warmupProgress, active: false };
|
|
397
|
+
this.lifecycle = { ...this.lifecycle, state: 'current' };
|
|
398
|
+
this.change_emit();
|
|
261
399
|
}
|
|
262
400
|
/**
|
|
263
401
|
* Stops an unsuccessful warm-up without marking its topology complete.
|
|
@@ -267,6 +405,8 @@ class ProcCache {
|
|
|
267
405
|
warmup_abort() {
|
|
268
406
|
this._warmupComplete = false;
|
|
269
407
|
this._warmupProgress = { ...this._warmupProgress, active: false };
|
|
408
|
+
this.lifecycle = { ...this.lifecycle, state: 'failed' };
|
|
409
|
+
this.change_emit();
|
|
270
410
|
}
|
|
271
411
|
warmup_progress(loaded, total) {
|
|
272
412
|
this._warmupProgress = { loaded, total, active: true };
|
|
@@ -274,6 +414,19 @@ class ProcCache {
|
|
|
274
414
|
warmupProgress_get() {
|
|
275
415
|
return { ...this._warmupProgress };
|
|
276
416
|
}
|
|
417
|
+
/**
|
|
418
|
+
* Resets reconciliation progress while retaining restored topology.
|
|
419
|
+
*
|
|
420
|
+
* @returns Nothing.
|
|
421
|
+
*/
|
|
422
|
+
warmup_reset() {
|
|
423
|
+
this._warmupComplete = false;
|
|
424
|
+
this._warmupProgress = { loaded: this.instances.size, total: this.instances.size, active: false };
|
|
425
|
+
this.lifecycle = this.lifecycle.checkpointAt
|
|
426
|
+
? { ...this.lifecycle, state: 'restored' }
|
|
427
|
+
: { state: 'empty' };
|
|
428
|
+
this.change_emit();
|
|
429
|
+
}
|
|
277
430
|
// ── Path reconstruction ───────────────────────────────────────────────────
|
|
278
431
|
/**
|
|
279
432
|
* Reconstructs the full /proc/jobs path for a given instance ID.
|
|
@@ -327,6 +480,58 @@ class ProcCache {
|
|
|
327
480
|
built_set() {
|
|
328
481
|
this._built = true;
|
|
329
482
|
}
|
|
483
|
+
/**
|
|
484
|
+
* Creates a persistence-safe snapshot without parameters or active statuses.
|
|
485
|
+
*
|
|
486
|
+
* @returns Serializable feed and terminal-topology state.
|
|
487
|
+
*/
|
|
488
|
+
snapshot_create() {
|
|
489
|
+
const instances = Array.from(this.instances.values()).map((inst) => {
|
|
490
|
+
const { outputPath: _outputPath, ...persistent } = inst;
|
|
491
|
+
return {
|
|
492
|
+
...persistent,
|
|
493
|
+
params: null,
|
|
494
|
+
status: status_isTerminal(inst.status) ? inst.status : null,
|
|
495
|
+
joinParentIDs: inst.joinParentIDs ? [...inst.joinParentIDs] : undefined,
|
|
496
|
+
};
|
|
497
|
+
});
|
|
498
|
+
return {
|
|
499
|
+
feeds: Array.from(this.feeds.values()).map((feed) => ({ ...feed })),
|
|
500
|
+
instances,
|
|
501
|
+
topologyLoaded: Array.from(this.topologyLoaded),
|
|
502
|
+
};
|
|
503
|
+
}
|
|
504
|
+
/**
|
|
505
|
+
* Replaces in-memory topology with a validated persistent snapshot.
|
|
506
|
+
*
|
|
507
|
+
* @param snapshot - Previously validated snapshot data.
|
|
508
|
+
* @param checkpointAt - ISO timestamp when the checkpoint was written.
|
|
509
|
+
* @returns Nothing.
|
|
510
|
+
*/
|
|
511
|
+
snapshot_restore(snapshot, checkpointAt) {
|
|
512
|
+
this.cache_clear();
|
|
513
|
+
for (const feed of snapshot.feeds) {
|
|
514
|
+
this.feeds.set(feed.id, { ...feed });
|
|
515
|
+
this.feedRoots.set(feed.id, []);
|
|
516
|
+
}
|
|
517
|
+
for (const inst of snapshot.instances) {
|
|
518
|
+
const { outputPath: _outputPath, ...restored } = inst;
|
|
519
|
+
this.instance_add({ ...restored, params: null, status: status_isTerminal(inst.status) ? inst.status : null });
|
|
520
|
+
}
|
|
521
|
+
this.topologyLoaded = new Set(snapshot.topologyLoaded.filter((id) => this.feeds.has(id)));
|
|
522
|
+
this._warmupProgress = { loaded: this.instances.size, total: this.instances.size, active: false };
|
|
523
|
+
this.lifecycle = { state: 'restored', checkpointAt };
|
|
524
|
+
this.change_emit();
|
|
525
|
+
}
|
|
526
|
+
/**
|
|
527
|
+
* Records the timestamp of a successful durable save.
|
|
528
|
+
*
|
|
529
|
+
* @param checkpointAt - ISO timestamp written into the checkpoint.
|
|
530
|
+
* @returns Nothing.
|
|
531
|
+
*/
|
|
532
|
+
checkpoint_mark(checkpointAt) {
|
|
533
|
+
this.lifecycle = { ...this.lifecycle, checkpointAt };
|
|
534
|
+
}
|
|
330
535
|
/**
|
|
331
536
|
* Clears all cache data. Called before a full rebuild.
|
|
332
537
|
*/
|
|
@@ -340,6 +545,8 @@ class ProcCache {
|
|
|
340
545
|
this._warmupComplete = false;
|
|
341
546
|
this._warmupProgress = { loaded: 0, total: 0, active: false };
|
|
342
547
|
this._built = false;
|
|
548
|
+
this.lifecycle = { state: 'empty' };
|
|
549
|
+
this.change_emit();
|
|
343
550
|
}
|
|
344
551
|
}
|
|
345
552
|
exports.ProcCache = ProcCache;
|