experimental-a2 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +39 -0
- package/dist/actor-D_54lz_1.d.ts +310 -0
- package/dist/actor-D_54lz_1.d.ts.map +1 -0
- package/dist/actor-client.d.ts +13 -4
- package/dist/actor-client.d.ts.map +1 -1
- package/dist/actor-client.js +63 -7
- package/dist/actor-client.js.map +1 -1
- package/dist/actor-react.d.ts +5 -4
- package/dist/actor-react.d.ts.map +1 -1
- package/dist/actor-react.js +16 -2
- package/dist/actor-react.js.map +1 -1
- package/dist/actor.d.ts +2 -176
- package/dist/actor.js +13 -2
- package/dist/actor.js.map +1 -1
- package/dist/ai-server.d.ts +1 -1
- package/dist/ai-server.js +2 -2
- package/dist/ai.d.ts +1 -1
- package/dist/ai.js +1 -1
- package/dist/client-Bf6uSEAk.js +1342 -0
- package/dist/client-Bf6uSEAk.js.map +1 -0
- package/dist/client-P_NNNRM-.d.ts +243 -0
- package/dist/client-P_NNNRM-.d.ts.map +1 -0
- package/dist/client.d.ts +2 -208
- package/dist/client.js +2 -1206
- package/dist/errors-DCk6ch5n.js.map +1 -1
- package/dist/errors-DvhSXnxk.d.ts +28 -0
- package/dist/errors-DvhSXnxk.d.ts.map +1 -0
- package/dist/index.d.ts +3 -35
- package/dist/{internal-DRXJ56EI.js → internal-Dq2qYxou.js} +2 -2
- package/dist/{internal-DRXJ56EI.js.map → internal-Dq2qYxou.js.map} +1 -1
- package/dist/platform-B4TnJtWu.js +34 -0
- package/dist/platform-B4TnJtWu.js.map +1 -0
- package/dist/react.d.ts +3 -1
- package/dist/react.d.ts.map +1 -1
- package/dist/react.js +2 -1
- package/dist/react.js.map +1 -1
- package/dist/scheduler-qstash.d.ts +2 -2
- package/dist/scheduler-qstash.js +3 -2
- package/dist/scheduler-qstash.js.map +1 -1
- package/dist/scheduler-vercel.d.ts +2 -2
- package/dist/scheduler-vercel.js +2 -2
- package/dist/{server-DlLyvaSH.js → server-Dkz2a84E.js} +165 -62
- package/dist/server-Dkz2a84E.js.map +1 -0
- package/dist/{server-DgCrSuhB.d.ts → server-DwPrMqHB.d.ts} +2 -2
- package/dist/{server-DgCrSuhB.d.ts.map → server-DwPrMqHB.d.ts.map} +1 -1
- package/dist/server.d.ts +2 -2
- package/dist/server.js +1 -1
- package/dist/{store-DGHeBtIQ.d.ts → store-DtDOWLSn.d.ts} +4 -5
- package/dist/{store-DGHeBtIQ.d.ts.map → store-DtDOWLSn.d.ts.map} +1 -1
- package/dist/store-N8PXxDAS.js.map +1 -1
- package/dist/store-memory.d.ts +1 -1
- package/dist/store-memory.js +1 -1
- package/dist/{store-polling-6DW7F1DT.js → store-polling-CmxUbV93.js} +56 -7
- package/dist/store-polling-CmxUbV93.js.map +1 -0
- package/dist/store-postgres.d.ts +6 -4
- package/dist/store-postgres.d.ts.map +1 -1
- package/dist/store-postgres.js +701 -53
- package/dist/store-postgres.js.map +1 -1
- package/dist/store-presence-polling-C7-XZyW9.js +94 -0
- package/dist/store-presence-polling-C7-XZyW9.js.map +1 -0
- package/dist/store-redis-http.d.ts +2 -2
- package/dist/store-redis-http.d.ts.map +1 -1
- package/dist/store-redis-http.js +184 -38
- package/dist/store-redis-http.js.map +1 -1
- package/dist/{store-redis-core-z-ykbyMg.js → store-redis-notify-BUCyXOn0.js} +491 -27
- package/dist/store-redis-notify-BUCyXOn0.js.map +1 -0
- package/dist/store-redis.d.ts +5 -13
- package/dist/store-redis.d.ts.map +1 -1
- package/dist/store-redis.js +27 -271
- package/dist/store-redis.js.map +1 -1
- package/dist/store-sqlite.d.ts +1 -1
- package/dist/store-sqlite.js +1 -1
- package/dist/{wire--yji6mO3.js → wire-BO5wWCb1.js} +18 -16
- package/dist/wire-BO5wWCb1.js.map +1 -0
- package/docs/actors/04-routes.mdx +40 -8
- package/docs/guides/03-react.mdx +52 -10
- package/docs/guides/05-production.mdx +54 -5
- package/docs/guides/09-presence.mdx +12 -7
- package/docs/guides/10-transports.mdx +15 -2
- package/docs/reference/01-api.mdx +60 -16
- package/docs/reference/02-errors.mdx +45 -11
- package/examples/playground/package.json +1 -1
- package/package.json +1 -1
- package/src/actor-client.ts +114 -14
- package/src/actor-react.ts +18 -3
- package/src/actor.ts +16 -1
- package/src/client-errors.ts +51 -0
- package/src/client.ts +253 -96
- package/src/errors.ts +4 -9
- package/src/index.ts +1 -1
- package/src/internal.ts +1 -1
- package/src/postgres-notification-scope.ts +134 -0
- package/src/postgres-notifications.ts +244 -0
- package/src/postgres-pool.ts +65 -0
- package/src/postgres-resources.ts +185 -0
- package/src/presence-recovery.ts +120 -0
- package/src/react.ts +3 -0
- package/src/redis-http-subscriptions.ts +199 -0
- package/src/server.ts +146 -19
- package/src/session-socket.ts +25 -7
- package/src/sse.ts +17 -0
- package/src/store-polling.ts +32 -12
- package/src/store-postgres.ts +292 -75
- package/src/store-presence-polling.ts +125 -0
- package/src/store-redis-core.ts +37 -30
- package/src/store-redis-http.ts +51 -45
- package/src/store-redis-notify.ts +464 -0
- package/src/store-redis.ts +9 -364
- package/src/store.ts +3 -4
- package/src/stream-activity.ts +32 -0
- package/src/wire.ts +39 -15
- package/dist/actor-shared-USo5MyuF.d.ts +0 -136
- package/dist/actor-shared-USo5MyuF.d.ts.map +0 -1
- package/dist/actor.d.ts.map +0 -1
- package/dist/client.d.ts.map +0 -1
- package/dist/client.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/server-DlLyvaSH.js.map +0 -1
- package/dist/store-polling-6DW7F1DT.js.map +0 -1
- package/dist/store-redis-core-z-ykbyMg.js.map +0 -1
- package/dist/wire--yji6mO3.js.map +0 -1
|
@@ -1,40 +1,10 @@
|
|
|
1
1
|
import { n as validateSync } from "./validate-XKT4FSNn.js";
|
|
2
2
|
import { n as NonRetriableError, r as asStoreUnavailable, t as A2Error } from "./errors-DCk6ch5n.js";
|
|
3
|
-
import { c as STREAM_TIMINGS, g as serverInternals, h as nullProtoRecord, i as POLL_TIMINGS, m as markSchedulerSendFailure, o as RESERVED_PARTICIPANT_IDS, s as SOCKET_TIMINGS, t as DRAIN_TIMINGS } from "./internal-
|
|
4
|
-
import { t as defaultSleep } from "./store-polling-
|
|
5
|
-
import {
|
|
3
|
+
import { c as STREAM_TIMINGS, g as serverInternals, h as nullProtoRecord, i as POLL_TIMINGS, m as markSchedulerSendFailure, o as RESERVED_PARTICIPANT_IDS, s as SOCKET_TIMINGS, t as DRAIN_TIMINGS } from "./internal-Dq2qYxou.js";
|
|
4
|
+
import { i as streamActivities, r as createStreamActivity, t as defaultSleep } from "./store-polling-CmxUbV93.js";
|
|
5
|
+
import { r as platformWaitUntil, t as invocationDeadlineMs } from "./platform-B4TnJtWu.js";
|
|
6
|
+
import { _ as socketErrorAckFor, a as errorToWire, b as socketUnsubscribedFor, g as socketAckFor, h as presenceSnapshotToWire, i as errorStatus, n as asA2Error, p as presencePatchToWire, s as eventToWire, t as SOCKET_PING_FRAME, v as socketFrameFor, y as socketSubscribedFor } from "./wire-BO5wWCb1.js";
|
|
6
7
|
import { t as retryableLazy } from "./retryable-lazy-DZWmHpii.js";
|
|
7
|
-
//#region src/platform.ts
|
|
8
|
-
const SYMBOL_FOR_REQ_CONTEXT = Symbol.for("@vercel/request-context");
|
|
9
|
-
function requestContext() {
|
|
10
|
-
try {
|
|
11
|
-
return Reflect.get(globalThis, SYMBOL_FOR_REQ_CONTEXT)?.get?.() ?? {};
|
|
12
|
-
} catch {
|
|
13
|
-
return {};
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
/** The current invocation's Vercel deployment identity, when available. */
|
|
17
|
-
function platformVercelOidcToken() {
|
|
18
|
-
try {
|
|
19
|
-
const token = requestContext().headers?.["x-vercel-oidc-token"];
|
|
20
|
-
return typeof token === "string" && token.length > 0 ? token : null;
|
|
21
|
-
} catch {
|
|
22
|
-
return null;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
function platformWaitUntil(promise) {
|
|
26
|
-
try {
|
|
27
|
-
requestContext().waitUntil?.(promise);
|
|
28
|
-
} catch {}
|
|
29
|
-
}
|
|
30
|
-
/** The invocation's termination time in epoch ms, or null if unknowable. */
|
|
31
|
-
function invocationDeadlineMs() {
|
|
32
|
-
const deadline = requestContext().deadline;
|
|
33
|
-
if (deadline === void 0 || deadline === null) return null;
|
|
34
|
-
const ms = new Date(deadline).getTime();
|
|
35
|
-
return Number.isNaN(ms) ? null : ms;
|
|
36
|
-
}
|
|
37
|
-
//#endregion
|
|
38
8
|
//#region src/push-envelope.ts
|
|
39
9
|
/**
|
|
40
10
|
* The push envelope's trust boundary for `{ sessionId, events, presence? }`,
|
|
@@ -242,7 +212,7 @@ const pumpSubscription = async (shell, subscription, frameFor) => {
|
|
|
242
212
|
shell.send(frameFor(value));
|
|
243
213
|
}
|
|
244
214
|
};
|
|
245
|
-
const handleSocketPush = async (shell, target, sessionId, frame, req, ackSessionId, gatePush) => {
|
|
215
|
+
const handleSocketPush = async (shell, target, sessionId, frame, req, ackSessionId, gatePush, activate) => {
|
|
246
216
|
try {
|
|
247
217
|
const events = parsePushEvents(frame["events"]);
|
|
248
218
|
const denial = await gatePush?.(sessionId, events, void 0) ?? null;
|
|
@@ -250,7 +220,9 @@ const handleSocketPush = async (shell, target, sessionId, frame, req, ackSession
|
|
|
250
220
|
shell.send(socketErrorAckFor(req, denial, ackSessionId));
|
|
251
221
|
return;
|
|
252
222
|
}
|
|
223
|
+
activate();
|
|
253
224
|
const appended = await target.append(...events);
|
|
225
|
+
activate();
|
|
254
226
|
shell.send(socketAckFor(req, appended, ackSessionId));
|
|
255
227
|
} catch (error) {
|
|
256
228
|
shell.send(socketErrorAckFor(req, asA2Error(error), ackSessionId));
|
|
@@ -300,7 +272,7 @@ function sessionSocket(sessionId, session, socket, options) {
|
|
|
300
272
|
shell.send(socketErrorAckFor(req, new A2Error("STORE_UNAVAILABLE", "push shed: too many in flight on this socket")));
|
|
301
273
|
return;
|
|
302
274
|
}
|
|
303
|
-
shell.track(handleSocketPush(shell, target, sessionId, frame, req, void 0, options?.gatePush));
|
|
275
|
+
shell.track(handleSocketPush(shell, target, sessionId, frame, req, void 0, options?.gatePush, () => streamActivities.get(subscription.iterator)?.activate()));
|
|
304
276
|
return;
|
|
305
277
|
}
|
|
306
278
|
case "presence":
|
|
@@ -355,29 +327,31 @@ function sessionsSocket(resolve, socket, options) {
|
|
|
355
327
|
if (shell.torn() || subscription.stopped) return;
|
|
356
328
|
retire(id, subscription);
|
|
357
329
|
shell.send(socketUnsubscribedFor(id));
|
|
358
|
-
} catch {
|
|
330
|
+
} catch (error) {
|
|
359
331
|
if (shell.torn() || subscription.stopped) return;
|
|
360
332
|
retire(id, subscription);
|
|
361
|
-
shell.send(socketUnsubscribedFor(id, "stream failed"));
|
|
333
|
+
shell.send(socketUnsubscribedFor(id, "stream failed", asA2Error(error)));
|
|
362
334
|
}
|
|
363
335
|
};
|
|
364
336
|
const startSubscription = async (id, index) => {
|
|
337
|
+
const existing = subscriptions.get(id);
|
|
338
|
+
if (existing) {
|
|
339
|
+
stopSubscription(existing);
|
|
340
|
+
subscriptions.delete(id);
|
|
341
|
+
}
|
|
365
342
|
let session;
|
|
366
343
|
try {
|
|
367
344
|
session = await resolve(id, index);
|
|
368
|
-
} catch {
|
|
369
|
-
if (!shell.torn()) shell.send(socketUnsubscribedFor(id, "stream failed"));
|
|
345
|
+
} catch (error) {
|
|
346
|
+
if (!shell.torn()) shell.send(socketUnsubscribedFor(id, "stream failed", asA2Error(error)));
|
|
370
347
|
return;
|
|
371
348
|
}
|
|
372
349
|
if (shell.torn()) return;
|
|
373
350
|
if (session === null) {
|
|
374
|
-
shell.send(socketUnsubscribedFor(id, "subscribe rejected"));
|
|
351
|
+
shell.send(socketUnsubscribedFor(id, "subscribe rejected", new A2Error("FORBIDDEN", "the subscription is not authorized")));
|
|
375
352
|
return;
|
|
376
353
|
}
|
|
377
|
-
const
|
|
378
|
-
const existing = subscriptions.get(id);
|
|
379
|
-
if (existing) stopSubscription(existing);
|
|
380
|
-
const subscription = socketSubscription(target, index, presence);
|
|
354
|
+
const subscription = socketSubscription(session, index, presence);
|
|
381
355
|
subscriptions.set(id, subscription);
|
|
382
356
|
shell.send(socketSubscribedFor(id));
|
|
383
357
|
runSubscription(id, subscription);
|
|
@@ -392,7 +366,10 @@ function sessionsSocket(resolve, socket, options) {
|
|
|
392
366
|
shell.send(socketErrorAckFor(req, new A2Error("STORE_UNAVAILABLE", "session is not subscribed on this socket"), sessionId));
|
|
393
367
|
return;
|
|
394
368
|
}
|
|
395
|
-
await handleSocketPush(shell, subscription.target, sessionId, frame, req, sessionId, options?.gatePush)
|
|
369
|
+
await handleSocketPush(shell, subscription.target, sessionId, frame, req, sessionId, options?.gatePush, () => {
|
|
370
|
+
const current = subscriptions.get(sessionId);
|
|
371
|
+
if (current) streamActivities.get(current.iterator)?.activate();
|
|
372
|
+
});
|
|
396
373
|
};
|
|
397
374
|
const handlePresence = async (frame, sessionId) => {
|
|
398
375
|
const subscription = subscriptions.get(sessionId);
|
|
@@ -493,7 +470,10 @@ function sseResponse(iterable) {
|
|
|
493
470
|
let deadlineTimer;
|
|
494
471
|
let closed = false;
|
|
495
472
|
let iteratorReturned = false;
|
|
473
|
+
let stopActivity;
|
|
496
474
|
const stopTimers = () => {
|
|
475
|
+
stopActivity?.();
|
|
476
|
+
stopActivity = void 0;
|
|
497
477
|
if (heartbeat !== void 0) clearInterval(heartbeat);
|
|
498
478
|
if (deadlineTimer !== void 0) clearTimeout(deadlineTimer);
|
|
499
479
|
heartbeat = void 0;
|
|
@@ -507,6 +487,15 @@ function sseResponse(iterable) {
|
|
|
507
487
|
const stream = new ReadableStream({
|
|
508
488
|
start(controller) {
|
|
509
489
|
controller.enqueue(encoder.encode(": connected\n\n"));
|
|
490
|
+
const activity = streamActivities.get(iterator);
|
|
491
|
+
if (activity) {
|
|
492
|
+
const announce = (idle) => {
|
|
493
|
+
if (closed) return;
|
|
494
|
+
controller.enqueue(encoder.encode(`event: a2-activity\ndata: ${idle ? "idle" : "active"}\n\n`));
|
|
495
|
+
};
|
|
496
|
+
stopActivity = activity.subscribe(announce);
|
|
497
|
+
if (activity.idle) announce(true);
|
|
498
|
+
}
|
|
510
499
|
heartbeat = setInterval(() => {
|
|
511
500
|
try {
|
|
512
501
|
controller.enqueue(encoder.encode(": ping\n\n"));
|
|
@@ -1405,12 +1394,57 @@ function createServer(options) {
|
|
|
1405
1394
|
createdAt: event.createdAt
|
|
1406
1395
|
});
|
|
1407
1396
|
const streamEvents = (id, startAfter) => {
|
|
1408
|
-
|
|
1397
|
+
let closed = false;
|
|
1398
|
+
let inner;
|
|
1399
|
+
let stopActivity;
|
|
1400
|
+
const activity = createStreamActivity(() => {
|
|
1401
|
+
if (inner && !closed) streamActivities.get(inner)?.activate();
|
|
1402
|
+
});
|
|
1403
|
+
let closing;
|
|
1404
|
+
const close = () => {
|
|
1405
|
+
closed = true;
|
|
1406
|
+
closing ??= (async () => {
|
|
1407
|
+
stopActivity?.();
|
|
1408
|
+
await inner?.return?.();
|
|
1409
|
+
})();
|
|
1410
|
+
return closing;
|
|
1411
|
+
};
|
|
1409
1412
|
const outer = async function* () {
|
|
1410
|
-
const
|
|
1411
|
-
|
|
1413
|
+
const store = await resolveStore();
|
|
1414
|
+
if (closed) return;
|
|
1415
|
+
inner = store.stream(nsId(id), { startAfter })[Symbol.asyncIterator]();
|
|
1416
|
+
const sourceActivity = streamActivities.get(inner);
|
|
1417
|
+
if (sourceActivity) {
|
|
1418
|
+
stopActivity = sourceActivity.subscribe(activity.setIdle);
|
|
1419
|
+
activity.setIdle(sourceActivity.idle);
|
|
1420
|
+
}
|
|
1421
|
+
try {
|
|
1422
|
+
for (;;) {
|
|
1423
|
+
if (closed) return;
|
|
1424
|
+
const result = await inner.next();
|
|
1425
|
+
if (closed || result.done) return;
|
|
1426
|
+
yield toSessionEvent(id, result.value);
|
|
1427
|
+
}
|
|
1428
|
+
} finally {
|
|
1429
|
+
await close();
|
|
1430
|
+
}
|
|
1412
1431
|
};
|
|
1413
|
-
|
|
1432
|
+
const iterator = outer();
|
|
1433
|
+
return { [Symbol.asyncIterator]() {
|
|
1434
|
+
const stream = {
|
|
1435
|
+
next: () => iterator.next(),
|
|
1436
|
+
async return() {
|
|
1437
|
+
await close();
|
|
1438
|
+
return iterator.return(void 0);
|
|
1439
|
+
},
|
|
1440
|
+
async throw(error) {
|
|
1441
|
+
await close();
|
|
1442
|
+
return iterator.throw(error);
|
|
1443
|
+
}
|
|
1444
|
+
};
|
|
1445
|
+
streamActivities.set(stream, activity);
|
|
1446
|
+
return stream;
|
|
1447
|
+
} };
|
|
1414
1448
|
};
|
|
1415
1449
|
const requirePresence = (store) => {
|
|
1416
1450
|
if (!store.presence) throw presenceNotSupported();
|
|
@@ -1462,8 +1496,39 @@ function createServer(options) {
|
|
|
1462
1496
|
*/
|
|
1463
1497
|
const streamWithPresence = (id, startAfter) => {
|
|
1464
1498
|
const ns = nsId(id);
|
|
1499
|
+
let closed = false;
|
|
1500
|
+
let events;
|
|
1501
|
+
let unsubscribe;
|
|
1502
|
+
let sleeper = null;
|
|
1503
|
+
let wakeQueue = null;
|
|
1504
|
+
let presenceInterval = Math.min(POLL_TIMINGS.activeFloorMs, POLL_TIMINGS.idleCeilingMs);
|
|
1505
|
+
let presenceActivityVersion = 0;
|
|
1506
|
+
let stopActivity;
|
|
1507
|
+
const activity = createStreamActivity(() => {
|
|
1508
|
+
if (closed) return;
|
|
1509
|
+
presenceActivityVersion += 1;
|
|
1510
|
+
presenceInterval = Math.min(POLL_TIMINGS.activeFloorMs, POLL_TIMINGS.idleCeilingMs);
|
|
1511
|
+
sleeper?.cancel();
|
|
1512
|
+
if (events) streamActivities.get(events)?.activate();
|
|
1513
|
+
});
|
|
1514
|
+
let closing;
|
|
1515
|
+
const close = () => {
|
|
1516
|
+
closed = true;
|
|
1517
|
+
sleeper?.cancel();
|
|
1518
|
+
wakeQueue?.();
|
|
1519
|
+
closing ??= (async () => {
|
|
1520
|
+
try {
|
|
1521
|
+
stopActivity?.();
|
|
1522
|
+
unsubscribe?.();
|
|
1523
|
+
} finally {
|
|
1524
|
+
await events?.return?.();
|
|
1525
|
+
}
|
|
1526
|
+
})();
|
|
1527
|
+
return closing;
|
|
1528
|
+
};
|
|
1465
1529
|
const outer = async function* () {
|
|
1466
1530
|
const store = await resolveStore();
|
|
1531
|
+
if (closed) return;
|
|
1467
1532
|
const api = requirePresence(store);
|
|
1468
1533
|
const readRows = async () => {
|
|
1469
1534
|
try {
|
|
@@ -1538,8 +1603,9 @@ function createServer(options) {
|
|
|
1538
1603
|
if (fields?.size === 0) painted.delete(patch.participant);
|
|
1539
1604
|
};
|
|
1540
1605
|
const queue = /* @__PURE__ */ new Map();
|
|
1541
|
-
let wakeQueue = null;
|
|
1542
1606
|
const enqueue = (patch) => {
|
|
1607
|
+
if (closed) return;
|
|
1608
|
+
activity.activate();
|
|
1543
1609
|
for (const [field, value] of Object.entries(patch.values)) {
|
|
1544
1610
|
if (value === void 0) continue;
|
|
1545
1611
|
let fields = queue.get(patch.participant);
|
|
@@ -1573,11 +1639,17 @@ function createServer(options) {
|
|
|
1573
1639
|
}
|
|
1574
1640
|
return null;
|
|
1575
1641
|
};
|
|
1576
|
-
const unsubscribe = api.subscribe?.(ns, enqueue);
|
|
1577
|
-
const events = store.stream(ns, { startAfter })[Symbol.asyncIterator]();
|
|
1578
1642
|
let pendingEvent = null;
|
|
1579
1643
|
try {
|
|
1644
|
+
unsubscribe = api.subscribe?.(ns, enqueue);
|
|
1645
|
+
events = store.stream(ns, { startAfter })[Symbol.asyncIterator]();
|
|
1646
|
+
const sourceActivity = streamActivities.get(events);
|
|
1647
|
+
if (sourceActivity) {
|
|
1648
|
+
stopActivity = sourceActivity.subscribe(activity.setIdle);
|
|
1649
|
+
activity.setIdle(sourceActivity.idle);
|
|
1650
|
+
}
|
|
1580
1651
|
const snapshotRows = await readRows();
|
|
1652
|
+
if (closed) return;
|
|
1581
1653
|
for (const row of snapshotRows) {
|
|
1582
1654
|
let fields = painted.get(row.participant);
|
|
1583
1655
|
if (!fields) {
|
|
@@ -1592,9 +1664,11 @@ function createServer(options) {
|
|
|
1592
1664
|
}
|
|
1593
1665
|
yield { snapshot: foldPresenceRows(snapshotRows) };
|
|
1594
1666
|
for (;;) {
|
|
1667
|
+
if (closed) return;
|
|
1595
1668
|
for (;;) {
|
|
1596
1669
|
const patch = dequeue();
|
|
1597
1670
|
if (!patch) break;
|
|
1671
|
+
if (closed) return;
|
|
1598
1672
|
paint(patch);
|
|
1599
1673
|
yield patch;
|
|
1600
1674
|
}
|
|
@@ -1606,28 +1680,57 @@ function createServer(options) {
|
|
|
1606
1680
|
});
|
|
1607
1681
|
woke = await Promise.race([pendingEvent.then(() => "event"), arrival.then(() => "patch")]);
|
|
1608
1682
|
wakeQueue = null;
|
|
1683
|
+
if (closed) return;
|
|
1609
1684
|
if (woke === "patch") continue;
|
|
1610
1685
|
} else {
|
|
1611
|
-
|
|
1686
|
+
sleeper = defaultSleep(presenceInterval);
|
|
1612
1687
|
woke = await Promise.race([pendingEvent.then(() => "event"), sleeper.promise.then(() => "tick")]);
|
|
1613
1688
|
sleeper.cancel();
|
|
1689
|
+
sleeper = null;
|
|
1614
1690
|
}
|
|
1691
|
+
if (closed) return;
|
|
1615
1692
|
if (woke === "event") {
|
|
1616
1693
|
const result = await pendingEvent;
|
|
1617
1694
|
pendingEvent = null;
|
|
1618
|
-
if (result.done) return;
|
|
1695
|
+
if (closed || result.done) return;
|
|
1696
|
+
activity.activate();
|
|
1619
1697
|
yield toSessionEvent(id, result.value);
|
|
1620
1698
|
}
|
|
1621
|
-
if (!
|
|
1699
|
+
if (!closed && !unsubscribe) {
|
|
1700
|
+
const version = presenceActivityVersion;
|
|
1701
|
+
const rows = await readRows();
|
|
1702
|
+
if (closed) return;
|
|
1703
|
+
const patches = diffRows(rows);
|
|
1704
|
+
if (patches.length > 0) activity.activate();
|
|
1705
|
+
else if (version === presenceActivityVersion) presenceInterval = Math.min(presenceInterval * 2, POLL_TIMINGS.idleCeilingMs);
|
|
1706
|
+
for (const patch of patches) {
|
|
1707
|
+
if (closed) return;
|
|
1708
|
+
yield patch;
|
|
1709
|
+
}
|
|
1710
|
+
}
|
|
1622
1711
|
}
|
|
1623
1712
|
} finally {
|
|
1624
|
-
wakeQueue = null;
|
|
1625
|
-
unsubscribe?.();
|
|
1626
1713
|
pendingEvent?.catch(() => {});
|
|
1627
|
-
await
|
|
1714
|
+
await close();
|
|
1715
|
+
wakeQueue = null;
|
|
1628
1716
|
}
|
|
1629
1717
|
};
|
|
1630
|
-
|
|
1718
|
+
const iterator = outer();
|
|
1719
|
+
return { [Symbol.asyncIterator]() {
|
|
1720
|
+
const stream = {
|
|
1721
|
+
next: () => iterator.next(),
|
|
1722
|
+
async return() {
|
|
1723
|
+
await close();
|
|
1724
|
+
return iterator.return(void 0);
|
|
1725
|
+
},
|
|
1726
|
+
async throw(error) {
|
|
1727
|
+
await close();
|
|
1728
|
+
return iterator.throw(error);
|
|
1729
|
+
}
|
|
1730
|
+
};
|
|
1731
|
+
streamActivities.set(stream, activity);
|
|
1732
|
+
return stream;
|
|
1733
|
+
} };
|
|
1631
1734
|
};
|
|
1632
1735
|
const makeSession = (id, append, trigger) => ({
|
|
1633
1736
|
id,
|
|
@@ -2216,6 +2319,6 @@ function cloneInitial(initial) {
|
|
|
2216
2319
|
}
|
|
2217
2320
|
}
|
|
2218
2321
|
//#endregion
|
|
2219
|
-
export { parsePresenceSibling as a, sseResponse as i, deliverSchedulerAppend as n,
|
|
2322
|
+
export { parsePresenceSibling as a, sseResponse as i, deliverSchedulerAppend as n, setServerFetchHooks as r, createServer as t };
|
|
2220
2323
|
|
|
2221
|
-
//# sourceMappingURL=server-
|
|
2324
|
+
//# sourceMappingURL=server-Dkz2a84E.js.map
|