@vincemakes/kiso-server 0.52.0 → 0.54.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/service.js +33 -10
- package/package.json +5 -5
package/dist/service.js
CHANGED
|
@@ -24,7 +24,7 @@ export class SessionService {
|
|
|
24
24
|
const opening = (async () => {
|
|
25
25
|
const agent = await this.#open(sessionId);
|
|
26
26
|
const session = await agent.session({ id: sessionId });
|
|
27
|
-
const held = { id: sessionId, agent, session, listeners: new Set(), live: null, pumping: null, executing: 0, highWater: -1, mismatch: null, unadmitted: null };
|
|
27
|
+
const held = { id: sessionId, agent, session, listeners: new Set(), live: null, pumping: null, executing: 0, highWater: -1, published: session.log.lastSeq, mismatch: null, unadmitted: null };
|
|
28
28
|
this.#held.set(sessionId, held);
|
|
29
29
|
return held;
|
|
30
30
|
})();
|
|
@@ -48,6 +48,28 @@ export class SessionService {
|
|
|
48
48
|
held.agent = agent;
|
|
49
49
|
held.session = await agent.session({ id: sessionId });
|
|
50
50
|
}
|
|
51
|
+
/** Fan out every event on the open log after `published`, in seq order.
|
|
52
|
+
* A run's events arrive through `#pump`, but a verdict given while no
|
|
53
|
+
* run is live (`resolveUncertain`, an offline `approve`) is appended
|
|
54
|
+
* straight to the log; reading the log here — not the one event in
|
|
55
|
+
* hand — is what keeps an event appended outside a run from being
|
|
56
|
+
* skipped when a run's next event reaches a subscriber first. */
|
|
57
|
+
#publish(held) {
|
|
58
|
+
const log = held.session.log.all;
|
|
59
|
+
// the log's seq is its index (EventLog refuses a discontinuity)
|
|
60
|
+
for (let i = held.published + 1; i < log.length; i++) {
|
|
61
|
+
const event = log[i];
|
|
62
|
+
held.published = event.seq;
|
|
63
|
+
for (const listener of [...held.listeners]) {
|
|
64
|
+
try {
|
|
65
|
+
listener(event);
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
held.listeners.delete(listener); // a throwing observer leaves; the run does not
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
51
73
|
// ---- runs -----------------------------------------------------------------
|
|
52
74
|
#pump(held, run) {
|
|
53
75
|
held.live = run;
|
|
@@ -60,14 +82,7 @@ export class SessionService {
|
|
|
60
82
|
held.unadmitted = { runId: run.runId, terminalSeq: event.seq, items: run.unadmitted() };
|
|
61
83
|
held.executing = Math.max(0, held.executing + executionDelta(event));
|
|
62
84
|
held.highWater = Math.max(held.highWater, event.seq);
|
|
63
|
-
|
|
64
|
-
try {
|
|
65
|
-
listener(event);
|
|
66
|
-
}
|
|
67
|
-
catch {
|
|
68
|
-
held.listeners.delete(listener); // a throwing observer leaves; the run does not
|
|
69
|
-
}
|
|
70
|
-
}
|
|
85
|
+
this.#publish(held);
|
|
71
86
|
}
|
|
72
87
|
}
|
|
73
88
|
finally {
|
|
@@ -182,6 +197,10 @@ export class SessionService {
|
|
|
182
197
|
const held = await this.#hold(sessionId);
|
|
183
198
|
const wasLive = held.live !== null;
|
|
184
199
|
await held.session.approve(decisionId, allow, reason);
|
|
200
|
+
// a live run appends the verdict itself and `#pump` fans it out once it
|
|
201
|
+
// is on disk; only a verdict appended with no run live is published here
|
|
202
|
+
if (held.live === null)
|
|
203
|
+
this.#publish(held);
|
|
185
204
|
return { needsResume: !wasLive };
|
|
186
205
|
}
|
|
187
206
|
async pendingApprovals(sessionId) {
|
|
@@ -196,6 +215,8 @@ export class SessionService {
|
|
|
196
215
|
async resolveUncertain(sessionId, executionId, resolution) {
|
|
197
216
|
const held = await this.#hold(sessionId);
|
|
198
217
|
await held.session.resolveUncertain(executionId, resolution);
|
|
218
|
+
if (held.live === null)
|
|
219
|
+
this.#publish(held);
|
|
199
220
|
return { remaining: held.session.uncertainExecutions().length };
|
|
200
221
|
}
|
|
201
222
|
// ---- observation ----------------------------------------------------------
|
|
@@ -212,7 +233,9 @@ export class SessionService {
|
|
|
212
233
|
events(sessionId, after = -1) {
|
|
213
234
|
const held = this.#held.get(sessionId);
|
|
214
235
|
const events = held !== undefined ? held.session.log.all : this.#store.load(sessionId).map((r) => r.event);
|
|
215
|
-
|
|
236
|
+
// the log's seq is its index (EventLog refuses a discontinuity): no scan, and with no `after` no copy either — a
|
|
237
|
+
// host that read every event's frames through a filtered copy spent seconds per replay on a long Work. Read-only.
|
|
238
|
+
return (after < 0 ? events : events.slice(after + 1));
|
|
216
239
|
}
|
|
217
240
|
isRunning(sessionId) {
|
|
218
241
|
return this.#held.get(sessionId)?.live !== null && this.#held.get(sessionId)?.live !== undefined;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vincemakes/kiso-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.54.0",
|
|
4
4
|
"description": "kiso server — the hosted-session service: many durable sessions in one process, observers with exact replay from a sequence number, approve / abort / resume routed to the right run, drain and close. No transport; a product supplies the agent factory.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -25,12 +25,12 @@
|
|
|
25
25
|
"test": "vitest run"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@vincemakes/kiso-core": "0.
|
|
29
|
-
"@vincemakes/kiso-protocol": "0.
|
|
30
|
-
"@vincemakes/kiso-runtime": "0.
|
|
28
|
+
"@vincemakes/kiso-core": "0.54.0",
|
|
29
|
+
"@vincemakes/kiso-protocol": "0.54.0",
|
|
30
|
+
"@vincemakes/kiso-runtime": "0.54.0"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
|
-
"@vincemakes/kiso-evals": "0.
|
|
33
|
+
"@vincemakes/kiso-evals": "0.54.0",
|
|
34
34
|
"@types/node": "^26.1.2",
|
|
35
35
|
"typescript": "^5.7.2",
|
|
36
36
|
"vitest": "^3.0.0"
|