statewire 0.9.1 → 0.9.2
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/client/connection.d.ts +4 -2
- package/dist/client/connection.d.ts.map +1 -1
- package/dist/client/connection.js +116 -23
- package/dist/client/connection.js.map +1 -1
- package/dist/client/session.d.ts.map +1 -1
- package/dist/client/session.js +3 -4
- package/dist/client/session.js.map +1 -1
- package/dist/client/timing.d.ts +2 -0
- package/dist/client/timing.d.ts.map +1 -1
- package/dist/client/timing.js +8 -2
- package/dist/client/timing.js.map +1 -1
- package/dist/host.d.ts +1 -1
- package/dist/host.d.ts.map +1 -1
- package/dist/statewire.d.ts +1 -1
- package/dist/statewire.js.map +1 -1
- package/dist/transports/sse.d.ts.map +1 -1
- package/dist/transports/sse.js +6 -4
- package/dist/transports/sse.js.map +1 -1
- package/dist/transports/ws.d.ts.map +1 -1
- package/dist/transports/ws.js +5 -9
- package/dist/transports/ws.js.map +1 -1
- package/package.json +1 -1
- package/src/client/connection.ts +200 -40
- package/src/client/session.ts +5 -9
- package/src/client/timing.ts +10 -2
- package/src/host.ts +1 -0
- package/src/statewire.ts +1 -1
- package/src/transports/sse.ts +6 -5
- package/src/transports/ws.ts +4 -9
|
@@ -42,6 +42,7 @@ type Conn = {
|
|
|
42
42
|
hasSnapshot: boolean;
|
|
43
43
|
lease: string | null;
|
|
44
44
|
attempt: number;
|
|
45
|
+
liveAt: number | null;
|
|
45
46
|
episode: Episode | null;
|
|
46
47
|
awaitingHello: boolean;
|
|
47
48
|
held: StatewireCmd[];
|
|
@@ -54,7 +55,8 @@ type Conn = {
|
|
|
54
55
|
notify: (connection: StatewireClient.Connection) => void;
|
|
55
56
|
reconnect: () => void;
|
|
56
57
|
};
|
|
57
|
-
declare const
|
|
58
|
+
declare const validateRefusalSyn: (value: unknown) => StatewireSyn;
|
|
59
|
+
declare const handleEnvelope: (c: Conn, value: unknown) => AttemptOutcome | null;
|
|
58
60
|
declare const useStatewireConn: (props: {
|
|
59
61
|
url: string;
|
|
60
62
|
onChange?: ((connection: StatewireClient.Connection) => void) | undefined;
|
|
@@ -63,5 +65,5 @@ declare const useStatewireConn: (props: {
|
|
|
63
65
|
}) => Conn;
|
|
64
66
|
declare const classify: (timeout: AbortSignal) => Error;
|
|
65
67
|
//#endregion
|
|
66
|
-
export { AttemptOutcome, Conn, Episode, Gate, StatewireCmd, StatewireEnvelope, StatewireSyn, classify, handleEnvelope, useStatewireConn };
|
|
68
|
+
export { AttemptOutcome, Conn, Episode, Gate, StatewireCmd, StatewireEnvelope, StatewireSyn, classify, handleEnvelope, useStatewireConn, validateRefusalSyn };
|
|
67
69
|
//# sourceMappingURL=connection.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection.d.ts","names":[],"sources":["../../src/client/connection.ts"],"mappings":";;;;KAQY;EACV;EACA;;KAGU;EACV;EACA;EACA;EACA;EACA;EACA;;EAEA;;KAGU;EACV;EACA;EACA;EACA;EACA;EACA;;KAGU;EACV;EACA,MAAM;EACN;EACA;EACA,MAAM;EACN,MAAM,cAAc;;KAGV;EAAS;EAAkB;;KAoC3B;KAEA;EACV,YAAY,gBAAgB;EAC5B;EACA;EACA;EACA,SAAS;EACT;EACA,MAAM;EACN,MAAM;EACN,OAAO;EACP,UAAU;EACV,KAAK;EACL,WAAW,YAAY,gBAAgB;EACvC,cAAc,OAAO,oBAAoB,QAAQ;EACjD,SAAS,YAAY,gBAAgB;EACrC;;
|
|
1
|
+
{"version":3,"file":"connection.d.ts","names":[],"sources":["../../src/client/connection.ts"],"mappings":";;;;KAQY;EACV;EACA;;KAGU;EACV;EACA;EACA;EACA;EACA;EACA;;EAEA;;KAGU;EACV;EACA;EACA;EACA;EACA;EACA;;KAGU;EACV;EACA,MAAM;EACN;EACA;EACA,MAAM;EACN,MAAM,cAAc;;KAGV;EAAS;EAAkB;;KAoC3B;KAEA;EACV,YAAY,gBAAgB;EAC5B;EACA;EACA;EACA;EACA,SAAS;EACT;EACA,MAAM;EACN,MAAM;EACN,OAAO;EACP,UAAU;EACV,KAAK;EACL,WAAW,YAAY,gBAAgB;EACvC,cAAc,OAAO,oBAAoB,QAAQ;EACjD,SAAS,YAAY,gBAAgB;EACrC;;cA8CW,qBAAsB,mBAAiB;cAyNvC,iBACX,GAAG,MACH,mBACC;cAuFU,mBAAoB;EAC/B;EACA,aAAa,YAAY,gBAAgB;EACzC,KAAK;EACL,cAAc,GAAG,MAAM,OAAO,oBAAoB,QAAQ;MACxD;cAoDS,WAAY,SAAS,gBAAW"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { reviveOps, reviveValue } from "../wire/meta.js";
|
|
2
|
-
import { backoff } from "./timing.js";
|
|
2
|
+
import { backoff, timing } from "./timing.js";
|
|
3
3
|
import { useEffect, useRef, useState } from "@assistant-ui/tap/react-shim";
|
|
4
4
|
import { flushTapSync } from "@assistant-ui/tap";
|
|
5
5
|
//#region src/client/connection.ts
|
|
@@ -45,6 +45,58 @@ const setStatus = (c, next) => {
|
|
|
45
45
|
const protocolError = (message) => {
|
|
46
46
|
throw new Error(`statewire: protocol error: ${message}`);
|
|
47
47
|
};
|
|
48
|
+
const isObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
49
|
+
const isNonnegativeSafeInteger = (value) => Number.isSafeInteger(value) && value >= 0;
|
|
50
|
+
const isPositiveSafeInteger = (value) => Number.isSafeInteger(value) && value > 0;
|
|
51
|
+
const validateOptionalString = (value, field) => {
|
|
52
|
+
if (value !== void 0 && typeof value !== "string") protocolError(`${field} must be a string`);
|
|
53
|
+
};
|
|
54
|
+
const validateSynScalars = (syn) => {
|
|
55
|
+
if (syn["seq"] !== void 0 && !isNonnegativeSafeInteger(syn["seq"])) protocolError("syn.seq must be a nonnegative safe integer");
|
|
56
|
+
if (syn["ctxSeq"] !== void 0 && !isNonnegativeSafeInteger(syn["ctxSeq"])) protocolError("syn.ctxSeq must be a nonnegative safe integer");
|
|
57
|
+
if (syn["retry"] !== void 0 && !isNonnegativeSafeInteger(syn["retry"])) protocolError("syn.retry must be a nonnegative safe integer");
|
|
58
|
+
validateOptionalString(syn["id"], "syn.id");
|
|
59
|
+
if (syn["idle"] !== void 0 && typeof syn["idle"] !== "boolean") protocolError("syn.idle must be a boolean");
|
|
60
|
+
validateOptionalString(syn["record"], "syn.record");
|
|
61
|
+
};
|
|
62
|
+
const validateRefusalSyn = (value) => {
|
|
63
|
+
if (!isObject(value)) return protocolError("syn must be an object");
|
|
64
|
+
validateSynScalars(value);
|
|
65
|
+
if (value["id"] !== void 0 || value["idle"] !== void 0 || value["record"] !== void 0) protocolError("invalid refusal syn");
|
|
66
|
+
if (value["seq"] === void 0 && value["ctxSeq"] === void 0 && value["retry"] === void 0) protocolError("refusal syn has no watermarks or retry");
|
|
67
|
+
return value;
|
|
68
|
+
};
|
|
69
|
+
const validateCmd = (value) => {
|
|
70
|
+
if (!isObject(value)) return protocolError("cmd entry must be an object");
|
|
71
|
+
if (!isPositiveSafeInteger(value["seq"])) protocolError("cmd.seq must be a positive safe integer");
|
|
72
|
+
validateOptionalString(value["type"], "cmd.type");
|
|
73
|
+
validateOptionalString(value["code"], "cmd.code");
|
|
74
|
+
validateOptionalString(value["message"], "cmd.message");
|
|
75
|
+
if (value["dur"] !== void 0 && value["dur"] !== true) protocolError("cmd.dur must be true");
|
|
76
|
+
return true;
|
|
77
|
+
};
|
|
78
|
+
const validateFin = (value) => {
|
|
79
|
+
if (!isObject(value)) return protocolError("fin must be an object");
|
|
80
|
+
if (typeof value["reason"] !== "string") protocolError("fin.reason must be a string");
|
|
81
|
+
validateOptionalString(value["message"], "fin.message");
|
|
82
|
+
return true;
|
|
83
|
+
};
|
|
84
|
+
const validateEnvelope = (value) => {
|
|
85
|
+
if (!isObject(value)) return protocolError("packet must be an object");
|
|
86
|
+
if (value["ops"] !== void 0 && !Array.isArray(value["ops"])) protocolError("ops must be an array");
|
|
87
|
+
if (value["cmd"] !== void 0) {
|
|
88
|
+
const cmd = value["cmd"];
|
|
89
|
+
if (!Array.isArray(cmd)) return protocolError("cmd must be an array");
|
|
90
|
+
for (const entry of cmd) validateCmd(entry);
|
|
91
|
+
}
|
|
92
|
+
if (value["idle"] !== void 0 && typeof value["idle"] !== "boolean") protocolError("idle must be a boolean");
|
|
93
|
+
if (value["next"] !== void 0) {
|
|
94
|
+
if (value["next"] !== true) protocolError("next must be true");
|
|
95
|
+
if (value["cmd"] === void 0 || value["ops"] !== void 0 || value["fin"] !== void 0) protocolError("next must ride a cmd-only packet");
|
|
96
|
+
}
|
|
97
|
+
if (value["fin"] !== void 0) validateFin(value["fin"]);
|
|
98
|
+
return value;
|
|
99
|
+
};
|
|
48
100
|
const releaseHeld = (c) => {
|
|
49
101
|
if (c.held.length === 0) return;
|
|
50
102
|
const held = c.held;
|
|
@@ -53,29 +105,56 @@ const releaseHeld = (c) => {
|
|
|
53
105
|
};
|
|
54
106
|
const cmdsOf = (env) => {
|
|
55
107
|
if (env.cmd === void 0) return [];
|
|
56
|
-
if (!Array.isArray(env.cmd)) return protocolError("cmd must be an array");
|
|
57
108
|
return env.cmd;
|
|
58
109
|
};
|
|
110
|
+
const snapshotOf = (env) => {
|
|
111
|
+
const ops = env.ops;
|
|
112
|
+
if (ops === void 0) return protocolError("hello missing snapshot");
|
|
113
|
+
if (ops.length !== 1 || !isObject(ops[0])) return protocolError("hello snapshot must be one root replace op");
|
|
114
|
+
const op = ops[0];
|
|
115
|
+
if (op["op"] !== "replace" || !Array.isArray(op["path"]) || op["path"].length !== 0 || !Object.hasOwn(op, "value")) return protocolError("hello snapshot must be one root replace op");
|
|
116
|
+
return reviveOps(ops);
|
|
117
|
+
};
|
|
118
|
+
const helloSynOf = (env) => {
|
|
119
|
+
if (!isObject(env.syn)) return protocolError("expected hello");
|
|
120
|
+
validateSynScalars(env.syn);
|
|
121
|
+
if (env.syn["retry"] !== void 0) protocolError("hello syn cannot carry retry");
|
|
122
|
+
return env.syn;
|
|
123
|
+
};
|
|
59
124
|
const handleHello = (c, env) => {
|
|
60
|
-
const syn = env
|
|
61
|
-
|
|
62
|
-
c.awaitingHello = false;
|
|
63
|
-
c.hasSnapshot = true;
|
|
125
|
+
const syn = helloSynOf(env);
|
|
126
|
+
const ops = snapshotOf(env);
|
|
64
127
|
c.ctx.onHello({
|
|
65
|
-
ops
|
|
128
|
+
ops,
|
|
66
129
|
syn
|
|
67
130
|
});
|
|
68
131
|
c.ctx.onIdle(syn.idle ?? false);
|
|
69
|
-
c.
|
|
132
|
+
c.awaitingHello = false;
|
|
133
|
+
c.hasSnapshot = true;
|
|
134
|
+
c.liveAt = Date.now();
|
|
70
135
|
c.episode = null;
|
|
71
136
|
setStatus(c, { status: "live" });
|
|
72
137
|
};
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
138
|
+
let warnedUnknownSynFact = false;
|
|
139
|
+
const warnUnknownSynFact = () => {
|
|
140
|
+
if (warnedUnknownSynFact) return;
|
|
141
|
+
warnedUnknownSynFact = true;
|
|
142
|
+
console.warn("statewire: ignoring unknown syn fact");
|
|
143
|
+
};
|
|
144
|
+
const deliverSyn = (c, value) => {
|
|
145
|
+
if (!isObject(value)) return protocolError("syn must be an object");
|
|
146
|
+
validateSynScalars(value);
|
|
147
|
+
if (value["record"] !== void 0 || value["idle"] !== void 0) protocolError("invalid mid-stream syn");
|
|
148
|
+
if (value["seq"] !== void 0 || value["ctxSeq"] !== void 0 || value["retry"] !== void 0) {
|
|
149
|
+
c.ctx.onRefusal(validateRefusalSyn(value));
|
|
150
|
+
return;
|
|
78
151
|
}
|
|
152
|
+
if (value["id"] !== void 0) return;
|
|
153
|
+
if (Object.keys(value).length === 0) protocolError("invalid mid-stream syn");
|
|
154
|
+
warnUnknownSynFact();
|
|
155
|
+
};
|
|
156
|
+
const deliverEnvelope = (c, env) => {
|
|
157
|
+
if (env.syn !== void 0) deliverSyn(c, env.syn);
|
|
79
158
|
if (env.ops !== void 0) {
|
|
80
159
|
const held = c.held;
|
|
81
160
|
c.held = [];
|
|
@@ -90,7 +169,14 @@ const deliverEnvelope = (c, env) => {
|
|
|
90
169
|
}
|
|
91
170
|
if (typeof env.idle === "boolean") c.ctx.onIdle(env.idle);
|
|
92
171
|
};
|
|
93
|
-
const
|
|
172
|
+
const transientCauseOf = (reason) => {
|
|
173
|
+
switch (reason) {
|
|
174
|
+
case "evicted": return "evicted";
|
|
175
|
+
case "error": return "error";
|
|
176
|
+
case "unauthorized": return "unauthorized";
|
|
177
|
+
default: return "error";
|
|
178
|
+
}
|
|
179
|
+
};
|
|
94
180
|
const settleFin = (c, fin) => {
|
|
95
181
|
let finish = fin;
|
|
96
182
|
if (finish.meta !== void 0) {
|
|
@@ -108,10 +194,14 @@ const settleFin = (c, fin) => {
|
|
|
108
194
|
setStatus(c, { status: "idle" });
|
|
109
195
|
return "idle";
|
|
110
196
|
}
|
|
111
|
-
|
|
112
|
-
|
|
197
|
+
const terminal = finish.reason === "gone" || finish.reason === "superseded";
|
|
198
|
+
c.ctx.onFinish(terminal ? finish : {
|
|
199
|
+
...finish,
|
|
200
|
+
reason: "error"
|
|
201
|
+
});
|
|
202
|
+
if (!terminal) {
|
|
113
203
|
c.episode = {
|
|
114
|
-
cause: finish.reason,
|
|
204
|
+
cause: transientCauseOf(finish.reason),
|
|
115
205
|
...finish.message !== void 0 && { message: finish.message }
|
|
116
206
|
};
|
|
117
207
|
return "reattach";
|
|
@@ -123,8 +213,8 @@ const settleFin = (c, fin) => {
|
|
|
123
213
|
});
|
|
124
214
|
return "stop";
|
|
125
215
|
};
|
|
126
|
-
const handleEnvelope = (c,
|
|
127
|
-
|
|
216
|
+
const handleEnvelope = (c, value) => {
|
|
217
|
+
const env = validateEnvelope(value);
|
|
128
218
|
if (c.awaitingHello) {
|
|
129
219
|
if (env.fin !== void 0) return settleFin(c, env.fin);
|
|
130
220
|
handleHello(c, env);
|
|
@@ -140,10 +230,12 @@ const handleEnvelope = (c, env) => {
|
|
|
140
230
|
return null;
|
|
141
231
|
};
|
|
142
232
|
const scheduleRetry = (c, failure, immediate) => {
|
|
233
|
+
if (c.liveAt !== null && Date.now() - c.liveAt >= timing.backoffResetMs) c.attempt = 0;
|
|
234
|
+
c.liveAt = null;
|
|
143
235
|
c.attempt += 1;
|
|
144
236
|
c.episode ??= { cause: "dropped" };
|
|
145
237
|
const delay = immediate ? 0 : backoff(c.attempt);
|
|
146
|
-
|
|
238
|
+
setStatus(c, {
|
|
147
239
|
status: "reconnecting",
|
|
148
240
|
...c.episode,
|
|
149
241
|
attempt: c.attempt,
|
|
@@ -158,8 +250,7 @@ const reconnectConn = (c) => {
|
|
|
158
250
|
c.attempt = 0;
|
|
159
251
|
c.episode = { cause: "dropped" };
|
|
160
252
|
flushTapSync(() => {
|
|
161
|
-
|
|
162
|
-
else setStatus(c, { status: "connecting" });
|
|
253
|
+
scheduleRetry(c, void 0, true);
|
|
163
254
|
});
|
|
164
255
|
}
|
|
165
256
|
openGate(c.gate);
|
|
@@ -205,6 +296,7 @@ const useStatewireConn = (props) => {
|
|
|
205
296
|
hasSnapshot: false,
|
|
206
297
|
lease: null,
|
|
207
298
|
attempt: 0,
|
|
299
|
+
liveAt: null,
|
|
208
300
|
episode: null,
|
|
209
301
|
awaitingHello: true,
|
|
210
302
|
held: [],
|
|
@@ -229,6 +321,7 @@ const useStatewireConn = (props) => {
|
|
|
229
321
|
c.hasSnapshot = false;
|
|
230
322
|
c.lease = null;
|
|
231
323
|
c.attempt = 0;
|
|
324
|
+
c.liveAt = null;
|
|
232
325
|
c.episode = null;
|
|
233
326
|
if (c.connection.status !== "connecting") setStatus(c, { status: "connecting" });
|
|
234
327
|
const lifetime = new AbortController();
|
|
@@ -246,6 +339,6 @@ const useStatewireConn = (props) => {
|
|
|
246
339
|
};
|
|
247
340
|
const classify = (timeout) => /* @__PURE__ */ new Error(timeout.aborted ? "timeout" : "network");
|
|
248
341
|
//#endregion
|
|
249
|
-
export { classify, handleEnvelope, useStatewireConn };
|
|
342
|
+
export { classify, handleEnvelope, useStatewireConn, validateRefusalSyn };
|
|
250
343
|
|
|
251
344
|
//# sourceMappingURL=connection.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection.js","names":["useEffect","useRef","useState","flushTapSync","reviveOps","reviveValue","backoff","ConnectionState","StatewireRemoteProps","StatewireClient","StatewireHost","Episode","cause","message","StatewireCmd","seq","type","code","payload","meta","dur","StatewireSyn","ctxSeq","record","id","idle","retry","StatewireEnvelope","ops","cmd","next","syn","fin","Fin","Gate","latched","wake","newGate","undefined","takeGate","g","was","waitGate","timeoutMs","Promise","resolve","timer","setTimeout","clearTimeout","openGate","AttemptOutcome","Conn","connection","Connection","hasSnapshot","lease","attempt","episode","awaitingHello","held","gate","abort","AbortController","lifetime","ctx","onChange","attemptOnce","notify","reconnect","setStatus","c","changed","status","protocolError","Error","releaseHeld","length","onCmds","cmdsOf","env","Array","isArray","handleHello","onHello","onIdle","deliverEnvelope","onRefusal","onOps","cmds","push","isTransientFinish","reason","settleFin","finish","rest","onFinish","handleEnvelope","scheduleRetry","failure","immediate","delay","nextRetryAt","Date","now","lastError","reconnectConn","run","alive","outcome","error","signal","aborted","onDetach","useStatewireConn","props","url","latest","current","setConnection","conn","classify","timeout","AbortSignal"],"sources":["../../src/client/connection.ts"],"sourcesContent":["import { useEffect, useRef, useState } from \"react\";\nimport { flushTapSync } from \"@assistant-ui/tap\";\nimport { reviveOps, reviveValue } from \"../wire/meta\";\nimport { backoff } from \"./timing\";\nimport type { ConnectionState, StatewireRemoteProps } from \"../transports/sse\";\nimport type { StatewireClient } from \"../statewire\";\nimport type { StatewireHost } from \"../host\";\n\nexport type Episode = {\n cause: \"dropped\" | \"evicted\" | \"error\" | \"unauthorized\";\n message?: string;\n};\n\nexport type StatewireCmd = {\n seq: number;\n type?: \"applied\" | \"result\" | \"rejected\" | \"failed\" | \"crashed\" | \"expired\";\n code?: string;\n message?: string;\n payload?: unknown;\n meta?: unknown;\n /** Cumulative: resending through this seq will never be needed. */\n dur?: boolean;\n};\n\nexport type StatewireSyn = {\n seq?: number;\n ctxSeq?: number;\n record?: \"fresh\" | \"resumed\" | \"ephemeral\";\n id?: string;\n idle?: boolean;\n retry?: number;\n};\n\nexport type StatewireEnvelope = {\n ops?: unknown[];\n cmd?: StatewireCmd[];\n next?: true;\n idle?: boolean;\n syn?: StatewireSyn;\n fin?: StatewireHost.Fin;\n};\n\nexport type Gate = { latched: boolean; wake: (() => void) | undefined };\n\nconst newGate = (): Gate => ({ latched: false, wake: undefined });\n\nconst takeGate = (g: Gate) => {\n const was = g.latched;\n g.latched = false;\n return was;\n};\n\nconst waitGate = (g: Gate, timeoutMs?: number) => {\n if (g.latched) {\n g.latched = false;\n return Promise.resolve();\n }\n return new Promise<void>((resolve) => {\n const timer =\n timeoutMs === undefined\n ? undefined\n : setTimeout(() => {\n g.wake = undefined;\n resolve();\n }, timeoutMs);\n g.wake = () => {\n clearTimeout(timer);\n g.wake = undefined;\n resolve();\n };\n });\n};\n\nconst openGate = (g: Gate) => {\n if (g.wake) g.wake();\n else g.latched = true;\n};\n\nexport type AttemptOutcome = \"stop\" | \"reattach\" | \"ended\" | \"idle\";\n\nexport type Conn = {\n connection: StatewireClient.Connection;\n hasSnapshot: boolean;\n lease: string | null;\n attempt: number;\n episode: Episode | null;\n awaitingHello: boolean;\n held: StatewireCmd[];\n gate: Gate;\n abort: AbortController | null;\n lifetime: AbortController | null;\n ctx: StatewireRemoteProps;\n onChange: (connection: StatewireClient.Connection) => void;\n attemptOnce: (abort: AbortController) => Promise<AttemptOutcome>;\n notify: (connection: StatewireClient.Connection) => void;\n reconnect: () => void;\n};\n\nconst setStatus = (c: Conn, next: ConnectionState) => {\n const changed = next.status !== c.connection.status;\n c.connection = { ...next, reconnect: c.reconnect };\n c.notify(c.connection);\n if (changed) c.onChange(c.connection);\n};\n\nconst protocolError = (message: string): never => {\n throw new Error(`statewire: protocol error: ${message}`);\n};\n\n// A hold's release delivers, never settles: fin and bare close both drain it.\nconst releaseHeld = (c: Conn) => {\n if (c.held.length === 0) return;\n const held = c.held;\n c.held = [];\n c.ctx.onCmds(held);\n};\n\nconst cmdsOf = (env: StatewireEnvelope): StatewireCmd[] => {\n if (env.cmd === undefined) return [];\n if (!Array.isArray(env.cmd)) return protocolError(\"cmd must be an array\");\n return env.cmd;\n};\n\nconst handleHello = (c: Conn, env: StatewireEnvelope) => {\n const syn = env.syn;\n if (syn === undefined) return protocolError(\"expected hello\");\n c.awaitingHello = false;\n c.hasSnapshot = true;\n c.ctx.onHello({\n ops: env.ops === undefined ? [] : reviveOps(env.ops),\n syn,\n });\n c.ctx.onIdle(syn.idle ?? false);\n c.attempt = 0;\n c.episode = null;\n setStatus(c, { status: \"live\" });\n};\n\nconst deliverEnvelope = (c: Conn, env: StatewireEnvelope) => {\n if (env.syn !== undefined) {\n const syn = env.syn;\n if (\n syn.seq !== undefined ||\n syn.ctxSeq !== undefined ||\n syn.retry !== undefined\n ) {\n c.ctx.onRefusal(syn);\n } else if (syn.id === undefined) {\n protocolError(\"invalid mid-stream syn\");\n }\n }\n if (env.ops !== undefined) {\n const held = c.held;\n c.held = [];\n c.ctx.onOps({\n ops: reviveOps(env.ops),\n cmds: [...held, ...cmdsOf(env)],\n });\n } else if (env.cmd !== undefined) {\n const cmds = cmdsOf(env);\n if (env.next === true) c.held.push(...cmds);\n else c.ctx.onCmds(cmds);\n }\n if (typeof env.idle === \"boolean\") c.ctx.onIdle(env.idle);\n};\n\nconst isTransientFinish = (\n reason: StatewireHost.Fin[\"reason\"],\n): reason is \"evicted\" | \"error\" => reason === \"evicted\" || reason === \"error\";\n\nconst settleFin = (c: Conn, fin: StatewireHost.Fin): AttemptOutcome => {\n let finish = fin;\n if (finish.meta !== undefined) {\n const { meta, ...rest } = finish;\n finish = { ...rest, payload: reviveValue(rest.payload, meta) };\n }\n releaseHeld(c);\n if (finish.reason === \"idle\") {\n c.ctx.onIdle(true);\n c.attempt = 0;\n c.episode = null;\n setStatus(c, { status: \"idle\" });\n return \"idle\";\n }\n c.ctx.onFinish(finish);\n if (isTransientFinish(finish.reason)) {\n c.episode = {\n cause: finish.reason,\n ...(finish.message !== undefined && { message: finish.message }),\n };\n return \"reattach\";\n }\n setStatus(c, {\n status: \"gone\",\n ...(finish.message !== undefined && { message: finish.message }),\n ...(finish.payload !== undefined && { payload: finish.payload }),\n });\n return \"stop\";\n};\n\nexport const handleEnvelope = (\n c: Conn,\n env: StatewireEnvelope,\n): AttemptOutcome | null => {\n if (typeof env !== \"object\" || env === null) {\n return protocolError(\"packet must be an object\");\n }\n if (c.awaitingHello) {\n if (env.fin !== undefined) return settleFin(c, env.fin);\n handleHello(c, env);\n return null;\n }\n deliverEnvelope(c, env);\n if (env.fin !== undefined) return settleFin(c, env.fin);\n if (c.connection.status !== \"live\") {\n c.attempt = 0;\n c.episode = null;\n setStatus(c, { status: \"live\" });\n }\n return null;\n};\n\nconst scheduleRetry = (\n c: Conn,\n failure: string | undefined,\n immediate: boolean,\n) => {\n c.attempt += 1;\n c.episode ??= { cause: \"dropped\" };\n const delay = immediate ? 0 : backoff(c.attempt);\n if (c.hasSnapshot) {\n setStatus(c, {\n status: \"reconnecting\",\n ...c.episode,\n attempt: c.attempt,\n nextRetryAt: Date.now() + delay,\n ...(failure !== undefined && { lastError: failure }),\n });\n }\n return delay;\n};\n\nconst reconnectConn = (c: Conn) => {\n if (!c.lifetime) return;\n if (c.connection.status === \"gone\" || c.connection.status === \"idle\") {\n c.attempt = 0;\n c.episode = { cause: \"dropped\" };\n flushTapSync(() => {\n if (c.hasSnapshot) scheduleRetry(c, undefined, true);\n else setStatus(c, { status: \"connecting\" });\n });\n }\n openGate(c.gate);\n c.abort?.abort();\n};\n\nconst run = async (c: Conn, lifetime: AbortController, gate: Gate) => {\n const alive = () => c.lifetime === lifetime;\n while (alive()) {\n const abort = new AbortController();\n c.abort = abort;\n c.awaitingHello = true;\n c.held = [];\n let outcome: AttemptOutcome | undefined;\n let failure: string | undefined;\n try {\n outcome = await c.attemptOnce(abort);\n } catch (error) {\n if (!abort.signal.aborted) {\n failure =\n error instanceof Error && error.message ? error.message : \"network\";\n }\n }\n abort.abort();\n if (!alive()) return;\n flushTapSync(() => {\n releaseHeld(c);\n c.ctx.onDetach();\n });\n if (!alive()) return;\n if (outcome === \"stop\" || outcome === \"idle\") {\n await waitGate(gate);\n continue;\n }\n const immediate = takeGate(gate);\n const delay = flushTapSync(() => scheduleRetry(c, failure, immediate));\n if (delay === 0) continue;\n await waitGate(gate, delay);\n }\n};\n\nexport const useStatewireConn = (props: {\n url: string;\n onChange?: ((connection: StatewireClient.Connection) => void) | undefined;\n ctx: StatewireRemoteProps;\n attemptOnce: (c: Conn, abort: AbortController) => Promise<AttemptOutcome>;\n}): Conn => {\n const latest = useRef(props);\n latest.current = props;\n const [, setConnection] = useState<StatewireClient.Connection | null>(null);\n const [c] = useState((): Conn => {\n const conn: Conn = {\n hasSnapshot: false,\n lease: null,\n attempt: 0,\n episode: null,\n awaitingHello: true,\n held: [],\n abort: null,\n gate: newGate(),\n lifetime: null,\n get ctx() {\n return latest.current.ctx;\n },\n onChange: (connection) => latest.current.onChange?.(connection),\n attemptOnce: (abort) => latest.current.attemptOnce(conn, abort),\n notify: setConnection,\n reconnect: () => reconnectConn(conn),\n connection: { status: \"connecting\", reconnect: () => conn.reconnect() },\n };\n return conn;\n });\n\n useEffect(() => {\n c.hasSnapshot = false;\n c.lease = null;\n c.attempt = 0;\n c.episode = null;\n if (c.connection.status !== \"connecting\") {\n setStatus(c, { status: \"connecting\" });\n }\n const lifetime = new AbortController();\n c.lifetime = lifetime;\n c.gate = newGate();\n void run(c, lifetime, c.gate);\n return () => {\n c.abort?.abort();\n lifetime.abort();\n if (c.lifetime === lifetime) c.lifetime = null;\n openGate(c.gate);\n };\n }, [c, props.url]);\n\n return c;\n};\n\nexport const classify = (timeout: AbortSignal) =>\n new Error(timeout.aborted ? \"timeout\" : \"network\");\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"connection.js","names":["useEffect","useRef","useState","flushTapSync","reviveOps","reviveValue","backoff","timing","ConnectionState","StatewireRemoteProps","StatewireClient","StatewireHost","Episode","cause","message","StatewireCmd","seq","type","code","payload","meta","dur","StatewireSyn","ctxSeq","record","id","idle","retry","StatewireEnvelope","ops","cmd","next","syn","fin","Fin","Gate","latched","wake","newGate","undefined","takeGate","g","was","waitGate","timeoutMs","Promise","resolve","timer","setTimeout","clearTimeout","openGate","AttemptOutcome","Conn","connection","Connection","hasSnapshot","lease","attempt","liveAt","episode","awaitingHello","held","gate","abort","AbortController","lifetime","ctx","onChange","attemptOnce","notify","reconnect","setStatus","c","changed","status","protocolError","Error","isObject","value","Record","Array","isArray","isNonnegativeSafeInteger","Number","isSafeInteger","isPositiveSafeInteger","validateOptionalString","field","validateSynScalars","validateRefusalSyn","validateCmd","validateFin","validateEnvelope","entry","releaseHeld","length","onCmds","cmdsOf","env","snapshotOf","op","Object","hasOwn","helloSynOf","handleHello","onHello","onIdle","Date","now","warnedUnknownSynFact","warnUnknownSynFact","console","warn","deliverSyn","onRefusal","keys","deliverEnvelope","onOps","cmds","push","transientCauseOf","reason","settleFin","finish","rest","terminal","onFinish","handleEnvelope","scheduleRetry","failure","immediate","backoffResetMs","delay","nextRetryAt","lastError","reconnectConn","run","alive","outcome","error","signal","aborted","onDetach","useStatewireConn","props","url","latest","current","setConnection","conn","classify","timeout","AbortSignal"],"sources":["../../src/client/connection.ts"],"sourcesContent":["import { useEffect, useRef, useState } from \"react\";\nimport { flushTapSync } from \"@assistant-ui/tap\";\nimport { reviveOps, reviveValue } from \"../wire/meta\";\nimport { backoff, timing } from \"./timing\";\nimport type { ConnectionState, StatewireRemoteProps } from \"../transports/sse\";\nimport type { StatewireClient } from \"../statewire\";\nimport type { StatewireHost } from \"../host\";\n\nexport type Episode = {\n cause: \"dropped\" | \"evicted\" | \"error\" | \"unauthorized\";\n message?: string;\n};\n\nexport type StatewireCmd = {\n seq: number;\n type?: \"applied\" | \"result\" | \"rejected\" | \"failed\" | \"crashed\" | \"expired\";\n code?: string;\n message?: string;\n payload?: unknown;\n meta?: unknown;\n /** Cumulative: resending through this seq will never be needed. */\n dur?: boolean;\n};\n\nexport type StatewireSyn = {\n seq?: number;\n ctxSeq?: number;\n record?: \"fresh\" | \"resumed\" | \"ephemeral\";\n id?: string;\n idle?: boolean;\n retry?: number;\n};\n\nexport type StatewireEnvelope = {\n ops?: unknown[];\n cmd?: StatewireCmd[];\n next?: true;\n idle?: boolean;\n syn?: StatewireSyn;\n fin?: StatewireHost.Fin;\n};\n\nexport type Gate = { latched: boolean; wake: (() => void) | undefined };\n\nconst newGate = (): Gate => ({ latched: false, wake: undefined });\n\nconst takeGate = (g: Gate) => {\n const was = g.latched;\n g.latched = false;\n return was;\n};\n\nconst waitGate = (g: Gate, timeoutMs?: number) => {\n if (g.latched) {\n g.latched = false;\n return Promise.resolve();\n }\n return new Promise<void>((resolve) => {\n const timer =\n timeoutMs === undefined\n ? undefined\n : setTimeout(() => {\n g.wake = undefined;\n resolve();\n }, timeoutMs);\n g.wake = () => {\n clearTimeout(timer);\n g.wake = undefined;\n resolve();\n };\n });\n};\n\nconst openGate = (g: Gate) => {\n if (g.wake) g.wake();\n else g.latched = true;\n};\n\nexport type AttemptOutcome = \"stop\" | \"reattach\" | \"ended\" | \"idle\";\n\nexport type Conn = {\n connection: StatewireClient.Connection;\n hasSnapshot: boolean;\n lease: string | null;\n attempt: number;\n liveAt: number | null;\n episode: Episode | null;\n awaitingHello: boolean;\n held: StatewireCmd[];\n gate: Gate;\n abort: AbortController | null;\n lifetime: AbortController | null;\n ctx: StatewireRemoteProps;\n onChange: (connection: StatewireClient.Connection) => void;\n attemptOnce: (abort: AbortController) => Promise<AttemptOutcome>;\n notify: (connection: StatewireClient.Connection) => void;\n reconnect: () => void;\n};\n\nconst setStatus = (c: Conn, next: ConnectionState) => {\n const changed = next.status !== c.connection.status;\n c.connection = { ...next, reconnect: c.reconnect };\n c.notify(c.connection);\n if (changed) c.onChange(c.connection);\n};\n\nconst protocolError = (message: string): never => {\n throw new Error(`statewire: protocol error: ${message}`);\n};\n\nconst isObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nconst isNonnegativeSafeInteger = (value: unknown): value is number =>\n Number.isSafeInteger(value) && (value as number) >= 0;\n\nconst isPositiveSafeInteger = (value: unknown): value is number =>\n Number.isSafeInteger(value) && (value as number) > 0;\n\nconst validateOptionalString = (value: unknown, field: string): void => {\n if (value !== undefined && typeof value !== \"string\") {\n protocolError(`${field} must be a string`);\n }\n};\n\nconst validateSynScalars = (syn: Record<string, unknown>) => {\n if (syn[\"seq\"] !== undefined && !isNonnegativeSafeInteger(syn[\"seq\"])) {\n protocolError(\"syn.seq must be a nonnegative safe integer\");\n }\n if (syn[\"ctxSeq\"] !== undefined && !isNonnegativeSafeInteger(syn[\"ctxSeq\"])) {\n protocolError(\"syn.ctxSeq must be a nonnegative safe integer\");\n }\n if (syn[\"retry\"] !== undefined && !isNonnegativeSafeInteger(syn[\"retry\"])) {\n protocolError(\"syn.retry must be a nonnegative safe integer\");\n }\n validateOptionalString(syn[\"id\"], \"syn.id\");\n if (syn[\"idle\"] !== undefined && typeof syn[\"idle\"] !== \"boolean\") {\n protocolError(\"syn.idle must be a boolean\");\n }\n validateOptionalString(syn[\"record\"], \"syn.record\");\n};\n\nexport const validateRefusalSyn = (value: unknown): StatewireSyn => {\n if (!isObject(value)) return protocolError(\"syn must be an object\");\n validateSynScalars(value);\n if (\n value[\"id\"] !== undefined ||\n value[\"idle\"] !== undefined ||\n value[\"record\"] !== undefined\n ) {\n protocolError(\"invalid refusal syn\");\n }\n if (\n value[\"seq\"] === undefined &&\n value[\"ctxSeq\"] === undefined &&\n value[\"retry\"] === undefined\n ) {\n protocolError(\"refusal syn has no watermarks or retry\");\n }\n return value as StatewireSyn;\n};\n\nconst validateCmd = (value: unknown): value is StatewireCmd => {\n if (!isObject(value)) return protocolError(\"cmd entry must be an object\");\n if (!isPositiveSafeInteger(value[\"seq\"])) {\n protocolError(\"cmd.seq must be a positive safe integer\");\n }\n validateOptionalString(value[\"type\"], \"cmd.type\");\n validateOptionalString(value[\"code\"], \"cmd.code\");\n validateOptionalString(value[\"message\"], \"cmd.message\");\n if (value[\"dur\"] !== undefined && value[\"dur\"] !== true) {\n protocolError(\"cmd.dur must be true\");\n }\n return true;\n};\n\nconst validateFin = (value: unknown): value is StatewireHost.Fin => {\n if (!isObject(value)) return protocolError(\"fin must be an object\");\n if (typeof value[\"reason\"] !== \"string\") {\n protocolError(\"fin.reason must be a string\");\n }\n validateOptionalString(value[\"message\"], \"fin.message\");\n return true;\n};\n\nconst validateEnvelope = (value: unknown): StatewireEnvelope => {\n if (!isObject(value)) return protocolError(\"packet must be an object\");\n if (value[\"ops\"] !== undefined && !Array.isArray(value[\"ops\"])) {\n protocolError(\"ops must be an array\");\n }\n if (value[\"cmd\"] !== undefined) {\n const cmd = value[\"cmd\"];\n if (!Array.isArray(cmd)) return protocolError(\"cmd must be an array\");\n for (const entry of cmd) validateCmd(entry);\n }\n if (value[\"idle\"] !== undefined && typeof value[\"idle\"] !== \"boolean\") {\n protocolError(\"idle must be a boolean\");\n }\n if (value[\"next\"] !== undefined) {\n if (value[\"next\"] !== true) protocolError(\"next must be true\");\n if (\n value[\"cmd\"] === undefined ||\n value[\"ops\"] !== undefined ||\n value[\"fin\"] !== undefined\n ) {\n protocolError(\"next must ride a cmd-only packet\");\n }\n }\n if (value[\"fin\"] !== undefined) validateFin(value[\"fin\"]);\n return value as StatewireEnvelope;\n};\n\n// A hold's release delivers, never settles: fin and bare close both drain it.\nconst releaseHeld = (c: Conn) => {\n if (c.held.length === 0) return;\n const held = c.held;\n c.held = [];\n c.ctx.onCmds(held);\n};\n\nconst cmdsOf = (env: StatewireEnvelope): StatewireCmd[] => {\n if (env.cmd === undefined) return [];\n return env.cmd;\n};\n\nconst snapshotOf = (env: StatewireEnvelope): unknown[] => {\n const ops = env.ops;\n if (ops === undefined) return protocolError(\"hello missing snapshot\");\n if (ops.length !== 1 || !isObject(ops[0])) {\n return protocolError(\"hello snapshot must be one root replace op\");\n }\n const op = ops[0];\n if (\n op[\"op\"] !== \"replace\" ||\n !Array.isArray(op[\"path\"]) ||\n op[\"path\"].length !== 0 ||\n !Object.hasOwn(op, \"value\")\n ) {\n return protocolError(\"hello snapshot must be one root replace op\");\n }\n return reviveOps(ops);\n};\n\nconst helloSynOf = (env: StatewireEnvelope): StatewireSyn => {\n if (!isObject(env.syn)) return protocolError(\"expected hello\");\n validateSynScalars(env.syn);\n if (env.syn[\"retry\"] !== undefined) {\n protocolError(\"hello syn cannot carry retry\");\n }\n return env.syn as StatewireSyn;\n};\n\nconst handleHello = (c: Conn, env: StatewireEnvelope) => {\n const syn = helloSynOf(env);\n const ops = snapshotOf(env);\n c.ctx.onHello({\n ops,\n syn,\n });\n c.ctx.onIdle(syn.idle ?? false);\n c.awaitingHello = false;\n c.hasSnapshot = true;\n c.liveAt = Date.now();\n c.episode = null;\n setStatus(c, { status: \"live\" });\n};\n\nlet warnedUnknownSynFact = false;\n\nconst warnUnknownSynFact = () => {\n if (warnedUnknownSynFact) return;\n warnedUnknownSynFact = true;\n console.warn(\"statewire: ignoring unknown syn fact\");\n};\n\nconst deliverSyn = (c: Conn, value: unknown) => {\n if (!isObject(value)) return protocolError(\"syn must be an object\");\n validateSynScalars(value);\n if (value[\"record\"] !== undefined || value[\"idle\"] !== undefined) {\n protocolError(\"invalid mid-stream syn\");\n }\n if (\n value[\"seq\"] !== undefined ||\n value[\"ctxSeq\"] !== undefined ||\n value[\"retry\"] !== undefined\n ) {\n c.ctx.onRefusal(validateRefusalSyn(value));\n return;\n }\n if (value[\"id\"] !== undefined) return;\n if (Object.keys(value).length === 0) {\n protocolError(\"invalid mid-stream syn\");\n }\n warnUnknownSynFact();\n};\n\nconst deliverEnvelope = (c: Conn, env: StatewireEnvelope) => {\n if (env.syn !== undefined) deliverSyn(c, env.syn);\n if (env.ops !== undefined) {\n const held = c.held;\n c.held = [];\n c.ctx.onOps({\n ops: reviveOps(env.ops),\n cmds: [...held, ...cmdsOf(env)],\n });\n } else if (env.cmd !== undefined) {\n const cmds = cmdsOf(env);\n if (env.next === true) c.held.push(...cmds);\n else c.ctx.onCmds(cmds);\n }\n if (typeof env.idle === \"boolean\") c.ctx.onIdle(env.idle);\n};\n\nconst transientCauseOf = (\n reason: StatewireHost.Fin[\"reason\"],\n): Episode[\"cause\"] => {\n switch (reason) {\n case \"evicted\":\n return \"evicted\";\n case \"error\":\n return \"error\";\n case \"unauthorized\":\n return \"unauthorized\";\n default:\n return \"error\";\n }\n};\n\nconst settleFin = (c: Conn, fin: StatewireHost.Fin): AttemptOutcome => {\n let finish = fin;\n if (finish.meta !== undefined) {\n const { meta, ...rest } = finish;\n finish = { ...rest, payload: reviveValue(rest.payload, meta) };\n }\n releaseHeld(c);\n if (finish.reason === \"idle\") {\n c.ctx.onIdle(true);\n c.attempt = 0;\n c.episode = null;\n setStatus(c, { status: \"idle\" });\n return \"idle\";\n }\n const terminal = finish.reason === \"gone\" || finish.reason === \"superseded\";\n c.ctx.onFinish(terminal ? finish : { ...finish, reason: \"error\" });\n if (!terminal) {\n c.episode = {\n cause: transientCauseOf(finish.reason),\n ...(finish.message !== undefined && { message: finish.message }),\n };\n return \"reattach\";\n }\n setStatus(c, {\n status: \"gone\",\n ...(finish.message !== undefined && { message: finish.message }),\n ...(finish.payload !== undefined && { payload: finish.payload }),\n });\n return \"stop\";\n};\n\nexport const handleEnvelope = (\n c: Conn,\n value: unknown,\n): AttemptOutcome | null => {\n const env = validateEnvelope(value);\n if (c.awaitingHello) {\n if (env.fin !== undefined) return settleFin(c, env.fin);\n handleHello(c, env);\n return null;\n }\n deliverEnvelope(c, env);\n if (env.fin !== undefined) return settleFin(c, env.fin);\n if (c.connection.status !== \"live\") {\n c.attempt = 0;\n c.episode = null;\n setStatus(c, { status: \"live\" });\n }\n return null;\n};\n\nconst scheduleRetry = (\n c: Conn,\n failure: string | undefined,\n immediate: boolean,\n) => {\n if (c.liveAt !== null && Date.now() - c.liveAt >= timing.backoffResetMs) {\n c.attempt = 0;\n }\n c.liveAt = null;\n c.attempt += 1;\n c.episode ??= { cause: \"dropped\" };\n const delay = immediate ? 0 : backoff(c.attempt);\n setStatus(c, {\n status: \"reconnecting\",\n ...c.episode,\n attempt: c.attempt,\n nextRetryAt: Date.now() + delay,\n ...(failure !== undefined && { lastError: failure }),\n });\n return delay;\n};\n\nconst reconnectConn = (c: Conn) => {\n if (!c.lifetime) return;\n if (c.connection.status === \"gone\" || c.connection.status === \"idle\") {\n c.attempt = 0;\n c.episode = { cause: \"dropped\" };\n flushTapSync(() => {\n scheduleRetry(c, undefined, true);\n });\n }\n openGate(c.gate);\n c.abort?.abort();\n};\n\nconst run = async (c: Conn, lifetime: AbortController, gate: Gate) => {\n const alive = () => c.lifetime === lifetime;\n while (alive()) {\n const abort = new AbortController();\n c.abort = abort;\n c.awaitingHello = true;\n c.held = [];\n let outcome: AttemptOutcome | undefined;\n let failure: string | undefined;\n try {\n outcome = await c.attemptOnce(abort);\n } catch (error) {\n if (!abort.signal.aborted) {\n failure =\n error instanceof Error && error.message ? error.message : \"network\";\n }\n }\n abort.abort();\n if (!alive()) return;\n flushTapSync(() => {\n releaseHeld(c);\n c.ctx.onDetach();\n });\n if (!alive()) return;\n if (outcome === \"stop\" || outcome === \"idle\") {\n await waitGate(gate);\n continue;\n }\n const immediate = takeGate(gate);\n const delay = flushTapSync(() => scheduleRetry(c, failure, immediate));\n if (delay === 0) continue;\n await waitGate(gate, delay);\n }\n};\n\nexport const useStatewireConn = (props: {\n url: string;\n onChange?: ((connection: StatewireClient.Connection) => void) | undefined;\n ctx: StatewireRemoteProps;\n attemptOnce: (c: Conn, abort: AbortController) => Promise<AttemptOutcome>;\n}): Conn => {\n const latest = useRef(props);\n latest.current = props;\n const [, setConnection] = useState<StatewireClient.Connection | null>(null);\n const [c] = useState((): Conn => {\n const conn: Conn = {\n hasSnapshot: false,\n lease: null,\n attempt: 0,\n liveAt: null,\n episode: null,\n awaitingHello: true,\n held: [],\n abort: null,\n gate: newGate(),\n lifetime: null,\n get ctx() {\n return latest.current.ctx;\n },\n onChange: (connection) => latest.current.onChange?.(connection),\n attemptOnce: (abort) => latest.current.attemptOnce(conn, abort),\n notify: setConnection,\n reconnect: () => reconnectConn(conn),\n connection: { status: \"connecting\", reconnect: () => conn.reconnect() },\n };\n return conn;\n });\n\n useEffect(() => {\n c.hasSnapshot = false;\n c.lease = null;\n c.attempt = 0;\n c.liveAt = null;\n c.episode = null;\n if (c.connection.status !== \"connecting\") {\n setStatus(c, { status: \"connecting\" });\n }\n const lifetime = new AbortController();\n c.lifetime = lifetime;\n c.gate = newGate();\n void run(c, lifetime, c.gate);\n return () => {\n c.abort?.abort();\n lifetime.abort();\n if (c.lifetime === lifetime) c.lifetime = null;\n openGate(c.gate);\n };\n }, [c, props.url]);\n\n return c;\n};\n\nexport const classify = (timeout: AbortSignal) =>\n new Error(timeout.aborted ? \"timeout\" : \"network\");\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.d.ts","names":[],"sources":["../../src/client/session.ts"],"mappings":";;;;;;KAyBK;EACH;EACA;EACA;;KAGG;WACM;WACA,SAAS;WACT,KAAK;;EAEd;;EAEA;;EAEA;EACA,UAAU;EACV,SAAS,OAAO;;KAGb;WACM;WACA;EACT;;KAiBG;KAEO,0BAA0B;EACpC;;KAGG;EACH,QAAQ;EACR,KAAK;EACL;EACA,OAAO;EACP;EACA;EACA;EACA;EACA;EACA;EACA;EACA,YAAY;EACZ;EACA,0BAA0B,qBAAqB;EAC/C;EACA,SAAS;EACT;EACA;EACA,SAAS;EACT,QAAQ,UAAU;EAClB,QAAQ;EACR;EACA;EACA;EACA,WAAW;EACX;EACA,WAAW;EACX;EACA,UAAU,mBAAmB,sBAAsB;;
|
|
1
|
+
{"version":3,"file":"session.d.ts","names":[],"sources":["../../src/client/session.ts"],"mappings":";;;;;;KAyBK;EACH;EACA;EACA;;KAGG;WACM;WACA,SAAS;WACT,KAAK;;EAEd;;EAEA;;EAEA;EACA,UAAU;EACV,SAAS,OAAO;;KAGb;WACM;WACA;EACT;;KAiBG;KAEO,0BAA0B;EACpC;;KAGG;EACH,QAAQ;EACR,KAAK;EACL;EACA,OAAO;EACP;EACA;EACA;EACA;EACA;EACA;EACA;EACA,YAAY;EACZ;EACA,0BAA0B,qBAAqB;EAC/C;EACA,SAAS;EACT;EACA;EACA,SAAS;EACT,QAAQ,UAAU;EAClB,QAAQ;EACR;EACA;EACA;EACA,WAAW;EACX;EACA,WAAW;EACX;EACA,UAAU,mBAAmB,sBAAsB;;cAsd/C,eAAgB,GAAG,SAAS,WAAW;cA6DvC,aAAc,GAAG,SAAS,OAAO;cAoB1B,sBACX,SAAS,4BACR"}
|
package/dist/client/session.js
CHANGED
|
@@ -150,17 +150,16 @@ const ephemeralDetach = (s) => {
|
|
|
150
150
|
resetRecord(s, newClientId());
|
|
151
151
|
};
|
|
152
152
|
const rejectedFailure = (cmd) => {
|
|
153
|
-
const code = cmd.code === void 0 || cmd.code === "unknown-command" || cmd.code === "invalid-params" ? cmd.code : protocolError(`unknown rejected code: ${cmd.code}`);
|
|
154
153
|
return {
|
|
155
154
|
fate: "rejected",
|
|
156
155
|
cause: "server",
|
|
157
|
-
...code !== void 0 && { code },
|
|
156
|
+
...cmd.code !== void 0 && { code: cmd.code },
|
|
158
157
|
...cmd.message !== void 0 && { message: cmd.message },
|
|
159
158
|
...cmd.payload !== void 0 && { payload: cmd.payload }
|
|
160
159
|
};
|
|
161
160
|
};
|
|
162
161
|
const handleCmd = (s, cmd) => {
|
|
163
|
-
if (
|
|
162
|
+
if (!Number.isSafeInteger(cmd.seq) || cmd.seq <= 0) protocolError("cmd.seq must be a positive safe integer");
|
|
164
163
|
if (cmd.dur === true) {
|
|
165
164
|
s.durableSeq = Math.max(s.durableSeq, cmd.seq);
|
|
166
165
|
for (const entry of s.pending) if (entry.seq <= s.durableSeq) entry.posted = true;
|
|
@@ -277,7 +276,7 @@ const handleRefusal = (s, syn) => {
|
|
|
277
276
|
s.ctxPending = s.ctxPending.filter((c) => c.seq > ctxSeq);
|
|
278
277
|
for (const c of s.ctxPending) c.posted = false;
|
|
279
278
|
}
|
|
280
|
-
if (typeof syn.retry === "number") s.resumeAt = Date.now() +
|
|
279
|
+
if (typeof syn.retry === "number") s.resumeAt = Date.now() + syn.retry;
|
|
281
280
|
const firstCmd = s.pending.find((p) => !p.posted);
|
|
282
281
|
const firstCtx = s.ctxPending.find((c) => !c.posted);
|
|
283
282
|
if (typeof syn.seq === "number" && firstCmd !== void 0 && firstCmd.seq > Math.max(syn.seq, s.durableSeq) + 1 || typeof syn.ctxSeq === "number" && firstCtx !== void 0 && firstCtx.seq > syn.ctxSeq + 1) s.transport?.connection.reconnect();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.js","names":["useEffect","useState","applyOps","StatewirePath","StatewireCmd","StatewireSyn","encodeParams","encodeValue","reviveResponse","bindCommandsHost","CommandsInvocation","CommandsListener","Statewire","StatewireClient","createMemorySessionStore","StatewireSessionRecord","StatewireSessionStore","StatewireSessionStoreOptions","backoff","createMethodProxy","randomId","StatewireSendError","RemoteLink","StatewireFrame","StatewireRemoteProps","WireCommand","method","params","meta","Pending","seq","command","inv","attempted","posted","applied","resolve","payload","reject","error","CtxPending","ops","protocolError","message","Error","newClientId","rejectedSend","failure","SendFailure","Promise","result","catch","AttachState","StatewireSessionOptions","onDone","Session","record","ctx","recordPersisted","store","ephemeral","sessionKnown","durableSeq","resumeAt","idle","ctxOps","ctxPending","lanesOnAttach","attachLaneSeqs","ReadonlySet","frameFailures","pending","canonical","lastPublished","changed","source","StateSource","attach","attachEpoch","running","pumping","transport","waiters","lifecycle","notify","commands","Record","publish","s","wake","waiter","waitForWake","r","push","sleepUntilWake","delayMs","clearTimeout","timer","setTimeout","filter","w","setRecord","save","setIdle","level","cover","entry","onApplied","onCovered","settleEntry","outcome","ok","p","onSettle","type","settleAll","detach","cause","unmount","gone","superseded","const","batch","detachFailure","predecessorLost","some","fate","restateContext","undefined","ctxNextSeq","resetRecord","clientId","survivors","nextSeq","old","enqueue","ephemeralDetach","rejectedFailure","cmd","code","handleCmd","dur","Math","max","find","String","handleCmds","cmds","ingestOps","state","changedPaths","publishIngested","RECORDS","snapClocks","seqWm","ctxWm","tail","cmdAligned","every","i","length","ctxAligned","c","handleHello","syn","includes","attachCmd","attachCtx","Set","has","ctxWatermark","ctxSeq","pump","handleOps","handleRefusal","watermark","retry","Date","now","firstCmd","firstCtx","clocksAhead","connection","reconnect","handleDetach","handleFinish","reason","isFinished","Lanes","frame","cmdEntries","ctxEntries","buildLanes","at","map","takeAttachLanes","wanted","lanes","status","resumeDelay","epoch","send","onPosted","start","stop","setTransport","ts","onStart","sendCommand","encoded","setContext","value","Array","isArray","op","path","useStatewireSession","options","defaultStore","sessionStore","stored","load","session","onHello","args","onOps","onCmds","onRefusal","onIdle","onDetach","onFinish","snapshot","takeChanged","setOnChange","listener","setListener"],"sources":["../../src/client/session.ts"],"sourcesContent":["import { useEffect, useState } from \"react\";\nimport { applyOps } from \"../wire/ops\";\nimport type { StatewirePath } from \"../wire/ops\";\nimport type { StatewireCmd, StatewireSyn } from \"./connection\";\nimport { encodeParams, encodeValue, reviveResponse } from \"../wire/meta\";\nimport { bindCommandsHost } from \"../host/host\";\nimport type { CommandsInvocation, CommandsListener } from \"../host/host\";\nimport type { Statewire } from \"../types\";\nimport type { StatewireClient } from \"../statewire\";\nimport { createMemorySessionStore } from \"./sessionStore\";\nimport type {\n StatewireSessionRecord,\n StatewireSessionStore,\n StatewireSessionStoreOptions,\n} from \"./sessionStore\";\nimport { backoff } from \"./timing\";\nimport { createMethodProxy } from \"../util/methodProxy\";\nimport { randomId } from \"../util/randomId\";\nimport { StatewireSendError } from \"../types\";\nimport type {\n RemoteLink,\n StatewireFrame,\n StatewireRemoteProps,\n} from \"../transports/sse\";\n\ntype WireCommand = {\n method: string;\n params: unknown[];\n meta?: unknown;\n};\n\ntype Pending = {\n readonly seq: number;\n readonly command: WireCommand;\n readonly inv: CommandsInvocation;\n /** A send carrying this statement may have reached the server. */\n attempted: boolean;\n /** In the resend queue when false. */\n posted: boolean;\n /** The server acknowledged admission; the terminal verdict is still due. */\n applied: boolean;\n resolve: (payload: unknown) => void;\n reject: (error: StatewireSendError) => void;\n};\n\ntype CtxPending = {\n readonly seq: number;\n readonly ops: unknown[];\n posted: boolean;\n};\n\nconst protocolError = (message: string): never => {\n throw new Error(`statewire: protocol error: ${message}`);\n};\n\nconst newClientId = () => `c-${randomId()}`;\n\nconst rejectedSend = (\n failure: StatewireClient.SendFailure,\n): Promise<unknown> => {\n const result = Promise.reject<unknown>(new StatewireSendError(failure));\n result.catch(() => {});\n return result;\n};\n\ntype AttachState = \"detached\" | \"attached\" | \"finished\";\n\nexport type StatewireSessionOptions = StatewireSessionStoreOptions & {\n onDone?: (() => void) | undefined;\n};\n\ntype Session = {\n record: StatewireSessionRecord;\n ctx: StatewireRemoteProps;\n recordPersisted: boolean;\n store: StatewireSessionStore;\n ephemeral: boolean;\n sessionKnown: boolean;\n durableSeq: number;\n resumeAt: number;\n idle: boolean;\n onDone: (() => void) | undefined;\n ctxOps: unknown[] | undefined;\n ctxPending: CtxPending[];\n lanesOnAttach: boolean;\n attachLaneSeqs: readonly [ReadonlySet<number>, ReadonlySet<number>];\n frameFailures: number;\n pending: Pending[];\n canonical: unknown;\n lastPublished: unknown;\n changed: StatewirePath[];\n source: Statewire.StateSource;\n attach: AttachState;\n attachEpoch: number;\n running: boolean;\n pumping: boolean;\n transport: RemoteLink | null;\n waiters: (() => void)[];\n lifecycle: CommandsListener | null;\n notify: () => void;\n commands: Record<string, (...params: unknown[]) => Promise<unknown>>;\n};\n\nconst publish = (s: Session) => {\n if (s.canonical === s.lastPublished) return;\n s.lastPublished = s.canonical;\n s.notify();\n};\n\nconst wake = (s: Session) => {\n const waiters = s.waiters;\n s.waiters = [];\n for (const waiter of waiters) waiter();\n};\n\nconst waitForWake = (s: Session) => new Promise<void>((r) => s.waiters.push(r));\n\nconst sleepUntilWake = (s: Session, delayMs: number) =>\n new Promise<void>((resolve) => {\n const waiter = () => {\n clearTimeout(timer);\n resolve();\n };\n const timer = setTimeout(() => {\n s.waiters = s.waiters.filter((w) => w !== waiter);\n resolve();\n }, delayMs);\n s.waiters.push(waiter);\n });\n\nconst setRecord = (s: Session, record: StatewireSessionRecord) => {\n s.record = record;\n if (!s.ephemeral) s.store.save(record);\n};\n\nconst setIdle = (s: Session, level: boolean) => {\n if (level === s.idle) return;\n s.idle = level;\n s.notify();\n if (level) s.onDone?.();\n};\n\nconst cover = (s: Session, entry: Pending) => {\n if (entry.applied) return;\n entry.applied = true;\n s.lifecycle?.onApplied(entry.inv);\n s.lifecycle?.onCovered?.(entry.inv);\n};\n\nconst settleEntry = (\n s: Session,\n entry: Pending,\n outcome:\n | { ok: true; payload: unknown }\n | { ok: false; failure: StatewireClient.SendFailure },\n) => {\n s.pending = s.pending.filter((p) => p !== entry);\n if (outcome.ok) {\n entry.resolve(outcome.payload);\n s.lifecycle?.onSettle(entry.inv, {\n type: \"accepted\",\n payload: outcome.payload,\n });\n } else {\n entry.reject(new StatewireSendError(outcome.failure));\n s.lifecycle?.onSettle(entry.inv, {\n type: \"rejected\",\n error: new StatewireSendError(outcome.failure),\n });\n }\n};\n\nconst settleAll = (s: Session, detach: \"unmount\" | \"gone\" | \"superseded\") => {\n const cause = (\n {\n unmount: \"unmount\",\n gone: \"stream-gone\",\n superseded: \"superseded\",\n } as const\n )[detach];\n const batch = s.pending;\n const detachFailure = (entry: Pending): StatewireClient.SendFailure => {\n if (!entry.attempted) {\n const predecessorLost = batch.some(\n (p) => p.seq < entry.seq && p.attempted,\n );\n return predecessorLost\n ? { fate: \"aborted\", cause, predecessorLost }\n : { fate: \"aborted\", cause };\n }\n return { fate: \"lost\", cause };\n };\n for (const entry of [...batch]) {\n s.lifecycle?.onCovered?.(entry.inv);\n settleEntry(s, entry, { ok: false, failure: detachFailure(entry) });\n }\n};\n\nconst restateContext = (s: Session) => {\n s.ctxPending = [];\n if (s.ctxOps === undefined) return;\n const seq = s.record.ctxNextSeq;\n setRecord(s, { ...s.record, ctxNextSeq: seq + 1 });\n s.ctxPending.push({ seq, ops: s.ctxOps, posted: false });\n};\n\n// The server-side record's dedup memory is gone: history that may have\n// reached a server settles lost — the new hello's snapshot is the only\n// truth about what survived — and never-attempted statements re-stamp\n// from 1 on the reset lane clocks.\nconst resetRecord = (s: Session, clientId: string) => {\n const survivors: Pending[] = [];\n for (const entry of [...s.pending]) {\n if (entry.attempted || entry.applied) {\n s.lifecycle?.onCovered?.(entry.inv);\n settleEntry(s, entry, {\n ok: false,\n failure: { fate: \"lost\", cause: \"session-lost\" },\n });\n } else {\n survivors.push(entry);\n }\n }\n s.pending = [];\n s.durableSeq = 0;\n setRecord(s, { clientId, nextSeq: 1, ctxNextSeq: 1 });\n for (const old of survivors) {\n s.lifecycle?.onCovered?.(old.inv);\n enqueue(s, old.command, old.inv.params, old.resolve, old.reject);\n }\n restateContext(s);\n publish(s);\n wake(s);\n};\n\n// The record died with the attach: mint a fresh id for the next one.\nconst ephemeralDetach = (s: Session) => {\n s.ephemeral = false;\n s.sessionKnown = false;\n resetRecord(s, newClientId());\n};\n\nconst rejectedFailure = (cmd: StatewireCmd): StatewireClient.SendFailure => {\n const code =\n cmd.code === undefined ||\n cmd.code === \"unknown-command\" ||\n cmd.code === \"invalid-params\"\n ? cmd.code\n : protocolError(`unknown rejected code: ${cmd.code}`);\n return {\n fate: \"rejected\",\n cause: \"server\",\n ...(code !== undefined && { code }),\n ...(cmd.message !== undefined && { message: cmd.message }),\n ...(cmd.payload !== undefined && { payload: cmd.payload }),\n };\n};\n\nconst handleCmd = (s: Session, cmd: StatewireCmd) => {\n if (typeof cmd.seq !== \"number\") protocolError(\"cmd entry missing seq\");\n if (cmd.dur === true) {\n s.durableSeq = Math.max(s.durableSeq, cmd.seq);\n for (const entry of s.pending) {\n if (entry.seq <= s.durableSeq) entry.posted = true;\n }\n }\n if (cmd.type === undefined) return;\n const entry = s.pending.find((p) => p.seq === cmd.seq);\n if (cmd.type === \"applied\") {\n if (entry) cover(s, entry);\n return;\n }\n if (!entry) return;\n cover(s, entry);\n const outcome =\n cmd.type === \"result\"\n ? { ok: true as const, payload: reviveResponse(cmd).payload }\n : cmd.type === \"rejected\"\n ? { ok: false as const, failure: rejectedFailure(reviveResponse(cmd)) }\n : cmd.type === \"failed\"\n ? {\n ok: false as const,\n failure: {\n fate: \"failed\" as const,\n cause: \"server\" as const,\n ...(cmd.message !== undefined && { message: cmd.message }),\n },\n }\n : cmd.type === \"crashed\"\n ? {\n ok: false as const,\n failure: { fate: \"crashed\" as const, cause: \"server\" as const },\n }\n : cmd.type === \"expired\"\n ? {\n ok: false as const,\n failure: {\n fate: \"expired\" as const,\n cause: \"server\" as const,\n },\n }\n : protocolError(`unknown cmd type: ${String(cmd.type)}`);\n settleEntry(s, entry, outcome);\n};\n\nconst handleCmds = (s: Session, cmds: StatewireCmd[]) => {\n for (const cmd of cmds) handleCmd(s, cmd);\n wake(s);\n};\n\nconst ingestOps = (s: Session, ops: unknown[]) => {\n const applied = applyOps(s.canonical, ops);\n s.canonical = applied.state;\n s.changed.push(...applied.changedPaths);\n};\n\nconst publishIngested = (s: Session) => {\n publish(s);\n wake(s);\n};\n\nconst RECORDS = [\"fresh\", \"resumed\", \"ephemeral\"];\n\n// Snap a resumed session's lane clocks onto the record: seqs above the stated\n// watermark were never admitted, so a stale restored clock re-stamps its\n// never-admitted statements consecutively after the watermark.\nconst snapClocks = (s: Session, seqWm: number, ctxWm: number) => {\n const tail = s.pending.filter((p) => p.seq > seqWm);\n const cmdAligned =\n tail.every((p, i) => p.seq === seqWm + 1 + i) &&\n s.record.nextSeq === seqWm + tail.length + 1;\n if (!cmdAligned) {\n s.pending = s.pending.filter((p) => p.seq <= seqWm);\n setRecord(s, { ...s.record, nextSeq: seqWm + 1 });\n for (const old of tail) {\n s.lifecycle?.onCovered?.(old.inv);\n enqueue(s, old.command, old.inv.params, old.resolve, old.reject);\n }\n }\n const ctxAligned =\n s.ctxPending.every((c, i) => c.seq === ctxWm + 1 + i) &&\n s.record.ctxNextSeq === ctxWm + s.ctxPending.length + 1;\n if (!ctxAligned) {\n setRecord(s, { ...s.record, ctxNextSeq: ctxWm + 1 });\n restateContext(s);\n }\n};\n\nconst handleHello = (\n s: Session,\n { ops, syn }: { ops: unknown[]; syn: StatewireSyn },\n) => {\n const record = syn.record ?? \"fresh\";\n if (!RECORDS.includes(record)) {\n protocolError(`unknown record: ${String(record)}`);\n }\n ingestOps(s, ops);\n s.attach = \"attached\";\n s.attachEpoch += 1;\n s.frameFailures = 0;\n s.resumeAt = 0;\n s.ephemeral = record === \"ephemeral\";\n const [attachCmd, attachCtx] = s.attachLaneSeqs;\n s.attachLaneSeqs = [new Set(), new Set()];\n if (record === \"resumed\") {\n // Resending unsettled statements is exactly-once-safe: absorbed replays\n // re-emit their stored verdicts (applied while still in flight).\n for (const entry of s.pending) {\n entry.posted = attachCmd.has(entry.seq);\n }\n const ctxWatermark = syn.ctxSeq ?? 0;\n s.ctxPending = s.ctxPending.filter((c) => c.seq > ctxWatermark);\n for (const c of s.ctxPending) c.posted = attachCtx.has(c.seq);\n snapClocks(s, syn.seq ?? 0, ctxWatermark);\n } else {\n resetRecord(s, s.record.clientId);\n }\n s.sessionKnown = true;\n publishIngested(s);\n void pump(s);\n};\n\nconst handleOps = (\n s: Session,\n { ops, cmds }: { ops: unknown[]; cmds: StatewireCmd[] },\n) => {\n ingestOps(s, ops);\n for (const cmd of cmds) handleCmd(s, cmd);\n publishIngested(s);\n};\n\n// A {syn} refusal never settles: reconcile the resend queues against the\n// stated watermarks; retry present means wait, absent means resend now.\nconst handleRefusal = (s: Session, syn: StatewireSyn) => {\n const { seq, ctxSeq } = syn;\n if (typeof seq === \"number\") {\n const watermark = Math.max(seq, s.durableSeq);\n for (const entry of s.pending) entry.posted = entry.seq <= watermark;\n }\n if (typeof ctxSeq === \"number\") {\n s.ctxPending = s.ctxPending.filter((c) => c.seq > ctxSeq);\n for (const c of s.ctxPending) c.posted = false;\n }\n if (typeof syn.retry === \"number\") {\n s.resumeAt = Date.now() + Math.max(0, syn.retry);\n }\n const firstCmd = s.pending.find((p) => !p.posted);\n const firstCtx = s.ctxPending.find((c) => !c.posted);\n const clocksAhead =\n (typeof syn.seq === \"number\" &&\n firstCmd !== undefined &&\n firstCmd.seq > Math.max(syn.seq, s.durableSeq) + 1) ||\n (typeof syn.ctxSeq === \"number\" &&\n firstCtx !== undefined &&\n firstCtx.seq > syn.ctxSeq + 1);\n // Clocks ahead of a record that cannot admit them: reattach first and let\n // the hello's record arbitrate.\n if (clocksAhead) s.transport?.connection.reconnect();\n wake(s);\n void pump(s);\n};\n\nconst handleDetach = (s: Session) => {\n if (s.attach === \"attached\") s.attach = \"detached\";\n if (s.ephemeral) ephemeralDetach(s);\n wake(s);\n};\n\nconst handleFinish = (s: Session, { reason }: { reason: string }) => {\n if (reason === \"evicted\" || reason === \"error\") return;\n s.attach = \"finished\";\n settleAll(s, reason === \"superseded\" ? \"superseded\" : \"gone\");\n publish(s);\n wake(s);\n};\n\nconst isFinished = (s: Session) => s.attach === \"finished\";\n\ntype Lanes = {\n frame: StatewireFrame;\n cmdEntries: Pending[];\n ctxEntries: CtxPending[];\n};\n\n// A lane must be strictly consecutive within a frame: the first unposted run\n// per lane rides now, later runs ride follow-up frames.\nconst buildLanes = (s: Session): Lanes | null => {\n const ctxEntries: CtxPending[] = [];\n for (const entry of s.ctxPending) {\n if (entry.posted) continue;\n if (ctxEntries.length > 0 && entry.seq !== ctxEntries.at(-1)!.seq + 1)\n break;\n ctxEntries.push(entry);\n }\n const cmdEntries: Pending[] = [];\n for (const entry of s.pending) {\n if (entry.posted) continue;\n if (cmdEntries.length > 0 && entry.seq !== cmdEntries.at(-1)!.seq + 1)\n break;\n cmdEntries.push(entry);\n }\n if (ctxEntries.length === 0 && cmdEntries.length === 0) return null;\n return {\n frame: {\n ...(ctxEntries.length > 0 && {\n ctx: ctxEntries.map((c) => ({ ops: c.ops, seq: c.seq })),\n }),\n ...(cmdEntries.length > 0 && {\n cmd: cmdEntries.map((p) => ({ ...p.command, seq: p.seq })),\n }),\n },\n cmdEntries,\n ctxEntries,\n };\n};\n\nconst takeAttachLanes = (s: Session): StatewireFrame | null => {\n s.attachLaneSeqs = [new Set(), new Set()];\n const wanted = s.lanesOnAttach;\n s.lanesOnAttach = false;\n if (!wanted || !s.sessionKnown) return null;\n const lanes = buildLanes(s);\n if (!lanes) return null;\n s.attachLaneSeqs = [\n new Set(lanes.cmdEntries.map((p) => p.seq)),\n new Set(lanes.ctxEntries.map((c) => c.seq)),\n ];\n for (const entry of lanes.cmdEntries) entry.attempted = true;\n return lanes.frame;\n};\n\nconst pump = async (s: Session) => {\n if (s.pumping) return;\n s.pumping = true;\n try {\n while (s.running && !isFinished(s)) {\n const transport = s.transport;\n if (buildLanes(s) === null) return;\n if (s.attach !== \"attached\" || !transport) {\n if (transport?.connection.status === \"idle\") {\n transport.connection.reconnect();\n }\n await waitForWake(s);\n continue;\n }\n const resumeDelay = s.resumeAt - Date.now();\n if (resumeDelay > 0) {\n await sleepUntilWake(s, resumeDelay);\n continue;\n }\n const lanes = buildLanes(s);\n if (!lanes) continue;\n const epoch = s.attachEpoch;\n for (const entry of lanes.cmdEntries) entry.attempted = true;\n let result;\n try {\n result = await transport.send(lanes.frame);\n } catch {\n if (!s.running || isFinished(s)) return;\n s.frameFailures += 1;\n await sleepUntilWake(s, backoff(s.frameFailures));\n continue;\n }\n if (!s.running) return;\n s.frameFailures = 0;\n if (result.type === \"ok\") {\n if (epoch === s.attachEpoch) {\n for (const entry of lanes.cmdEntries) {\n if (s.pending.includes(entry)) {\n entry.posted = true;\n s.lifecycle?.onPosted?.(entry.inv);\n }\n }\n for (const entry of lanes.ctxEntries) entry.posted = true;\n }\n } else if (result.type === \"refusal\") {\n if (epoch === s.attachEpoch) handleRefusal(s, result.syn);\n } else if (result.type === \"stale-lease\") {\n // A POST outlived its attach: reattach first, the hello arbitrates.\n if (epoch === s.attachEpoch) {\n transport.connection.reconnect();\n await waitForWake(s);\n }\n } else if (result.type === \"no-lease\") {\n // No out-of-band write channel: the frame rides a fresh attach.\n if (epoch === s.attachEpoch) {\n s.lanesOnAttach = true;\n transport.connection.reconnect();\n while (s.running && !isFinished(s) && epoch === s.attachEpoch) {\n await waitForWake(s);\n }\n }\n }\n }\n } finally {\n s.pumping = false;\n }\n};\n\nconst start = (s: Session) => {\n if (!s.recordPersisted) {\n s.recordPersisted = true;\n s.store.save(s.record);\n }\n s.running = true;\n void pump(s);\n};\n\nconst stop = (s: Session) => {\n s.running = false;\n wake(s);\n settleAll(s, \"unmount\");\n};\n\nconst setTransport = (s: Session, transport: RemoteLink) => {\n if (s.transport === transport) return;\n s.transport = transport;\n wake(s);\n};\n\nconst enqueue = (\n s: Session,\n command: WireCommand,\n params: readonly unknown[],\n resolve: (payload: unknown) => void,\n reject: (error: StatewireSendError) => void,\n) => {\n const seq = s.record.nextSeq;\n setRecord(s, { ...s.record, nextSeq: seq + 1 });\n const entry: Pending = {\n seq,\n command,\n inv: {\n method: command.method,\n params,\n ts: Date.now(),\n seq,\n clientId: s.record.clientId,\n },\n attempted: false,\n posted: false,\n applied: false,\n resolve,\n reject,\n };\n s.pending.push(entry);\n s.lifecycle?.onStart(entry.inv);\n void pump(s);\n};\n\nconst sendCommand = (\n s: Session,\n method: string,\n params: readonly unknown[],\n): Promise<unknown> => {\n if (!s.running) {\n return rejectedSend({ fate: \"aborted\", cause: \"unmount\" });\n }\n if (isFinished(s)) {\n return rejectedSend({ fate: \"aborted\", cause: \"stream-gone\" });\n }\n const result = new Promise<unknown>((resolve, reject) => {\n const { params: encoded, meta } = encodeParams(params);\n enqueue(\n s,\n { method, params: encoded, ...(meta !== undefined && { meta }) },\n params,\n resolve,\n reject,\n );\n });\n result.catch(() => {});\n return result;\n};\n\nconst setContext = (s: Session, value: Record<string, unknown>): void => {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n throw new Error(\"statewire: context must be a plain object\");\n }\n const { value: encoded, meta } = encodeValue(value);\n s.ctxOps = [\n {\n op: \"replace\",\n path: [],\n value: encoded,\n ...(meta !== undefined && { meta }),\n },\n ];\n const seq = s.record.ctxNextSeq;\n setRecord(s, { ...s.record, ctxNextSeq: seq + 1 });\n s.ctxPending.push({ seq, ops: s.ctxOps, posted: false });\n wake(s);\n void pump(s);\n};\n\nexport const useStatewireSession = (\n options: StatewireSessionOptions,\n): Session => {\n const [defaultStore] = useState(createMemorySessionStore);\n const store = options.sessionStore ?? defaultStore;\n const [s] = useState((): Session => {\n const stored = store.load();\n const record = stored ?? {\n clientId: newClientId(),\n nextSeq: 1,\n ctxNextSeq: 1,\n };\n const session: Session = {\n record,\n ctx: {\n get clientId() {\n return session.record.clientId;\n },\n takeAttachLanes: () => takeAttachLanes(session),\n onHello: (args) => handleHello(session, args),\n onOps: (args) => handleOps(session, args),\n onCmds: (cmds) => handleCmds(session, cmds),\n onRefusal: (syn) => handleRefusal(session, syn),\n onIdle: (level) => setIdle(session, level),\n onDetach: () => handleDetach(session),\n onFinish: (args) => handleFinish(session, args),\n },\n recordPersisted: stored !== null,\n store,\n ephemeral: false,\n sessionKnown: false,\n durableSeq: 0,\n resumeAt: 0,\n idle: false,\n onDone: undefined,\n ctxOps: undefined,\n ctxPending: [],\n lanesOnAttach: false,\n attachLaneSeqs: [new Set(), new Set()],\n frameFailures: 0,\n pending: [],\n canonical: undefined,\n lastPublished: undefined,\n changed: [],\n source: {\n snapshot: () => session.canonical,\n takeChanged: () => {\n const changed = session.changed;\n session.changed = [];\n return changed;\n },\n setOnChange: (listener) => {\n session.notify = listener ?? (() => {});\n },\n },\n attach: \"detached\",\n attachEpoch: 0,\n running: false,\n pumping: false,\n transport: null,\n waiters: [],\n lifecycle: null,\n notify: () => {},\n commands: createMethodProxy((method, params) =>\n sendCommand(session, method, params),\n ),\n };\n bindCommandsHost(session.commands, {\n setListener: (listener) => {\n session.lifecycle = listener;\n },\n });\n return session;\n });\n s.store = store;\n s.onDone = options.onDone;\n useEffect(() => {\n start(s);\n return () => stop(s);\n }, [s]);\n return s;\n};\n\nexport { setContext, setTransport };\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"session.js","names":["useEffect","useState","applyOps","StatewirePath","StatewireCmd","StatewireSyn","encodeParams","encodeValue","reviveResponse","bindCommandsHost","CommandsInvocation","CommandsListener","Statewire","StatewireClient","createMemorySessionStore","StatewireSessionRecord","StatewireSessionStore","StatewireSessionStoreOptions","backoff","createMethodProxy","randomId","StatewireSendError","RemoteLink","StatewireFrame","StatewireRemoteProps","WireCommand","method","params","meta","Pending","seq","command","inv","attempted","posted","applied","resolve","payload","reject","error","CtxPending","ops","protocolError","message","Error","newClientId","rejectedSend","failure","SendFailure","Promise","result","catch","AttachState","StatewireSessionOptions","onDone","Session","record","ctx","recordPersisted","store","ephemeral","sessionKnown","durableSeq","resumeAt","idle","ctxOps","ctxPending","lanesOnAttach","attachLaneSeqs","ReadonlySet","frameFailures","pending","canonical","lastPublished","changed","source","StateSource","attach","attachEpoch","running","pumping","transport","waiters","lifecycle","notify","commands","Record","publish","s","wake","waiter","waitForWake","r","push","sleepUntilWake","delayMs","clearTimeout","timer","setTimeout","filter","w","setRecord","save","setIdle","level","cover","entry","onApplied","onCovered","settleEntry","outcome","ok","p","onSettle","type","settleAll","detach","cause","unmount","gone","superseded","const","batch","detachFailure","predecessorLost","some","fate","restateContext","undefined","ctxNextSeq","resetRecord","clientId","survivors","nextSeq","old","enqueue","ephemeralDetach","rejectedFailure","cmd","code","handleCmd","Number","isSafeInteger","dur","Math","max","find","String","handleCmds","cmds","ingestOps","state","changedPaths","publishIngested","RECORDS","snapClocks","seqWm","ctxWm","tail","cmdAligned","every","i","length","ctxAligned","c","handleHello","syn","includes","attachCmd","attachCtx","Set","has","ctxWatermark","ctxSeq","pump","handleOps","handleRefusal","watermark","retry","Date","now","firstCmd","firstCtx","clocksAhead","connection","reconnect","handleDetach","handleFinish","reason","isFinished","Lanes","frame","cmdEntries","ctxEntries","buildLanes","at","map","takeAttachLanes","wanted","lanes","status","resumeDelay","epoch","send","onPosted","start","stop","setTransport","ts","onStart","sendCommand","encoded","setContext","value","Array","isArray","op","path","useStatewireSession","options","defaultStore","sessionStore","stored","load","session","onHello","args","onOps","onCmds","onRefusal","onIdle","onDetach","onFinish","snapshot","takeChanged","setOnChange","listener","setListener"],"sources":["../../src/client/session.ts"],"sourcesContent":["import { useEffect, useState } from \"react\";\nimport { applyOps } from \"../wire/ops\";\nimport type { StatewirePath } from \"../wire/ops\";\nimport type { StatewireCmd, StatewireSyn } from \"./connection\";\nimport { encodeParams, encodeValue, reviveResponse } from \"../wire/meta\";\nimport { bindCommandsHost } from \"../host/host\";\nimport type { CommandsInvocation, CommandsListener } from \"../host/host\";\nimport type { Statewire } from \"../types\";\nimport type { StatewireClient } from \"../statewire\";\nimport { createMemorySessionStore } from \"./sessionStore\";\nimport type {\n StatewireSessionRecord,\n StatewireSessionStore,\n StatewireSessionStoreOptions,\n} from \"./sessionStore\";\nimport { backoff } from \"./timing\";\nimport { createMethodProxy } from \"../util/methodProxy\";\nimport { randomId } from \"../util/randomId\";\nimport { StatewireSendError } from \"../types\";\nimport type {\n RemoteLink,\n StatewireFrame,\n StatewireRemoteProps,\n} from \"../transports/sse\";\n\ntype WireCommand = {\n method: string;\n params: unknown[];\n meta?: unknown;\n};\n\ntype Pending = {\n readonly seq: number;\n readonly command: WireCommand;\n readonly inv: CommandsInvocation;\n /** A send carrying this statement may have reached the server. */\n attempted: boolean;\n /** In the resend queue when false. */\n posted: boolean;\n /** The server acknowledged admission; the terminal verdict is still due. */\n applied: boolean;\n resolve: (payload: unknown) => void;\n reject: (error: StatewireSendError) => void;\n};\n\ntype CtxPending = {\n readonly seq: number;\n readonly ops: unknown[];\n posted: boolean;\n};\n\nconst protocolError = (message: string): never => {\n throw new Error(`statewire: protocol error: ${message}`);\n};\n\nconst newClientId = () => `c-${randomId()}`;\n\nconst rejectedSend = (\n failure: StatewireClient.SendFailure,\n): Promise<unknown> => {\n const result = Promise.reject<unknown>(new StatewireSendError(failure));\n result.catch(() => {});\n return result;\n};\n\ntype AttachState = \"detached\" | \"attached\" | \"finished\";\n\nexport type StatewireSessionOptions = StatewireSessionStoreOptions & {\n onDone?: (() => void) | undefined;\n};\n\ntype Session = {\n record: StatewireSessionRecord;\n ctx: StatewireRemoteProps;\n recordPersisted: boolean;\n store: StatewireSessionStore;\n ephemeral: boolean;\n sessionKnown: boolean;\n durableSeq: number;\n resumeAt: number;\n idle: boolean;\n onDone: (() => void) | undefined;\n ctxOps: unknown[] | undefined;\n ctxPending: CtxPending[];\n lanesOnAttach: boolean;\n attachLaneSeqs: readonly [ReadonlySet<number>, ReadonlySet<number>];\n frameFailures: number;\n pending: Pending[];\n canonical: unknown;\n lastPublished: unknown;\n changed: StatewirePath[];\n source: Statewire.StateSource;\n attach: AttachState;\n attachEpoch: number;\n running: boolean;\n pumping: boolean;\n transport: RemoteLink | null;\n waiters: (() => void)[];\n lifecycle: CommandsListener | null;\n notify: () => void;\n commands: Record<string, (...params: unknown[]) => Promise<unknown>>;\n};\n\nconst publish = (s: Session) => {\n if (s.canonical === s.lastPublished) return;\n s.lastPublished = s.canonical;\n s.notify();\n};\n\nconst wake = (s: Session) => {\n const waiters = s.waiters;\n s.waiters = [];\n for (const waiter of waiters) waiter();\n};\n\nconst waitForWake = (s: Session) => new Promise<void>((r) => s.waiters.push(r));\n\nconst sleepUntilWake = (s: Session, delayMs: number) =>\n new Promise<void>((resolve) => {\n const waiter = () => {\n clearTimeout(timer);\n resolve();\n };\n const timer = setTimeout(() => {\n s.waiters = s.waiters.filter((w) => w !== waiter);\n resolve();\n }, delayMs);\n s.waiters.push(waiter);\n });\n\nconst setRecord = (s: Session, record: StatewireSessionRecord) => {\n s.record = record;\n if (!s.ephemeral) s.store.save(record);\n};\n\nconst setIdle = (s: Session, level: boolean) => {\n if (level === s.idle) return;\n s.idle = level;\n s.notify();\n if (level) s.onDone?.();\n};\n\nconst cover = (s: Session, entry: Pending) => {\n if (entry.applied) return;\n entry.applied = true;\n s.lifecycle?.onApplied(entry.inv);\n s.lifecycle?.onCovered?.(entry.inv);\n};\n\nconst settleEntry = (\n s: Session,\n entry: Pending,\n outcome:\n | { ok: true; payload: unknown }\n | { ok: false; failure: StatewireClient.SendFailure },\n) => {\n s.pending = s.pending.filter((p) => p !== entry);\n if (outcome.ok) {\n entry.resolve(outcome.payload);\n s.lifecycle?.onSettle(entry.inv, {\n type: \"accepted\",\n payload: outcome.payload,\n });\n } else {\n entry.reject(new StatewireSendError(outcome.failure));\n s.lifecycle?.onSettle(entry.inv, {\n type: \"rejected\",\n error: new StatewireSendError(outcome.failure),\n });\n }\n};\n\nconst settleAll = (s: Session, detach: \"unmount\" | \"gone\" | \"superseded\") => {\n const cause = (\n {\n unmount: \"unmount\",\n gone: \"stream-gone\",\n superseded: \"superseded\",\n } as const\n )[detach];\n const batch = s.pending;\n const detachFailure = (entry: Pending): StatewireClient.SendFailure => {\n if (!entry.attempted) {\n const predecessorLost = batch.some(\n (p) => p.seq < entry.seq && p.attempted,\n );\n return predecessorLost\n ? { fate: \"aborted\", cause, predecessorLost }\n : { fate: \"aborted\", cause };\n }\n return { fate: \"lost\", cause };\n };\n for (const entry of [...batch]) {\n s.lifecycle?.onCovered?.(entry.inv);\n settleEntry(s, entry, { ok: false, failure: detachFailure(entry) });\n }\n};\n\nconst restateContext = (s: Session) => {\n s.ctxPending = [];\n if (s.ctxOps === undefined) return;\n const seq = s.record.ctxNextSeq;\n setRecord(s, { ...s.record, ctxNextSeq: seq + 1 });\n s.ctxPending.push({ seq, ops: s.ctxOps, posted: false });\n};\n\n// The server-side record's dedup memory is gone: history that may have\n// reached a server settles lost — the new hello's snapshot is the only\n// truth about what survived — and never-attempted statements re-stamp\n// from 1 on the reset lane clocks.\nconst resetRecord = (s: Session, clientId: string) => {\n const survivors: Pending[] = [];\n for (const entry of [...s.pending]) {\n if (entry.attempted || entry.applied) {\n s.lifecycle?.onCovered?.(entry.inv);\n settleEntry(s, entry, {\n ok: false,\n failure: { fate: \"lost\", cause: \"session-lost\" },\n });\n } else {\n survivors.push(entry);\n }\n }\n s.pending = [];\n s.durableSeq = 0;\n setRecord(s, { clientId, nextSeq: 1, ctxNextSeq: 1 });\n for (const old of survivors) {\n s.lifecycle?.onCovered?.(old.inv);\n enqueue(s, old.command, old.inv.params, old.resolve, old.reject);\n }\n restateContext(s);\n publish(s);\n wake(s);\n};\n\n// The record died with the attach: mint a fresh id for the next one.\nconst ephemeralDetach = (s: Session) => {\n s.ephemeral = false;\n s.sessionKnown = false;\n resetRecord(s, newClientId());\n};\n\nconst rejectedFailure = (cmd: StatewireCmd): StatewireClient.SendFailure => {\n return {\n fate: \"rejected\",\n cause: \"server\",\n ...(cmd.code !== undefined && { code: cmd.code }),\n ...(cmd.message !== undefined && { message: cmd.message }),\n ...(cmd.payload !== undefined && { payload: cmd.payload }),\n };\n};\n\nconst handleCmd = (s: Session, cmd: StatewireCmd) => {\n if (!Number.isSafeInteger(cmd.seq) || cmd.seq <= 0) {\n protocolError(\"cmd.seq must be a positive safe integer\");\n }\n if (cmd.dur === true) {\n s.durableSeq = Math.max(s.durableSeq, cmd.seq);\n for (const entry of s.pending) {\n if (entry.seq <= s.durableSeq) entry.posted = true;\n }\n }\n if (cmd.type === undefined) return;\n const entry = s.pending.find((p) => p.seq === cmd.seq);\n if (cmd.type === \"applied\") {\n if (entry) cover(s, entry);\n return;\n }\n if (!entry) return;\n cover(s, entry);\n const outcome =\n cmd.type === \"result\"\n ? { ok: true as const, payload: reviveResponse(cmd).payload }\n : cmd.type === \"rejected\"\n ? { ok: false as const, failure: rejectedFailure(reviveResponse(cmd)) }\n : cmd.type === \"failed\"\n ? {\n ok: false as const,\n failure: {\n fate: \"failed\" as const,\n cause: \"server\" as const,\n ...(cmd.message !== undefined && { message: cmd.message }),\n },\n }\n : cmd.type === \"crashed\"\n ? {\n ok: false as const,\n failure: { fate: \"crashed\" as const, cause: \"server\" as const },\n }\n : cmd.type === \"expired\"\n ? {\n ok: false as const,\n failure: {\n fate: \"expired\" as const,\n cause: \"server\" as const,\n },\n }\n : protocolError(`unknown cmd type: ${String(cmd.type)}`);\n settleEntry(s, entry, outcome);\n};\n\nconst handleCmds = (s: Session, cmds: StatewireCmd[]) => {\n for (const cmd of cmds) handleCmd(s, cmd);\n wake(s);\n};\n\nconst ingestOps = (s: Session, ops: unknown[]) => {\n const applied = applyOps(s.canonical, ops);\n s.canonical = applied.state;\n s.changed.push(...applied.changedPaths);\n};\n\nconst publishIngested = (s: Session) => {\n publish(s);\n wake(s);\n};\n\nconst RECORDS = [\"fresh\", \"resumed\", \"ephemeral\"];\n\n// Snap a resumed session's lane clocks onto the record: seqs above the stated\n// watermark were never admitted, so a stale restored clock re-stamps its\n// never-admitted statements consecutively after the watermark.\nconst snapClocks = (s: Session, seqWm: number, ctxWm: number) => {\n const tail = s.pending.filter((p) => p.seq > seqWm);\n const cmdAligned =\n tail.every((p, i) => p.seq === seqWm + 1 + i) &&\n s.record.nextSeq === seqWm + tail.length + 1;\n if (!cmdAligned) {\n s.pending = s.pending.filter((p) => p.seq <= seqWm);\n setRecord(s, { ...s.record, nextSeq: seqWm + 1 });\n for (const old of tail) {\n s.lifecycle?.onCovered?.(old.inv);\n enqueue(s, old.command, old.inv.params, old.resolve, old.reject);\n }\n }\n const ctxAligned =\n s.ctxPending.every((c, i) => c.seq === ctxWm + 1 + i) &&\n s.record.ctxNextSeq === ctxWm + s.ctxPending.length + 1;\n if (!ctxAligned) {\n setRecord(s, { ...s.record, ctxNextSeq: ctxWm + 1 });\n restateContext(s);\n }\n};\n\nconst handleHello = (\n s: Session,\n { ops, syn }: { ops: unknown[]; syn: StatewireSyn },\n) => {\n const record = syn.record ?? \"fresh\";\n if (!RECORDS.includes(record)) {\n protocolError(`unknown record: ${String(record)}`);\n }\n ingestOps(s, ops);\n s.attach = \"attached\";\n s.attachEpoch += 1;\n s.frameFailures = 0;\n s.resumeAt = 0;\n s.ephemeral = record === \"ephemeral\";\n const [attachCmd, attachCtx] = s.attachLaneSeqs;\n s.attachLaneSeqs = [new Set(), new Set()];\n if (record === \"resumed\") {\n // Resending unsettled statements is exactly-once-safe: absorbed replays\n // re-emit their stored verdicts (applied while still in flight).\n for (const entry of s.pending) {\n entry.posted = attachCmd.has(entry.seq);\n }\n const ctxWatermark = syn.ctxSeq ?? 0;\n s.ctxPending = s.ctxPending.filter((c) => c.seq > ctxWatermark);\n for (const c of s.ctxPending) c.posted = attachCtx.has(c.seq);\n snapClocks(s, syn.seq ?? 0, ctxWatermark);\n } else {\n resetRecord(s, s.record.clientId);\n }\n s.sessionKnown = true;\n publishIngested(s);\n void pump(s);\n};\n\nconst handleOps = (\n s: Session,\n { ops, cmds }: { ops: unknown[]; cmds: StatewireCmd[] },\n) => {\n ingestOps(s, ops);\n for (const cmd of cmds) handleCmd(s, cmd);\n publishIngested(s);\n};\n\n// A {syn} refusal never settles: reconcile the resend queues against the\n// stated watermarks; retry present means wait, absent means resend now.\nconst handleRefusal = (s: Session, syn: StatewireSyn) => {\n const { seq, ctxSeq } = syn;\n if (typeof seq === \"number\") {\n const watermark = Math.max(seq, s.durableSeq);\n for (const entry of s.pending) entry.posted = entry.seq <= watermark;\n }\n if (typeof ctxSeq === \"number\") {\n s.ctxPending = s.ctxPending.filter((c) => c.seq > ctxSeq);\n for (const c of s.ctxPending) c.posted = false;\n }\n if (typeof syn.retry === \"number\") {\n s.resumeAt = Date.now() + syn.retry;\n }\n const firstCmd = s.pending.find((p) => !p.posted);\n const firstCtx = s.ctxPending.find((c) => !c.posted);\n const clocksAhead =\n (typeof syn.seq === \"number\" &&\n firstCmd !== undefined &&\n firstCmd.seq > Math.max(syn.seq, s.durableSeq) + 1) ||\n (typeof syn.ctxSeq === \"number\" &&\n firstCtx !== undefined &&\n firstCtx.seq > syn.ctxSeq + 1);\n // Clocks ahead of a record that cannot admit them: reattach first and let\n // the hello's record arbitrate.\n if (clocksAhead) s.transport?.connection.reconnect();\n wake(s);\n void pump(s);\n};\n\nconst handleDetach = (s: Session) => {\n if (s.attach === \"attached\") s.attach = \"detached\";\n if (s.ephemeral) ephemeralDetach(s);\n wake(s);\n};\n\nconst handleFinish = (s: Session, { reason }: { reason: string }) => {\n if (reason === \"evicted\" || reason === \"error\") return;\n s.attach = \"finished\";\n settleAll(s, reason === \"superseded\" ? \"superseded\" : \"gone\");\n publish(s);\n wake(s);\n};\n\nconst isFinished = (s: Session) => s.attach === \"finished\";\n\ntype Lanes = {\n frame: StatewireFrame;\n cmdEntries: Pending[];\n ctxEntries: CtxPending[];\n};\n\n// A lane must be strictly consecutive within a frame: the first unposted run\n// per lane rides now, later runs ride follow-up frames.\nconst buildLanes = (s: Session): Lanes | null => {\n const ctxEntries: CtxPending[] = [];\n for (const entry of s.ctxPending) {\n if (entry.posted) continue;\n if (ctxEntries.length > 0 && entry.seq !== ctxEntries.at(-1)!.seq + 1)\n break;\n ctxEntries.push(entry);\n }\n const cmdEntries: Pending[] = [];\n for (const entry of s.pending) {\n if (entry.posted) continue;\n if (cmdEntries.length > 0 && entry.seq !== cmdEntries.at(-1)!.seq + 1)\n break;\n cmdEntries.push(entry);\n }\n if (ctxEntries.length === 0 && cmdEntries.length === 0) return null;\n return {\n frame: {\n ...(ctxEntries.length > 0 && {\n ctx: ctxEntries.map((c) => ({ ops: c.ops, seq: c.seq })),\n }),\n ...(cmdEntries.length > 0 && {\n cmd: cmdEntries.map((p) => ({ ...p.command, seq: p.seq })),\n }),\n },\n cmdEntries,\n ctxEntries,\n };\n};\n\nconst takeAttachLanes = (s: Session): StatewireFrame | null => {\n s.attachLaneSeqs = [new Set(), new Set()];\n const wanted = s.lanesOnAttach;\n s.lanesOnAttach = false;\n if (!wanted || !s.sessionKnown) return null;\n const lanes = buildLanes(s);\n if (!lanes) return null;\n s.attachLaneSeqs = [\n new Set(lanes.cmdEntries.map((p) => p.seq)),\n new Set(lanes.ctxEntries.map((c) => c.seq)),\n ];\n for (const entry of lanes.cmdEntries) entry.attempted = true;\n return lanes.frame;\n};\n\nconst pump = async (s: Session) => {\n if (s.pumping) return;\n s.pumping = true;\n try {\n while (s.running && !isFinished(s)) {\n const transport = s.transport;\n if (buildLanes(s) === null) return;\n if (s.attach !== \"attached\" || !transport) {\n if (transport?.connection.status === \"idle\") {\n transport.connection.reconnect();\n }\n await waitForWake(s);\n continue;\n }\n const resumeDelay = s.resumeAt - Date.now();\n if (resumeDelay > 0) {\n await sleepUntilWake(s, resumeDelay);\n continue;\n }\n const lanes = buildLanes(s);\n if (!lanes) continue;\n const epoch = s.attachEpoch;\n for (const entry of lanes.cmdEntries) entry.attempted = true;\n let result;\n try {\n result = await transport.send(lanes.frame);\n } catch {\n if (!s.running || isFinished(s)) return;\n s.frameFailures += 1;\n await sleepUntilWake(s, backoff(s.frameFailures));\n continue;\n }\n if (!s.running) return;\n s.frameFailures = 0;\n if (result.type === \"ok\") {\n if (epoch === s.attachEpoch) {\n for (const entry of lanes.cmdEntries) {\n if (s.pending.includes(entry)) {\n entry.posted = true;\n s.lifecycle?.onPosted?.(entry.inv);\n }\n }\n for (const entry of lanes.ctxEntries) entry.posted = true;\n }\n } else if (result.type === \"refusal\") {\n if (epoch === s.attachEpoch) handleRefusal(s, result.syn);\n } else if (result.type === \"stale-lease\") {\n // A POST outlived its attach: reattach first, the hello arbitrates.\n if (epoch === s.attachEpoch) {\n transport.connection.reconnect();\n await waitForWake(s);\n }\n } else if (result.type === \"no-lease\") {\n // No out-of-band write channel: the frame rides a fresh attach.\n if (epoch === s.attachEpoch) {\n s.lanesOnAttach = true;\n transport.connection.reconnect();\n while (s.running && !isFinished(s) && epoch === s.attachEpoch) {\n await waitForWake(s);\n }\n }\n }\n }\n } finally {\n s.pumping = false;\n }\n};\n\nconst start = (s: Session) => {\n if (!s.recordPersisted) {\n s.recordPersisted = true;\n s.store.save(s.record);\n }\n s.running = true;\n void pump(s);\n};\n\nconst stop = (s: Session) => {\n s.running = false;\n wake(s);\n settleAll(s, \"unmount\");\n};\n\nconst setTransport = (s: Session, transport: RemoteLink) => {\n if (s.transport === transport) return;\n s.transport = transport;\n wake(s);\n};\n\nconst enqueue = (\n s: Session,\n command: WireCommand,\n params: readonly unknown[],\n resolve: (payload: unknown) => void,\n reject: (error: StatewireSendError) => void,\n) => {\n const seq = s.record.nextSeq;\n setRecord(s, { ...s.record, nextSeq: seq + 1 });\n const entry: Pending = {\n seq,\n command,\n inv: {\n method: command.method,\n params,\n ts: Date.now(),\n seq,\n clientId: s.record.clientId,\n },\n attempted: false,\n posted: false,\n applied: false,\n resolve,\n reject,\n };\n s.pending.push(entry);\n s.lifecycle?.onStart(entry.inv);\n void pump(s);\n};\n\nconst sendCommand = (\n s: Session,\n method: string,\n params: readonly unknown[],\n): Promise<unknown> => {\n if (!s.running) {\n return rejectedSend({ fate: \"aborted\", cause: \"unmount\" });\n }\n if (isFinished(s)) {\n return rejectedSend({ fate: \"aborted\", cause: \"stream-gone\" });\n }\n const result = new Promise<unknown>((resolve, reject) => {\n const { params: encoded, meta } = encodeParams(params);\n enqueue(\n s,\n { method, params: encoded, ...(meta !== undefined && { meta }) },\n params,\n resolve,\n reject,\n );\n });\n result.catch(() => {});\n return result;\n};\n\nconst setContext = (s: Session, value: Record<string, unknown>): void => {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n throw new Error(\"statewire: context must be a plain object\");\n }\n const { value: encoded, meta } = encodeValue(value);\n s.ctxOps = [\n {\n op: \"replace\",\n path: [],\n value: encoded,\n ...(meta !== undefined && { meta }),\n },\n ];\n const seq = s.record.ctxNextSeq;\n setRecord(s, { ...s.record, ctxNextSeq: seq + 1 });\n s.ctxPending.push({ seq, ops: s.ctxOps, posted: false });\n wake(s);\n void pump(s);\n};\n\nexport const useStatewireSession = (\n options: StatewireSessionOptions,\n): Session => {\n const [defaultStore] = useState(createMemorySessionStore);\n const store = options.sessionStore ?? defaultStore;\n const [s] = useState((): Session => {\n const stored = store.load();\n const record = stored ?? {\n clientId: newClientId(),\n nextSeq: 1,\n ctxNextSeq: 1,\n };\n const session: Session = {\n record,\n ctx: {\n get clientId() {\n return session.record.clientId;\n },\n takeAttachLanes: () => takeAttachLanes(session),\n onHello: (args) => handleHello(session, args),\n onOps: (args) => handleOps(session, args),\n onCmds: (cmds) => handleCmds(session, cmds),\n onRefusal: (syn) => handleRefusal(session, syn),\n onIdle: (level) => setIdle(session, level),\n onDetach: () => handleDetach(session),\n onFinish: (args) => handleFinish(session, args),\n },\n recordPersisted: stored !== null,\n store,\n ephemeral: false,\n sessionKnown: false,\n durableSeq: 0,\n resumeAt: 0,\n idle: false,\n onDone: undefined,\n ctxOps: undefined,\n ctxPending: [],\n lanesOnAttach: false,\n attachLaneSeqs: [new Set(), new Set()],\n frameFailures: 0,\n pending: [],\n canonical: undefined,\n lastPublished: undefined,\n changed: [],\n source: {\n snapshot: () => session.canonical,\n takeChanged: () => {\n const changed = session.changed;\n session.changed = [];\n return changed;\n },\n setOnChange: (listener) => {\n session.notify = listener ?? (() => {});\n },\n },\n attach: \"detached\",\n attachEpoch: 0,\n running: false,\n pumping: false,\n transport: null,\n waiters: [],\n lifecycle: null,\n notify: () => {},\n commands: createMethodProxy((method, params) =>\n sendCommand(session, method, params),\n ),\n };\n bindCommandsHost(session.commands, {\n setListener: (listener) => {\n session.lifecycle = listener;\n },\n });\n return session;\n });\n s.store = store;\n s.onDone = options.onDone;\n useEffect(() => {\n start(s);\n return () => stop(s);\n }, [s]);\n return s;\n};\n\nexport { setContext, setTransport };\n"],"mappings":"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"}
|
package/dist/client/timing.d.ts
CHANGED