experimental-a2 0.17.0 → 0.18.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +32 -0
- package/README.md +1 -1
- package/dist/{actor-DBbe5xeE.d.ts → actor-C7b-1arn.d.ts} +5 -5
- package/dist/{actor-DBbe5xeE.d.ts.map → actor-C7b-1arn.d.ts.map} +1 -1
- package/dist/actor-client.d.ts +1 -1
- package/dist/actor-react.d.ts +3 -3
- package/dist/actor-react.js +1 -1
- package/dist/actor.d.ts +1 -1
- package/dist/actor.js +2 -2
- package/dist/{ai-vpGtcaCB.d.ts → ai-BMLlI2Ff.d.ts} +3 -3
- package/dist/{ai-vpGtcaCB.d.ts.map → ai-BMLlI2Ff.d.ts.map} +1 -1
- package/dist/{ai-UrWfKeuv.js → ai-D6mGlO8j.js} +2 -2
- package/dist/{ai-UrWfKeuv.js.map → ai-D6mGlO8j.js.map} +1 -1
- package/dist/ai-client.d.ts +2 -2
- package/dist/ai-client.js +2 -2
- package/dist/ai-fx.browser.d.ts +1 -0
- package/dist/ai-fx.browser.js +6 -0
- package/dist/ai-fx.browser.js.map +1 -0
- package/dist/ai-fx.d.ts +10 -0
- package/dist/ai-fx.d.ts.map +1 -0
- package/dist/ai-fx.js +692 -0
- package/dist/ai-fx.js.map +1 -0
- package/dist/ai-harness-B2suP2Qh.d.ts +26 -0
- package/dist/ai-harness-B2suP2Qh.d.ts.map +1 -0
- package/dist/ai-harness-BuLh_EYi.js +273 -0
- package/dist/ai-harness-BuLh_EYi.js.map +1 -0
- package/dist/ai-pi.browser.d.ts +1 -0
- package/dist/ai-pi.browser.js +6 -0
- package/dist/ai-pi.browser.js.map +1 -0
- package/dist/ai-pi.d.ts +17 -0
- package/dist/ai-pi.d.ts.map +1 -0
- package/dist/ai-pi.js +950 -0
- package/dist/ai-pi.js.map +1 -0
- package/dist/ai-react.d.ts +5 -5
- package/dist/ai-react.js +2 -2
- package/dist/ai-server.d.ts +47 -25
- package/dist/ai-server.d.ts.map +1 -1
- package/dist/ai-server.js +113 -40
- package/dist/ai-server.js.map +1 -1
- package/dist/ai-tool-input-DmSqMUQi.js +40 -0
- package/dist/ai-tool-input-DmSqMUQi.js.map +1 -0
- package/dist/ai.d.ts +1 -1
- package/dist/ai.js +1 -1
- package/dist/bounded-cache-CPHWF-8h.js +41 -0
- package/dist/bounded-cache-CPHWF-8h.js.map +1 -0
- package/dist/{client-COaiaDub.js → client-BhHLoNKF.js} +3 -3
- package/dist/{client-COaiaDub.js.map → client-BhHLoNKF.js.map} +1 -1
- package/dist/{client-qRnRUzBS.d.ts → client-h_DKFAjj.d.ts} +3 -3
- package/dist/{client-qRnRUzBS.d.ts.map → client-h_DKFAjj.d.ts.map} +1 -1
- package/dist/client.d.ts +3 -3
- package/dist/client.js +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/{initial-snapshot-BrLso5x_.d.ts → initial-snapshot-Bx-c0pDP.d.ts} +2 -2
- package/dist/{initial-snapshot-BrLso5x_.d.ts.map → initial-snapshot-Bx-c0pDP.d.ts.map} +1 -1
- package/dist/{internal-CbVvEwad.js → internal-CscSY7K_.js} +11 -3
- package/dist/internal-CscSY7K_.js.map +1 -0
- package/dist/otel.d.ts +1 -1
- package/dist/{react-BbJ-g6Uu.d.ts → react-BBXgHWFc.d.ts} +4 -4
- package/dist/{react-BbJ-g6Uu.d.ts.map → react-BBXgHWFc.d.ts.map} +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/react.js +1 -1
- package/dist/reducer-BAXc8JyF.js.map +1 -1
- package/dist/{reducer-BYu6DT7h.d.ts → reducer-CqA59Q6U.d.ts} +2 -2
- package/dist/{reducer-BYu6DT7h.d.ts.map → reducer-CqA59Q6U.d.ts.map} +1 -1
- package/dist/scheduler-qstash.d.ts +2 -2
- package/dist/scheduler-qstash.js +3 -3
- package/dist/scheduler-qstash.js.map +1 -1
- package/dist/scheduler-vercel.d.ts +7 -7
- package/dist/scheduler-vercel.d.ts.map +1 -1
- package/dist/scheduler-vercel.js +9 -10
- package/dist/scheduler-vercel.js.map +1 -1
- package/dist/{server-Rj64fNvX.js → server-D-Y4pqwu.js} +126 -67
- package/dist/server-D-Y4pqwu.js.map +1 -0
- package/dist/{server-CGM8WzRG.d.ts → server-DYAATFuT.d.ts} +42 -7
- package/dist/server-DYAATFuT.d.ts.map +1 -0
- package/dist/server.d.ts +4 -4
- package/dist/server.js +1 -1
- package/dist/{session-clear-Dshpuhff.d.ts → session-clear-C-QwTXV1.d.ts} +2 -2
- package/dist/session-clear-C-QwTXV1.d.ts.map +1 -0
- package/dist/{store-Gpkq7WBo.d.ts → store-CyLUy86v.d.ts} +53 -5
- package/dist/store-CyLUy86v.d.ts.map +1 -0
- package/dist/store-N8PXxDAS.js.map +1 -1
- package/dist/store-memory.d.ts +1 -1
- package/dist/store-memory.js +56 -11
- package/dist/store-memory.js.map +1 -1
- package/dist/{store-polling-4_y8lETm.js → store-polling-7WJV0YWP.js} +2 -2
- package/dist/{store-polling-4_y8lETm.js.map → store-polling-7WJV0YWP.js.map} +1 -1
- package/dist/store-postgres.d.ts +1 -1
- package/dist/store-postgres.d.ts.map +1 -1
- package/dist/store-postgres.js +106 -25
- package/dist/store-postgres.js.map +1 -1
- package/dist/{store-presence-polling-Q1C-k2dd.js → store-presence-polling-B1ixeqIS.js} +3 -3
- package/dist/{store-presence-polling-Q1C-k2dd.js.map → store-presence-polling-B1ixeqIS.js.map} +1 -1
- package/dist/store-redis-http.d.ts +1 -1
- package/dist/store-redis-http.js +3 -3
- package/dist/{store-redis-notify-tqWNnMRu.js → store-redis-notify-CM0AfLY0.js} +271 -101
- package/dist/store-redis-notify-CM0AfLY0.js.map +1 -0
- package/dist/store-redis.d.ts +1 -1
- package/dist/store-redis.js +1 -1
- package/dist/store-sqlite.d.ts +1 -1
- package/dist/store-sqlite.js +66 -21
- package/dist/store-sqlite.js.map +1 -1
- package/dist/{telemetry-cZH-cibj.d.ts → telemetry-Cyfqo6Qt.d.ts} +2 -2
- package/dist/telemetry-Cyfqo6Qt.d.ts.map +1 -0
- package/dist/{wire-DjfHOvdW.js → wire-BKxH1vbP.js} +2 -2
- package/dist/{wire-DjfHOvdW.js.map → wire-BKxH1vbP.js.map} +1 -1
- package/docs/01-quickstart.mdx +49 -83
- package/docs/{guides/07-examples.mdx → 02-examples.mdx} +10 -20
- package/docs/actors/01-introduction.mdx +48 -86
- package/docs/actors/02-concurrency.mdx +43 -70
- package/docs/actors/03-timers.mdx +28 -42
- package/docs/actors/04-routes.mdx +110 -150
- package/docs/actors/meta.ts +1 -1
- package/docs/agents/01-introduction.mdx +257 -0
- package/docs/agents/02-tools.mdx +247 -0
- package/docs/agents/03-conversations.mdx +538 -0
- package/docs/agents/04-harnesses.mdx +136 -0
- package/docs/agents/meta.ts +1 -0
- package/docs/client/01-react.mdx +294 -0
- package/docs/client/02-transports.mdx +86 -0
- package/docs/client/03-presence.mdx +224 -0
- package/docs/client/meta.ts +1 -0
- package/docs/contract/01-events.mdx +57 -0
- package/docs/contract/02-state.mdx +142 -0
- package/docs/contract/03-sessions.mdx +175 -0
- package/docs/index.mdx +109 -145
- package/docs/reference/01-core.mdx +139 -0
- package/docs/reference/02-server.mdx +860 -0
- package/docs/reference/03-client.mdx +301 -0
- package/docs/reference/04-ai.mdx +731 -0
- package/docs/reference/05-adapters.mdx +351 -0
- package/docs/reference/06-errors.mdx +138 -0
- package/docs/reference/meta.ts +1 -1
- package/docs/server/01-handlers.mdx +200 -0
- package/docs/server/02-timers.mdx +130 -0
- package/docs/server/03-cancellation.mdx +142 -0
- package/docs/server/04-routes.mdx +243 -0
- package/docs/server/05-production.mdx +323 -0
- package/docs/server/06-guarantees.mdx +132 -0
- package/examples/playground/DEPLOY.md +3 -5
- package/examples/playground/app/a0/[appId]/page.tsx +12 -13
- package/examples/playground/app/a0/app-list.tsx +9 -2
- package/examples/playground/app/a0/app-view.tsx +9 -1
- package/examples/playground/app/a0/apps/[appId]/route.ts +10 -5
- package/examples/playground/app/a0/apps.test.ts +12 -0
- package/examples/playground/app/a0/apps.ts +22 -7
- package/examples/playground/app/a0/chat.tsx +47 -1
- package/examples/playground/app/a0/devtools.tsx +2 -8
- package/examples/playground/app/a0/fx/events/route.ts +9 -0
- package/examples/playground/app/a0/fx/scheduler/route.ts +7 -0
- package/examples/playground/app/a0/fx/short/events/route.ts +11 -0
- package/examples/playground/app/a0/model.test.ts +18 -1
- package/examples/playground/app/a0/model.ts +47 -10
- package/examples/playground/app/a0/no-photon.cjs +4 -0
- package/examples/playground/app/a0/no-quickjs.cjs +3 -0
- package/examples/playground/app/a0/pi/events/route.ts +9 -0
- package/examples/playground/app/a0/pi/scheduler/route.ts +7 -0
- package/examples/playground/app/a0/pi/short/events/route.ts +11 -0
- package/examples/playground/app/a0/sandbox-log.ts +10 -4
- package/examples/playground/app/a0/sandbox-session.ts +152 -0
- package/examples/playground/app/a0/scheduler/route.ts +2 -2
- package/examples/playground/app/a0/server.ts +98 -54
- package/examples/playground/app/a0/session.ts +17 -5
- package/examples/playground/app/a0/shell.tsx +11 -3
- package/examples/playground/app/agent/ingress.test.ts +6 -3
- package/examples/playground/app/agent/server.ts +9 -6
- package/examples/playground/app/agent/telemetry.test.ts +71 -50
- package/examples/playground/app/canvas/[canvasId]/canvas-client.tsx +1 -1
- package/examples/playground/app/chat/server.test.ts +30 -26
- package/examples/playground/app/chat/server.ts +46 -46
- package/examples/playground/next.config.ts +17 -5
- package/examples/playground/package.json +4 -1
- package/examples/playground/vercel.json +18 -0
- package/package.json +27 -3
- package/src/ai-agent.ts +271 -90
- package/src/ai-fx.browser.ts +5 -0
- package/src/ai-fx.ts +912 -0
- package/src/ai-harness.ts +518 -0
- package/src/ai-model-metadata.ts +11 -6
- package/src/ai-pi.browser.ts +5 -0
- package/src/ai-pi.ts +1322 -0
- package/src/ai-sdk-step.ts +2 -2
- package/src/ai-server.ts +3 -1
- package/src/ai-tool-input.ts +45 -0
- package/src/internal.ts +13 -0
- package/src/libfx.d.ts +34 -0
- package/src/reducer.ts +1 -1
- package/src/scheduler-qstash.ts +5 -5
- package/src/scheduler-vercel.ts +14 -15
- package/src/server.ts +233 -29
- package/src/store-memory.ts +92 -16
- package/src/store-postgres.ts +156 -25
- package/src/store-redis-core.ts +322 -110
- package/src/store-redis-notify.ts +2 -0
- package/src/store-sqlite.ts +121 -28
- package/src/store.ts +55 -3
- package/src/telemetry.ts +1 -0
- package/dist/internal-CbVvEwad.js.map +0 -1
- package/dist/server-CGM8WzRG.d.ts.map +0 -1
- package/dist/server-Rj64fNvX.js.map +0 -1
- package/dist/session-clear-Dshpuhff.d.ts.map +0 -1
- package/dist/store-Gpkq7WBo.d.ts.map +0 -1
- package/dist/store-redis-notify-tqWNnMRu.js.map +0 -1
- package/dist/telemetry-cZH-cibj.d.ts.map +0 -1
- package/docs/concepts/01-contracts.mdx +0 -237
- package/docs/concepts/02-handlers.mdx +0 -284
- package/docs/concepts/03-durability.mdx +0 -314
- package/docs/concepts/04-state.mdx +0 -209
- package/docs/guides/01-timers.mdx +0 -193
- package/docs/guides/02-cancellation.mdx +0 -161
- package/docs/guides/03-react.mdx +0 -324
- package/docs/guides/04-local-first.mdx +0 -47
- package/docs/guides/05-production.mdx +0 -534
- package/docs/guides/06-ai-agents.mdx +0 -1408
- package/docs/guides/08-application-data.mdx +0 -113
- package/docs/guides/09-presence.mdx +0 -262
- package/docs/guides/10-transports.mdx +0 -221
- package/docs/reference/01-api.mdx +0 -2358
- package/docs/reference/02-errors.mdx +0 -150
- /package/docs/{concepts → contract}/meta.ts +0 -0
- /package/docs/{guides → server}/meta.ts +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { i as POLL_TIMINGS } from "./internal-
|
|
2
|
-
import { t as defaultSleep } from "./store-polling-
|
|
1
|
+
import { i as POLL_TIMINGS } from "./internal-CscSY7K_.js";
|
|
2
|
+
import { t as defaultSleep } from "./store-polling-7WJV0YWP.js";
|
|
3
3
|
//#region src/store-presence-polling.ts
|
|
4
4
|
const key = ({ participant, field }) => JSON.stringify([participant, field]);
|
|
5
5
|
function pollPresence({ read, deliver, sleep = defaultSleep }) {
|
|
@@ -91,4 +91,4 @@ function pollPresence({ read, deliver, sleep = defaultSleep }) {
|
|
|
91
91
|
//#endregion
|
|
92
92
|
export { pollPresence as t };
|
|
93
93
|
|
|
94
|
-
//# sourceMappingURL=store-presence-polling-
|
|
94
|
+
//# sourceMappingURL=store-presence-polling-B1ixeqIS.js.map
|
package/dist/{store-presence-polling-Q1C-k2dd.js.map → store-presence-polling-B1ixeqIS.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store-presence-polling-
|
|
1
|
+
{"version":3,"file":"store-presence-polling-B1ixeqIS.js","names":[],"sources":["../src/store-presence-polling.ts"],"sourcesContent":["import type { PresencePatch } from './contract.ts'\nimport { POLL_TIMINGS } from './internal.ts'\nimport { defaultSleep, type Sleeper } from './store-polling.ts'\nimport type { PresenceRow } from './store.ts'\n\nconst key = ({\n participant,\n field,\n}: Pick<PresenceRow, 'participant' | 'field'>): string =>\n JSON.stringify([participant, field])\n\nexport function pollPresence({\n read,\n deliver,\n sleep = defaultSleep,\n}: {\n read: () => Promise<PresenceRow[]>\n deliver: (patch: PresencePatch) => void\n sleep?: (ms: number) => Sleeper\n}): {\n ready: Promise<void>\n update(patch: PresencePatch): void\n wake(): void\n stop(): void\n} {\n let stopped = false\n let pending: Sleeper | undefined\n let interval = Math.min(\n POLL_TIMINGS.activeFloorMs,\n POLL_TIMINGS.idleCeilingMs,\n )\n let version = 0\n const seen = new Map<string, Omit<PresenceRow, 'expiresAt'>>()\n const activate = (): void => {\n version += 1\n interval = Math.min(POLL_TIMINGS.activeFloorMs, POLL_TIMINGS.idleCeilingMs)\n pending?.cancel()\n }\n const ready = read()\n .then((rows) => {\n if (stopped) return\n for (const row of rows) seen.set(key(row), row)\n return undefined\n })\n // Seeding is best effort; foreground snapshots still report read errors.\n .catch(() => undefined)\n\n const run = async (): Promise<void> => {\n await ready\n for (;;) {\n if (stopped) return\n const before = version\n pending = sleep(interval)\n // oxlint-disable-next-line no-await-in-loop -- adaptive presence polling\n await pending.promise\n if (stopped) return\n try {\n const reading = version\n // oxlint-disable-next-line no-await-in-loop -- read each new presence snapshot\n const rows = await read()\n if (stopped) return\n if (version !== reading) continue\n const live = new Set<string>()\n let changed = false\n for (const row of rows) {\n const id = key(row)\n live.add(id)\n const prior = seen.get(id)\n seen.set(id, row)\n if (\n prior?.seen === row.seen &&\n prior.at.getTime() === row.at.getTime() &&\n JSON.stringify(prior.value) === JSON.stringify(row.value)\n )\n continue\n changed = true\n deliver({\n participant: row.participant,\n values: { [row.field]: row.value },\n seen: row.seen,\n at: row.at,\n })\n }\n for (const [id, row] of seen) {\n if (live.has(id)) continue\n seen.delete(id)\n changed = true\n deliver({\n participant: row.participant,\n values: { [row.field]: null },\n seen: row.seen,\n at: new Date(),\n })\n }\n if (changed) activate()\n else if (version === before)\n interval = Math.min(interval * 2, POLL_TIMINGS.idleCeilingMs)\n } catch {\n interval = POLL_TIMINGS.idleCeilingMs\n }\n }\n }\n void run()\n return {\n ready,\n wake: activate,\n update(patch) {\n for (const [field, value] of Object.entries(patch.values)) {\n seen.set(key({ participant: patch.participant, field }), {\n participant: patch.participant,\n field,\n value,\n seen: patch.seen,\n at: patch.at,\n })\n }\n activate()\n },\n stop() {\n stopped = true\n pending?.cancel()\n seen.clear()\n },\n }\n}\n"],"mappings":";;;AAKA,MAAM,OAAO,EACX,aACA,YAEA,KAAK,UAAU,CAAC,aAAa,KAAK,CAAC;AAErC,SAAgB,aAAa,EAC3B,MACA,SACA,QAAQ,gBAUR;CACA,IAAI,UAAU;CACd,IAAI;CACJ,IAAI,WAAW,KAAK,IAClB,aAAa,eACb,aAAa,aACf;CACA,IAAI,UAAU;CACd,MAAM,uBAAO,IAAI,IAA4C;CAC7D,MAAM,iBAAuB;EAC3B,WAAW;EACX,WAAW,KAAK,IAAI,aAAa,eAAe,aAAa,aAAa;EAC1E,SAAS,OAAO;CAClB;CACA,MAAM,QAAQ,KAAK,CAAC,CACjB,MAAM,SAAS;EACd,IAAI,SAAS;EACb,KAAK,MAAM,OAAO,MAAM,KAAK,IAAI,IAAI,GAAG,GAAG,GAAG;CAEhD,CAAC,CAAC,CAED,YAAY,KAAA,CAAS;CAExB,MAAM,MAAM,YAA2B;EACrC,MAAM;EACN,SAAS;GACP,IAAI,SAAS;GACb,MAAM,SAAS;GACf,UAAU,MAAM,QAAQ;GAExB,MAAM,QAAQ;GACd,IAAI,SAAS;GACb,IAAI;IACF,MAAM,UAAU;IAEhB,MAAM,OAAO,MAAM,KAAK;IACxB,IAAI,SAAS;IACb,IAAI,YAAY,SAAS;IACzB,MAAM,uBAAO,IAAI,IAAY;IAC7B,IAAI,UAAU;IACd,KAAK,MAAM,OAAO,MAAM;KACtB,MAAM,KAAK,IAAI,GAAG;KAClB,KAAK,IAAI,EAAE;KACX,MAAM,QAAQ,KAAK,IAAI,EAAE;KACzB,KAAK,IAAI,IAAI,GAAG;KAChB,IACE,OAAO,SAAS,IAAI,QACpB,MAAM,GAAG,QAAQ,MAAM,IAAI,GAAG,QAAQ,KACtC,KAAK,UAAU,MAAM,KAAK,MAAM,KAAK,UAAU,IAAI,KAAK,GAExD;KACF,UAAU;KACV,QAAQ;MACN,aAAa,IAAI;MACjB,QAAQ,GAAG,IAAI,QAAQ,IAAI,MAAM;MACjC,MAAM,IAAI;MACV,IAAI,IAAI;KACV,CAAC;IACH;IACA,KAAK,MAAM,CAAC,IAAI,QAAQ,MAAM;KAC5B,IAAI,KAAK,IAAI,EAAE,GAAG;KAClB,KAAK,OAAO,EAAE;KACd,UAAU;KACV,QAAQ;MACN,aAAa,IAAI;MACjB,QAAQ,GAAG,IAAI,QAAQ,KAAK;MAC5B,MAAM,IAAI;MACV,oBAAI,IAAI,KAAK;KACf,CAAC;IACH;IACA,IAAI,SAAS,SAAS;SACjB,IAAI,YAAY,QACnB,WAAW,KAAK,IAAI,WAAW,GAAG,aAAa,aAAa;GAChE,QAAQ;IACN,WAAW,aAAa;GAC1B;EACF;CACF;CACA,IAAS;CACT,OAAO;EACL;EACA,MAAM;EACN,OAAO,OAAO;GACZ,KAAK,MAAM,CAAC,OAAO,UAAU,OAAO,QAAQ,MAAM,MAAM,GACtD,KAAK,IAAI,IAAI;IAAE,aAAa,MAAM;IAAa;GAAM,CAAC,GAAG;IACvD,aAAa,MAAM;IACnB;IACA;IACA,MAAM,MAAM;IACZ,IAAI,MAAM;GACZ,CAAC;GAEH,SAAS;EACX;EACA,OAAO;GACL,UAAU;GACV,SAAS,OAAO;GAChB,KAAK,MAAM;EACb;CACF;AACF"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { r as Clock, s as IdSource, t as A2Store } from "./store-
|
|
1
|
+
import { r as Clock, s as IdSource, t as A2Store } from "./store-CyLUy86v.js";
|
|
2
2
|
//#region src/store-redis-http.d.ts
|
|
3
3
|
type RedisHttpStoreOptions = {
|
|
4
4
|
/** REST endpoint, e.g. `process.env.UPSTASH_REDIS_REST_URL`. */
|
package/dist/store-redis-http.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { i as A2Error } from "./session-clear-DGI4jTQ5.js";
|
|
2
|
-
import { r as NOTIFY_TIMINGS } from "./internal-
|
|
3
|
-
import { t as defaultSleep } from "./store-polling-
|
|
2
|
+
import { r as NOTIFY_TIMINGS } from "./internal-CscSY7K_.js";
|
|
3
|
+
import { t as defaultSleep } from "./store-polling-7WJV0YWP.js";
|
|
4
4
|
import { n as SYSTEM_CLOCK, t as RANDOM_IDS } from "./store-N8PXxDAS.js";
|
|
5
|
-
import { t as createRedisNotifyStore } from "./store-redis-notify-
|
|
5
|
+
import { t as createRedisNotifyStore } from "./store-redis-notify-CM0AfLY0.js";
|
|
6
6
|
//#region src/redis-http-subscriptions.ts
|
|
7
7
|
function redisHttpSubscriptions({ url, token, onReconnect, fallback }) {
|
|
8
8
|
const subscriptions = /* @__PURE__ */ new Map();
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { i as A2Error, r as sessionClearedError, s as supersededAttemptError, t as CLEAR_EVENT_TYPE } from "./session-clear-DGI4jTQ5.js";
|
|
2
|
-
import {
|
|
3
|
-
import { i as streamActivities, n as pollingStream, r as createStreamActivity, t as defaultSleep } from "./store-polling-
|
|
2
|
+
import { _ as nullProtoRecord, r as NOTIFY_TIMINGS, y as stateTailReaders } from "./internal-CscSY7K_.js";
|
|
3
|
+
import { i as streamActivities, n as pollingStream, r as createStreamActivity, t as defaultSleep } from "./store-polling-7WJV0YWP.js";
|
|
4
4
|
import { n as isSerializedEvent, r as parseSerializedEvent, t as bufferedEvents } from "./stream-buffer-Cx7AAPGq.js";
|
|
5
5
|
import { t as idempotentReplay } from "./idempotent-replay-JdgMQRRm.js";
|
|
6
6
|
import { t as decodeReturnedEventIds } from "./store-codec-DTG0Ftek.js";
|
|
7
|
-
import { t as pollPresence } from "./store-presence-polling-
|
|
7
|
+
import { t as pollPresence } from "./store-presence-polling-B1ixeqIS.js";
|
|
8
8
|
//#region src/presence-recovery.ts
|
|
9
9
|
const key = ({ participant, field }) => JSON.stringify([participant, field]);
|
|
10
10
|
function presenceRecovery({ read, deliver, isActive }) {
|
|
@@ -102,6 +102,22 @@ function presenceRecovery({ read, deliver, isActive }) {
|
|
|
102
102
|
const FEED_PAGE_SIZE = 1e3;
|
|
103
103
|
const READ_CONCURRENCY = 16;
|
|
104
104
|
const META_CHUNK_SIZE = 1e3;
|
|
105
|
+
/** The metadata columns of a full stored row. */
|
|
106
|
+
const STORED_EVENT_META_SUFFIXES = [
|
|
107
|
+
"p",
|
|
108
|
+
"pa",
|
|
109
|
+
"ri",
|
|
110
|
+
"ch",
|
|
111
|
+
"ce",
|
|
112
|
+
"f",
|
|
113
|
+
"fc",
|
|
114
|
+
"lc",
|
|
115
|
+
"lf",
|
|
116
|
+
"lfa",
|
|
117
|
+
"d",
|
|
118
|
+
"a",
|
|
119
|
+
"e"
|
|
120
|
+
];
|
|
105
121
|
/**
|
|
106
122
|
* Upstash bills every call a script makes, so scripts read the counter and
|
|
107
123
|
* split with one MGET, read metadata with one HMGET per hash (`read_fields`),
|
|
@@ -256,6 +272,32 @@ local function flush_queue()
|
|
|
256
272
|
end
|
|
257
273
|
`;
|
|
258
274
|
/**
|
|
275
|
+
* Settles one unfinished event for scripts that include ENQUEUE_LUA: it
|
|
276
|
+
* leaves the pending and ready sets, and a lane head hands its lane to the
|
|
277
|
+
* next unfinished event. A dead-lettered successor stays out of the ready set.
|
|
278
|
+
*/
|
|
279
|
+
const SETTLE_LUA = `
|
|
280
|
+
local function settle(field, lane, next_field)
|
|
281
|
+
redis.call('ZREM', PENDING, field)
|
|
282
|
+
redis.call('ZREM', READY, field)
|
|
283
|
+
if lane == '' then return end
|
|
284
|
+
local head_key = lane_field(lane, 'head')
|
|
285
|
+
if redis.call('HGET', META, head_key) ~= field then return end
|
|
286
|
+
while next_field do
|
|
287
|
+
local row = read_fields({ next_field }, { 'p', 'f', 'next' })[next_field]
|
|
288
|
+
if not row[1] then
|
|
289
|
+
redis.call('HSET', META, head_key, next_field)
|
|
290
|
+
if not row[2] then
|
|
291
|
+
redis.call('ZADD', READY, tonumber(next_field), next_field)
|
|
292
|
+
end
|
|
293
|
+
return
|
|
294
|
+
end
|
|
295
|
+
next_field = row[3]
|
|
296
|
+
end
|
|
297
|
+
clear_lane(lane)
|
|
298
|
+
end
|
|
299
|
+
`;
|
|
300
|
+
/**
|
|
259
301
|
* Event-id ownership for scripts that add events. Each script reads the
|
|
260
302
|
* counter, split, clear boundary, and per-id keys with one MGET and applies
|
|
261
303
|
* the first three. Returns the owner record, or false, per event, and the
|
|
@@ -422,7 +464,7 @@ return { 'ok', tostring(base + 1), pending_after }
|
|
|
422
464
|
/**
|
|
423
465
|
* KEYS: counter, meta, pending, ready, event snapshot pins, snapshot pin counts,
|
|
424
466
|
* metadata split.
|
|
425
|
-
* ARGV: idx, attempt, error, maxFailures, nowMs.
|
|
467
|
+
* ARGV: idx, attempt, error, maxFailures, nowMs, retryAtMs ('' for none).
|
|
426
468
|
*/
|
|
427
469
|
const FAIL_ATTEMPT_LUA = `
|
|
428
470
|
local COUNTER, META, SPLIT = KEYS[1], KEYS[2], KEYS[7]
|
|
@@ -454,8 +496,14 @@ put(meta_key, field .. ':e', ARGV[3])
|
|
|
454
496
|
put(meta_key, field .. ':lf', ARGV[5])
|
|
455
497
|
put(meta_key, field .. ':lfa', ARGV[2])
|
|
456
498
|
if dead then put(meta_key, field .. ':f', ARGV[5]) end
|
|
499
|
+
local hold = not dead and ARGV[6] ~= ''
|
|
500
|
+
if hold then put(meta_key, field .. ':ce', ARGV[6]) end
|
|
457
501
|
flush()
|
|
458
|
-
|
|
502
|
+
if hold then
|
|
503
|
+
redis.call('HDEL', meta_key, field .. ':ch')
|
|
504
|
+
else
|
|
505
|
+
redis.call('HDEL', meta_key, field .. ':ch', field .. ':ce')
|
|
506
|
+
end
|
|
459
507
|
if dead then
|
|
460
508
|
redis.call('ZREM', KEYS[4], field)
|
|
461
509
|
release_snapshot_pins(KEYS[5], KEYS[6])
|
|
@@ -464,23 +512,29 @@ end
|
|
|
464
512
|
return { 'failed', tostring(failures) }
|
|
465
513
|
`;
|
|
466
514
|
/**
|
|
467
|
-
* KEYS: store, counter, meta, pending, ready, metadata split
|
|
468
|
-
*
|
|
515
|
+
* KEYS: store, counter, meta, pending, ready, metadata split, snapshot pin
|
|
516
|
+
* counts.
|
|
517
|
+
* ARGV: holder, nowMs, expiresAtMs, excludedCount, excluded indexes, then
|
|
518
|
+
* maxFailures ('' for none) and the event snapshot-pins key prefix.
|
|
469
519
|
* The ready set is a subset of the pending set, so an empty ready set is
|
|
470
520
|
* enough to report 'settled'. A claimed result ends with the clear boundary.
|
|
471
521
|
*/
|
|
472
522
|
const CLAIM_AVAILABLE_LUA = `
|
|
473
523
|
local COUNTER, META, SPLIT = KEYS[2], KEYS[3], KEYS[6]
|
|
474
524
|
${META_LUA}
|
|
525
|
+
${RELEASE_PINS_LUA}
|
|
475
526
|
local ready = redis.call('ZRANGE', KEYS[5], 0, -1)
|
|
476
527
|
local excluded = {}
|
|
528
|
+
local tail = 5 + tonumber(ARGV[4])
|
|
477
529
|
for i = 1, tonumber(ARGV[4]) do excluded[ARGV[4 + i]] = true end
|
|
530
|
+
local max_failures = tonumber(ARGV[tail])
|
|
478
531
|
local candidates = {}
|
|
479
532
|
for _, field in ipairs(ready) do
|
|
480
533
|
if not excluded[field] then candidates[#candidates + 1] = field end
|
|
481
534
|
end
|
|
482
535
|
local rows = read_fields(candidates, { 'ce', 'd', 'fc', 'a', 'e', 'lf', 'lfa' })
|
|
483
536
|
local claimed = {}
|
|
537
|
+
local dead = {}
|
|
484
538
|
local retry_at = nil
|
|
485
539
|
for _, field in ipairs(candidates) do
|
|
486
540
|
local row = rows[field]
|
|
@@ -490,29 +544,63 @@ for _, field in ipairs(candidates) do
|
|
|
490
544
|
else
|
|
491
545
|
local entries = redis.call('XRANGE', KEYS[1], field .. '-0', field .. '-0')
|
|
492
546
|
if #entries == 0 then return { 'missing', field } end
|
|
493
|
-
local attempt = tostring(tonumber(row[2] or '0') + 1)
|
|
494
|
-
local first_claimed = row[3] or ARGV[2]
|
|
495
547
|
local meta_key = mkey(field)
|
|
548
|
+
local attempt = tostring(tonumber(row[2] or '0') + 1)
|
|
549
|
+
-- An expiry that is not the current attempt's retry hold is a lapsed
|
|
550
|
+
-- claim: its attempt never finished.
|
|
551
|
+
local lapsed = row[1] and row[7] ~= row[2]
|
|
552
|
+
local failures = tonumber(row[4] or '0')
|
|
553
|
+
if lapsed then
|
|
554
|
+
failures = failures + 1
|
|
555
|
+
put(meta_key, field .. ':a', tostring(failures))
|
|
556
|
+
end
|
|
496
557
|
put(meta_key, field .. ':d', attempt)
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
558
|
+
if lapsed and max_failures and failures >= max_failures then
|
|
559
|
+
-- That takeover spent the last failed attempt: dead-letter, unclaimed.
|
|
560
|
+
-- Advancing the attempt fences the lapsed one; nothing runs.
|
|
561
|
+
put(meta_key, field .. ':f', ARGV[2])
|
|
562
|
+
dead[#dead + 1] = field
|
|
563
|
+
claimed[#claimed + 1] = {
|
|
564
|
+
attempt,
|
|
565
|
+
tostring(failures),
|
|
566
|
+
row[5] or false,
|
|
567
|
+
row[3] or false,
|
|
568
|
+
read_fields({ field }, { 'lc' })[field][1] or false,
|
|
569
|
+
row[6] or false,
|
|
570
|
+
row[7] or false,
|
|
571
|
+
false,
|
|
572
|
+
false,
|
|
573
|
+
entries[1],
|
|
574
|
+
ARGV[2]
|
|
575
|
+
}
|
|
576
|
+
else
|
|
577
|
+
local first_claimed = row[3] or ARGV[2]
|
|
578
|
+
put(meta_key, field .. ':fc', first_claimed)
|
|
579
|
+
put(meta_key, field .. ':lc', ARGV[2])
|
|
580
|
+
put(meta_key, field .. ':ch', ARGV[1])
|
|
581
|
+
put(meta_key, field .. ':ce', ARGV[3])
|
|
582
|
+
claimed[#claimed + 1] = {
|
|
583
|
+
attempt,
|
|
584
|
+
tostring(failures),
|
|
585
|
+
row[5] or false,
|
|
586
|
+
first_claimed,
|
|
587
|
+
ARGV[2],
|
|
588
|
+
row[6] or false,
|
|
589
|
+
row[7] or false,
|
|
590
|
+
ARGV[1],
|
|
591
|
+
ARGV[3],
|
|
592
|
+
entries[1],
|
|
593
|
+
false
|
|
594
|
+
}
|
|
595
|
+
end
|
|
513
596
|
end
|
|
514
597
|
end
|
|
515
598
|
flush()
|
|
599
|
+
for _, field in ipairs(dead) do
|
|
600
|
+
redis.call('HDEL', mkey(field), field .. ':ch', field .. ':ce')
|
|
601
|
+
redis.call('ZREM', KEYS[5], field)
|
|
602
|
+
release_snapshot_pins(ARGV[tail + 1] .. field, KEYS[7])
|
|
603
|
+
end
|
|
516
604
|
if #claimed > 0 then
|
|
517
605
|
local result = { 'claimed', tostring(#claimed) }
|
|
518
606
|
for _, claim in ipairs(claimed) do
|
|
@@ -580,25 +668,7 @@ ${ENQUEUE_LUA}
|
|
|
580
668
|
${ID_OWNERS_LUA}
|
|
581
669
|
${RELEASE_PINS_LUA}
|
|
582
670
|
${WAKE_LUA}
|
|
583
|
-
|
|
584
|
-
redis.call('ZREM', PENDING, field)
|
|
585
|
-
redis.call('ZREM', READY, field)
|
|
586
|
-
if lane == '' then return end
|
|
587
|
-
local head_key = lane_field(lane, 'head')
|
|
588
|
-
if redis.call('HGET', META, head_key) ~= field then return end
|
|
589
|
-
while next_field do
|
|
590
|
-
local row = read_fields({ next_field }, { 'p', 'f', 'next' })[next_field]
|
|
591
|
-
if not row[1] then
|
|
592
|
-
redis.call('HSET', META, head_key, next_field)
|
|
593
|
-
if not row[2] then
|
|
594
|
-
redis.call('ZADD', READY, tonumber(next_field), next_field)
|
|
595
|
-
end
|
|
596
|
-
return
|
|
597
|
-
end
|
|
598
|
-
next_field = row[3]
|
|
599
|
-
end
|
|
600
|
-
clear_lane(lane)
|
|
601
|
-
end
|
|
671
|
+
${SETTLE_LUA}
|
|
602
672
|
local parent = ARGV[3]
|
|
603
673
|
local attempt = tonumber(ARGV[4])
|
|
604
674
|
local n = tonumber(ARGV[5])
|
|
@@ -684,6 +754,76 @@ if n > 0 then wake(ARGV[6 + n * 5], tostring(total + n), ARGV[2]) end
|
|
|
684
754
|
return { 'ok', tostring(total + 1) }
|
|
685
755
|
`;
|
|
686
756
|
/**
|
|
757
|
+
* KEYS: counter, meta, pending, ready, metadata split.
|
|
758
|
+
* ARGV: idx, action ('retry' | 'skip'), nowMs.
|
|
759
|
+
* Returns [redriven, hasPending]. Acts only on an unfinished, dead-lettered
|
|
760
|
+
* event above the clear boundary. A retry keeps the event pending and makes
|
|
761
|
+
* it ready again when it is unlaned or its lane's head.
|
|
762
|
+
*/
|
|
763
|
+
const REDRIVE_LUA = `
|
|
764
|
+
local COUNTER, META, SPLIT, PENDING, READY = KEYS[1], KEYS[2], KEYS[5], KEYS[3], KEYS[4]
|
|
765
|
+
${META_LUA}
|
|
766
|
+
${ENQUEUE_LUA}
|
|
767
|
+
${SETTLE_LUA}
|
|
768
|
+
local function result(redriven)
|
|
769
|
+
return { redriven, redis.call('ZCARD', PENDING) > 0 and '1' or '0' }
|
|
770
|
+
end
|
|
771
|
+
local counts = redis.call('MGET', COUNTER, SPLIT, CLEAR)
|
|
772
|
+
local total = tonumber(counts[1] or '0')
|
|
773
|
+
use_split(counts[2], counts[1], counts[3])
|
|
774
|
+
local idx = tonumber(ARGV[1])
|
|
775
|
+
if idx <= boundary or idx > total then return result('0') end
|
|
776
|
+
local field = tostring(idx)
|
|
777
|
+
local row = read_fields({ field }, { 'p', 'f', 'l', 'next' })[field]
|
|
778
|
+
if row[1] or not row[2] then return result('0') end
|
|
779
|
+
local meta_key = mkey(field)
|
|
780
|
+
local lane = row[3] or ''
|
|
781
|
+
if ARGV[2] == 'skip' then
|
|
782
|
+
put(meta_key, field .. ':p', ARGV[3])
|
|
783
|
+
settle(field, lane, row[4])
|
|
784
|
+
flush_queue()
|
|
785
|
+
flush()
|
|
786
|
+
else
|
|
787
|
+
redis.call('HDEL', meta_key, field .. ':f', field .. ':a')
|
|
788
|
+
if lane == '' or redis.call('HGET', META, lane_field(lane, 'head')) == field then
|
|
789
|
+
redis.call('ZADD', READY, idx, field)
|
|
790
|
+
end
|
|
791
|
+
end
|
|
792
|
+
return result('1')
|
|
793
|
+
`;
|
|
794
|
+
/**
|
|
795
|
+
* KEYS: store, counter, meta, pending, metadata split.
|
|
796
|
+
* Returns the dead-lettered events above the clear boundary, oldest first,
|
|
797
|
+
* as pairs of a stream entry and its STORED_EVENT_META_SUFFIXES columns.
|
|
798
|
+
* Every unfinished event is in the pending set, so the scan is bounded by
|
|
799
|
+
* unfinished work, not history; only dead letters read their full columns.
|
|
800
|
+
*/
|
|
801
|
+
const DEAD_LETTERS_LUA = `
|
|
802
|
+
local COUNTER, META, SPLIT = KEYS[2], KEYS[3], KEYS[5]
|
|
803
|
+
${META_LUA}
|
|
804
|
+
local counts = redis.call('MGET', COUNTER, SPLIT, CLEAR)
|
|
805
|
+
use_split(counts[2], counts[1], counts[3])
|
|
806
|
+
local candidates = {}
|
|
807
|
+
for _, field in ipairs(redis.call('ZRANGE', KEYS[4], 0, -1)) do
|
|
808
|
+
if tonumber(field) > boundary then candidates[#candidates + 1] = field end
|
|
809
|
+
end
|
|
810
|
+
local status = read_fields(candidates, { 'p', 'f' })
|
|
811
|
+
local dead = {}
|
|
812
|
+
for _, field in ipairs(candidates) do
|
|
813
|
+
if status[field][2] and not status[field][1] then dead[#dead + 1] = field end
|
|
814
|
+
end
|
|
815
|
+
local rows = read_fields(dead, { ${STORED_EVENT_META_SUFFIXES.map((suffix) => `'${suffix}'`).join(", ")} })
|
|
816
|
+
local result = {}
|
|
817
|
+
for _, field in ipairs(dead) do
|
|
818
|
+
local entries = redis.call('XRANGE', KEYS[1], field .. '-0', field .. '-0')
|
|
819
|
+
if #entries > 0 then
|
|
820
|
+
result[#result + 1] = entries[1]
|
|
821
|
+
result[#result + 1] = rows[field]
|
|
822
|
+
end
|
|
823
|
+
end
|
|
824
|
+
return result
|
|
825
|
+
`;
|
|
826
|
+
/**
|
|
687
827
|
* KEYS: head, history, event counter, event meta, pin counts, metadata split.
|
|
688
828
|
* ARGV: nowMs, event pin key prefix, write count, then per write:
|
|
689
829
|
* index, snapshot JSON, pin count, pin event indexes; finally the reducer
|
|
@@ -1070,21 +1210,6 @@ const fieldMap = (fields) => {
|
|
|
1070
1210
|
for (let i = 0; i + 1 < fields.length; i += 2) map[fields[i]] = fields[i + 1];
|
|
1071
1211
|
return map;
|
|
1072
1212
|
};
|
|
1073
|
-
const STORED_EVENT_META_SUFFIXES = [
|
|
1074
|
-
"p",
|
|
1075
|
-
"pa",
|
|
1076
|
-
"ri",
|
|
1077
|
-
"ch",
|
|
1078
|
-
"ce",
|
|
1079
|
-
"f",
|
|
1080
|
-
"fc",
|
|
1081
|
-
"lc",
|
|
1082
|
-
"lf",
|
|
1083
|
-
"lfa",
|
|
1084
|
-
"d",
|
|
1085
|
-
"a",
|
|
1086
|
-
"e"
|
|
1087
|
-
];
|
|
1088
1213
|
const entryIndex = (entryId) => Number(entryId.slice(0, entryId.indexOf("-")));
|
|
1089
1214
|
const toEvent = (sessionId, entry) => {
|
|
1090
1215
|
const fields = fieldMap(entry[1]);
|
|
@@ -1153,13 +1278,43 @@ const toCause = (raw) => {
|
|
|
1153
1278
|
...value.batchSize === void 0 ? {} : { batchSize: Number(value.batchSize) }
|
|
1154
1279
|
};
|
|
1155
1280
|
};
|
|
1281
|
+
/** A stream entry joined with its metadata columns; absent columns are unset. */
|
|
1282
|
+
const toStoredEvent = (sessionId, entry, column) => {
|
|
1283
|
+
const fields = fieldMap(entry[1]);
|
|
1284
|
+
const date = (suffix) => {
|
|
1285
|
+
const value = column(suffix);
|
|
1286
|
+
return value === void 0 ? null : new Date(Number(value));
|
|
1287
|
+
};
|
|
1288
|
+
const count = (suffix) => {
|
|
1289
|
+
const value = column(suffix);
|
|
1290
|
+
return value === void 0 ? null : Number(value);
|
|
1291
|
+
};
|
|
1292
|
+
const returnedEventIds = column("ri");
|
|
1293
|
+
return Object.assign(toEvent(sessionId, entry), {
|
|
1294
|
+
cause: toCause(fields["cause"]),
|
|
1295
|
+
lane: fields["lane"] === "" ? null : fields["lane"],
|
|
1296
|
+
processedAt: date("p"),
|
|
1297
|
+
processedByAttempt: count("pa"),
|
|
1298
|
+
returnedEventIds: returnedEventIds === void 0 ? null : decodeReturnedEventIds(returnedEventIds),
|
|
1299
|
+
firstClaimedAt: date("fc"),
|
|
1300
|
+
lastClaimedAt: date("lc"),
|
|
1301
|
+
attemptCount: count("d") ?? 0,
|
|
1302
|
+
claimHolder: column("ch") ?? null,
|
|
1303
|
+
claimExpiresAt: date("ce"),
|
|
1304
|
+
failureCount: count("a") ?? 0,
|
|
1305
|
+
lastFailedAt: date("lf"),
|
|
1306
|
+
lastFailedAttempt: count("lfa"),
|
|
1307
|
+
lastError: column("e") ?? null,
|
|
1308
|
+
failedAt: date("f")
|
|
1309
|
+
});
|
|
1310
|
+
};
|
|
1156
1311
|
const toClaimAvailableResult = (sessionId, reply) => {
|
|
1157
1312
|
const outcome = String(reply[0]);
|
|
1158
1313
|
if (outcome === "claimed") {
|
|
1159
1314
|
const count = Number(reply[1]);
|
|
1160
1315
|
const events = [];
|
|
1161
1316
|
for (let i = 0; i < count; i++) {
|
|
1162
|
-
const offset = 2 + i *
|
|
1317
|
+
const offset = 2 + i * 11;
|
|
1163
1318
|
const entry = reply[offset + 9];
|
|
1164
1319
|
const event = toEvent(sessionId, entry);
|
|
1165
1320
|
const fields = fieldMap(entry[1]);
|
|
@@ -1170,18 +1325,18 @@ const toClaimAvailableResult = (sessionId, reply) => {
|
|
|
1170
1325
|
processedByAttempt: null,
|
|
1171
1326
|
returnedEventIds: null,
|
|
1172
1327
|
firstClaimedAt: reply[offset + 3] === null ? null : new Date(Number(reply[offset + 3])),
|
|
1173
|
-
lastClaimedAt: new Date(Number(reply[offset + 4])),
|
|
1328
|
+
lastClaimedAt: reply[offset + 4] === null ? null : new Date(Number(reply[offset + 4])),
|
|
1174
1329
|
attemptCount: Number(reply[offset]),
|
|
1175
|
-
claimHolder: String(reply[offset + 7]),
|
|
1176
|
-
claimExpiresAt: new Date(Number(reply[offset + 8])),
|
|
1330
|
+
claimHolder: reply[offset + 7] === null ? null : String(reply[offset + 7]),
|
|
1331
|
+
claimExpiresAt: reply[offset + 8] === null ? null : new Date(Number(reply[offset + 8])),
|
|
1177
1332
|
failureCount: Number(reply[offset + 1]),
|
|
1178
1333
|
lastFailedAt: reply[offset + 5] === null ? null : new Date(Number(reply[offset + 5])),
|
|
1179
1334
|
lastFailedAttempt: reply[offset + 6] === null ? null : Number(reply[offset + 6]),
|
|
1180
1335
|
lastError: reply[offset + 2] === null ? null : String(reply[offset + 2]),
|
|
1181
|
-
failedAt: null
|
|
1336
|
+
failedAt: reply[offset + 10] === null ? null : new Date(Number(reply[offset + 10]))
|
|
1182
1337
|
}));
|
|
1183
1338
|
}
|
|
1184
|
-
const clearIndex = Number(reply[2 + count *
|
|
1339
|
+
const clearIndex = Number(reply[2 + count * 11] ?? 0);
|
|
1185
1340
|
if (clearIndex > 0) for (const event of events) event.clearIndex = clearIndex;
|
|
1186
1341
|
return {
|
|
1187
1342
|
outcome: "claimed",
|
|
@@ -1295,36 +1450,8 @@ function createRedisStoreCore(options) {
|
|
|
1295
1450
|
}
|
|
1296
1451
|
}
|
|
1297
1452
|
return entries.map((entry) => {
|
|
1298
|
-
const
|
|
1299
|
-
|
|
1300
|
-
const fields = fieldMap(entry[1]);
|
|
1301
|
-
const processedAt = meta[`${idx}:p`];
|
|
1302
|
-
const processedByAttempt = meta[`${idx}:pa`];
|
|
1303
|
-
const returnedEventIds = meta[`${idx}:ri`];
|
|
1304
|
-
const claimHolder = meta[`${idx}:ch`];
|
|
1305
|
-
const claimExpiresAt = meta[`${idx}:ce`];
|
|
1306
|
-
const failedAt = meta[`${idx}:f`];
|
|
1307
|
-
const firstClaimedAt = meta[`${idx}:fc`];
|
|
1308
|
-
const lastClaimedAt = meta[`${idx}:lc`];
|
|
1309
|
-
const lastFailedAt = meta[`${idx}:lf`];
|
|
1310
|
-
const lastFailedAttempt = meta[`${idx}:lfa`];
|
|
1311
|
-
return Object.assign(event, {
|
|
1312
|
-
cause: toCause(fields["cause"]),
|
|
1313
|
-
lane: fields["lane"] === "" ? null : fields["lane"],
|
|
1314
|
-
processedAt: processedAt === void 0 ? null : new Date(Number(processedAt)),
|
|
1315
|
-
processedByAttempt: processedByAttempt === void 0 ? null : Number(processedByAttempt),
|
|
1316
|
-
returnedEventIds: returnedEventIds === void 0 ? null : decodeReturnedEventIds(returnedEventIds),
|
|
1317
|
-
firstClaimedAt: firstClaimedAt === void 0 ? null : new Date(Number(firstClaimedAt)),
|
|
1318
|
-
lastClaimedAt: lastClaimedAt === void 0 ? null : new Date(Number(lastClaimedAt)),
|
|
1319
|
-
attemptCount: Number(meta[`${idx}:d`] ?? 0),
|
|
1320
|
-
claimHolder: claimHolder ?? null,
|
|
1321
|
-
claimExpiresAt: claimExpiresAt === void 0 ? null : new Date(Number(claimExpiresAt)),
|
|
1322
|
-
failureCount: Number(meta[`${idx}:a`] ?? 0),
|
|
1323
|
-
lastFailedAt: lastFailedAt === void 0 ? null : new Date(Number(lastFailedAt)),
|
|
1324
|
-
lastFailedAttempt: lastFailedAttempt === void 0 ? null : Number(lastFailedAttempt),
|
|
1325
|
-
lastError: meta[`${idx}:e`] ?? null,
|
|
1326
|
-
failedAt: failedAt === void 0 ? null : new Date(Number(failedAt))
|
|
1327
|
-
});
|
|
1453
|
+
const idx = entryIndex(entry[0]);
|
|
1454
|
+
return toStoredEvent(sessionId, entry, (suffix) => meta[`${idx}:${suffix}`]);
|
|
1328
1455
|
});
|
|
1329
1456
|
};
|
|
1330
1457
|
const readEventPages = async (sessionId, afterIndex, throughIndex) => {
|
|
@@ -1518,7 +1645,7 @@ function createRedisStoreCore(options) {
|
|
|
1518
1645
|
return readEventRange(sessionId, Math.max(after, clearIndex - 1), Math.min(opts?.throughIndex ?? frontier, frontier));
|
|
1519
1646
|
}));
|
|
1520
1647
|
},
|
|
1521
|
-
async claimAvailable({ sessionId, holder, ttlMs, expiresAtMs, excludeIndexes }) {
|
|
1648
|
+
async claimAvailable({ sessionId, holder, ttlMs, expiresAtMs, excludeIndexes, maxFailures }) {
|
|
1522
1649
|
return wrap(async () => {
|
|
1523
1650
|
const now = clock.now().getTime();
|
|
1524
1651
|
const expiresAt = expiresAtMs ?? now + ttlMs;
|
|
@@ -1529,13 +1656,16 @@ function createRedisStoreCore(options) {
|
|
|
1529
1656
|
metaKey(sessionId),
|
|
1530
1657
|
pendingKey(sessionId),
|
|
1531
1658
|
readyKey(sessionId),
|
|
1532
|
-
metaSplitKey(sessionId)
|
|
1659
|
+
metaSplitKey(sessionId),
|
|
1660
|
+
snapshotPinCountsKey(sessionId)
|
|
1533
1661
|
], [
|
|
1534
1662
|
holder,
|
|
1535
1663
|
now,
|
|
1536
1664
|
expiresAt,
|
|
1537
1665
|
excluded.length,
|
|
1538
|
-
...excluded
|
|
1666
|
+
...excluded,
|
|
1667
|
+
maxFailures ?? "",
|
|
1668
|
+
snapshotEventPinsPrefix(sessionId)
|
|
1539
1669
|
]);
|
|
1540
1670
|
return toClaimAvailableResult(sessionId, reply);
|
|
1541
1671
|
});
|
|
@@ -1646,8 +1776,9 @@ function createRedisStoreCore(options) {
|
|
|
1646
1776
|
throw new TypeError(`unexpected completion outcome '${outcome}'`);
|
|
1647
1777
|
});
|
|
1648
1778
|
},
|
|
1649
|
-
async failAttempt({ sessionId, index, attempt, error, maxFailures }) {
|
|
1779
|
+
async failAttempt({ sessionId, index, attempt, error, maxFailures, retryAfterMs }) {
|
|
1650
1780
|
return wrap(async () => {
|
|
1781
|
+
const now = clock.now().getTime();
|
|
1651
1782
|
const reply = await evalScript(FAIL_ATTEMPT_LUA, [
|
|
1652
1783
|
countKey(sessionId),
|
|
1653
1784
|
metaKey(sessionId),
|
|
@@ -1661,7 +1792,8 @@ function createRedisStoreCore(options) {
|
|
|
1661
1792
|
attempt,
|
|
1662
1793
|
error,
|
|
1663
1794
|
maxFailures,
|
|
1664
|
-
|
|
1795
|
+
now,
|
|
1796
|
+
retryAfterMs === void 0 ? "" : now + retryAfterMs
|
|
1665
1797
|
]);
|
|
1666
1798
|
const outcome = reply[0];
|
|
1667
1799
|
if (outcome === "cleared") return {
|
|
@@ -1675,6 +1807,42 @@ function createRedisStoreCore(options) {
|
|
|
1675
1807
|
};
|
|
1676
1808
|
});
|
|
1677
1809
|
},
|
|
1810
|
+
async deadLetters(sessionId) {
|
|
1811
|
+
return wrap(async () => {
|
|
1812
|
+
const reply = await evalScript(DEAD_LETTERS_LUA, [
|
|
1813
|
+
storeKey(sessionId),
|
|
1814
|
+
countKey(sessionId),
|
|
1815
|
+
metaKey(sessionId),
|
|
1816
|
+
pendingKey(sessionId),
|
|
1817
|
+
metaSplitKey(sessionId)
|
|
1818
|
+
], []);
|
|
1819
|
+
const events = [];
|
|
1820
|
+
for (let i = 0; i + 1 < reply.length; i += 2) {
|
|
1821
|
+
const columns = reply[i + 1];
|
|
1822
|
+
events.push(toStoredEvent(sessionId, reply[i], (suffix) => columns[STORED_EVENT_META_SUFFIXES.indexOf(suffix)] ?? void 0));
|
|
1823
|
+
}
|
|
1824
|
+
return events;
|
|
1825
|
+
});
|
|
1826
|
+
},
|
|
1827
|
+
async redrive({ sessionId, index, action }) {
|
|
1828
|
+
return wrap(async () => {
|
|
1829
|
+
const [redriven, hasPending] = await evalScript(REDRIVE_LUA, [
|
|
1830
|
+
countKey(sessionId),
|
|
1831
|
+
metaKey(sessionId),
|
|
1832
|
+
pendingKey(sessionId),
|
|
1833
|
+
readyKey(sessionId),
|
|
1834
|
+
metaSplitKey(sessionId)
|
|
1835
|
+
], [
|
|
1836
|
+
index,
|
|
1837
|
+
action,
|
|
1838
|
+
clock.now().getTime()
|
|
1839
|
+
]);
|
|
1840
|
+
return {
|
|
1841
|
+
redriven: redriven === "1",
|
|
1842
|
+
hasPending: hasPending === "1"
|
|
1843
|
+
};
|
|
1844
|
+
});
|
|
1845
|
+
},
|
|
1678
1846
|
async readState(sessionId, reducerName, stateOptions) {
|
|
1679
1847
|
return wrap(() => retryAfterGap(async () => {
|
|
1680
1848
|
const reply = await evalScript(READ_STATE_LUA, [
|
|
@@ -2084,6 +2252,8 @@ function createRedisNotifyStore(options) {
|
|
|
2084
2252
|
putSnapshots: core.putSnapshots,
|
|
2085
2253
|
clear: core.clear,
|
|
2086
2254
|
reclaim: core.reclaim,
|
|
2255
|
+
deadLetters: core.deadLetters,
|
|
2256
|
+
redrive: core.redrive,
|
|
2087
2257
|
presence: {
|
|
2088
2258
|
async set(ns, participant, values, meta) {
|
|
2089
2259
|
const patch = await core.presence.set(ns, participant, values, meta);
|
|
@@ -2371,4 +2541,4 @@ function createRedisNotifyStore(options) {
|
|
|
2371
2541
|
//#endregion
|
|
2372
2542
|
export { createRedisNotifyStore as t };
|
|
2373
2543
|
|
|
2374
|
-
//# sourceMappingURL=store-redis-notify-
|
|
2544
|
+
//# sourceMappingURL=store-redis-notify-CM0AfLY0.js.map
|