@livestore/sync-cf 0.4.0-dev.9 → 0.5.0-dev.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -8
- package/dist/.tsbuildinfo +1 -1
- package/dist/cf-worker/do/durable-object.d.ts +1 -1
- package/dist/cf-worker/do/durable-object.d.ts.map +1 -1
- package/dist/cf-worker/do/durable-object.js +36 -18
- package/dist/cf-worker/do/durable-object.js.map +1 -1
- package/dist/cf-worker/do/layer.d.ts +24 -20
- package/dist/cf-worker/do/layer.d.ts.map +1 -1
- package/dist/cf-worker/do/layer.js +57 -24
- package/dist/cf-worker/do/layer.js.map +1 -1
- package/dist/cf-worker/do/pull.d.ts +8 -3
- package/dist/cf-worker/do/pull.d.ts.map +1 -1
- package/dist/cf-worker/do/pull.js +26 -21
- package/dist/cf-worker/do/pull.js.map +1 -1
- package/dist/cf-worker/do/push.d.ts +20 -6
- package/dist/cf-worker/do/push.d.ts.map +1 -1
- package/dist/cf-worker/do/push.js +84 -56
- package/dist/cf-worker/do/push.js.map +1 -1
- package/dist/cf-worker/do/push.test.d.ts +2 -0
- package/dist/cf-worker/do/push.test.d.ts.map +1 -0
- package/dist/cf-worker/do/push.test.js +30 -0
- package/dist/cf-worker/do/push.test.js.map +1 -0
- package/dist/cf-worker/do/sqlite.d.ts +49 -52
- package/dist/cf-worker/do/sqlite.d.ts.map +1 -1
- package/dist/cf-worker/do/sqlite.js +14 -5
- package/dist/cf-worker/do/sqlite.js.map +1 -1
- package/dist/cf-worker/do/sync-storage.d.ts +15 -9
- package/dist/cf-worker/do/sync-storage.d.ts.map +1 -1
- package/dist/cf-worker/do/sync-storage.js +111 -25
- package/dist/cf-worker/do/sync-storage.js.map +1 -1
- package/dist/cf-worker/do/transport/do-rpc-server.d.ts +2 -2
- package/dist/cf-worker/do/transport/do-rpc-server.d.ts.map +1 -1
- package/dist/cf-worker/do/transport/do-rpc-server.js +31 -23
- package/dist/cf-worker/do/transport/do-rpc-server.js.map +1 -1
- package/dist/cf-worker/do/transport/http-rpc-server.d.ts +5 -3
- package/dist/cf-worker/do/transport/http-rpc-server.d.ts.map +1 -1
- package/dist/cf-worker/do/transport/http-rpc-server.js +28 -19
- package/dist/cf-worker/do/transport/http-rpc-server.js.map +1 -1
- package/dist/cf-worker/do/transport/ws-rpc-server.d.ts +3 -2
- package/dist/cf-worker/do/transport/ws-rpc-server.d.ts.map +1 -1
- package/dist/cf-worker/do/transport/ws-rpc-server.js +32 -10
- package/dist/cf-worker/do/transport/ws-rpc-server.js.map +1 -1
- package/dist/cf-worker/shared.d.ts +124 -34
- package/dist/cf-worker/shared.d.ts.map +1 -1
- package/dist/cf-worker/shared.js +52 -17
- package/dist/cf-worker/shared.js.map +1 -1
- package/dist/cf-worker/worker.d.ts +47 -39
- package/dist/cf-worker/worker.d.ts.map +1 -1
- package/dist/cf-worker/worker.js +54 -35
- package/dist/cf-worker/worker.js.map +1 -1
- package/dist/client/transport/do-rpc-client.d.ts +13 -4
- package/dist/client/transport/do-rpc-client.d.ts.map +1 -1
- package/dist/client/transport/do-rpc-client.js +74 -28
- package/dist/client/transport/do-rpc-client.js.map +1 -1
- package/dist/client/transport/http-rpc-client.d.ts +3 -3
- package/dist/client/transport/http-rpc-client.d.ts.map +1 -1
- package/dist/client/transport/http-rpc-client.js +51 -22
- package/dist/client/transport/http-rpc-client.js.map +1 -1
- package/dist/client/transport/ws-rpc-client.d.ts +4 -3
- package/dist/client/transport/ws-rpc-client.d.ts.map +1 -1
- package/dist/client/transport/ws-rpc-client.js +40 -22
- package/dist/client/transport/ws-rpc-client.js.map +1 -1
- package/dist/common/constants.d.ts +7 -0
- package/dist/common/constants.d.ts.map +1 -0
- package/dist/common/constants.js +17 -0
- package/dist/common/constants.js.map +1 -0
- package/dist/common/do-rpc-schema.d.ts +42 -43
- package/dist/common/do-rpc-schema.d.ts.map +1 -1
- package/dist/common/do-rpc-schema.js +5 -5
- package/dist/common/do-rpc-schema.js.map +1 -1
- package/dist/common/http-rpc-schema.d.ts +37 -38
- package/dist/common/http-rpc-schema.d.ts.map +1 -1
- package/dist/common/http-rpc-schema.js +7 -7
- package/dist/common/http-rpc-schema.js.map +1 -1
- package/dist/common/mod.d.ts +5 -3
- package/dist/common/mod.d.ts.map +1 -1
- package/dist/common/mod.js +4 -2
- package/dist/common/mod.js.map +1 -1
- package/dist/common/sync-message-types.d.ts +113 -130
- package/dist/common/sync-message-types.d.ts.map +1 -1
- package/dist/common/sync-message-types.js +29 -17
- package/dist/common/sync-message-types.js.map +1 -1
- package/dist/common/ws-rpc-schema.d.ts +34 -35
- package/dist/common/ws-rpc-schema.d.ts.map +1 -1
- package/dist/common/ws-rpc-schema.js +5 -5
- package/dist/common/ws-rpc-schema.js.map +1 -1
- package/package.json +57 -15
- package/src/cf-worker/do/durable-object.ts +59 -41
- package/src/cf-worker/do/layer.ts +153 -88
- package/src/cf-worker/do/pull.ts +48 -31
- package/src/cf-worker/do/push.test.ts +40 -0
- package/src/cf-worker/do/push.ts +163 -125
- package/src/cf-worker/do/sqlite.ts +15 -5
- package/src/cf-worker/do/sync-storage.ts +171 -38
- package/src/cf-worker/do/transport/do-rpc-server.ts +40 -40
- package/src/cf-worker/do/transport/http-rpc-server.ts +37 -20
- package/src/cf-worker/do/transport/ws-rpc-server.ts +44 -16
- package/src/cf-worker/shared.ts +152 -36
- package/src/cf-worker/worker.ts +110 -58
- package/src/client/transport/do-rpc-client.ts +106 -40
- package/src/client/transport/http-rpc-client.ts +74 -38
- package/src/client/transport/ws-rpc-client.ts +55 -29
- package/src/common/constants.ts +18 -0
- package/src/common/do-rpc-schema.ts +6 -5
- package/src/common/http-rpc-schema.ts +8 -7
- package/src/common/mod.ts +4 -3
- package/src/common/sync-message-types.ts +19 -19
- package/src/common/ws-rpc-schema.ts +6 -5
- package/dist/cf-worker/do/ws-chunking.d.ts +0 -22
- package/dist/cf-worker/do/ws-chunking.d.ts.map +0 -1
- package/dist/cf-worker/do/ws-chunking.js +0 -49
- package/dist/cf-worker/do/ws-chunking.js.map +0 -1
- package/src/cf-worker/do/ws-chunking.ts +0 -76
|
@@ -7,7 +7,7 @@ export type MakeDurableObjectClass = (options?: MakeDurableObjectClassOptions) =
|
|
|
7
7
|
};
|
|
8
8
|
/**
|
|
9
9
|
* Creates a Durable Object class for handling WebSocket-based sync.
|
|
10
|
-
* A sync
|
|
10
|
+
* A sync Durable Object is uniquely scoped to a specific `storeId`.
|
|
11
11
|
*
|
|
12
12
|
* The sync DO supports 3 transport modes:
|
|
13
13
|
* - HTTP JSON-RPC
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"durable-object.d.ts","sourceRoot":"","sources":["../../../src/cf-worker/do/durable-object.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"durable-object.d.ts","sourceRoot":"","sources":["../../../src/cf-worker/do/durable-object.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,OAAO,EAAkC,MAAM,sBAAsB,CAAA;AAcnF,OAAO,EACL,KAAK,GAAG,EAER,KAAK,6BAA6B,EAElC,KAAK,uBAAuB,EAE7B,MAAM,cAAc,CAAA;AAmBrB,MAAM,MAAM,OAAO,GAAG,OAAO,CAAC,kBAAkB,CAAA;AAChD,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI,OAAO,CAAC,aAAa,GAAG,CAAC,CAAA;AAEnD,MAAM,MAAM,sBAAsB,GAAG,CAAC,OAAO,CAAC,EAAE,6BAA6B,KAAK;IAChF,KAAK,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,GAAG,QAAQ,CAAC,uBAAuB,CAAC,CAAA;CAChE,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,eAAO,MAAM,iBAAiB,EAAE,sBAuK/B,CAAA"}
|
|
@@ -2,16 +2,21 @@
|
|
|
2
2
|
import { DurableObject } from 'cloudflare:workers';
|
|
3
3
|
import { setupDurableObjectWebSocketRpc } from '@livestore/common-cf';
|
|
4
4
|
import { CfDeclare } from '@livestore/common-cf/declare';
|
|
5
|
-
import { Effect, FetchHttpClient, Layer, Logger,
|
|
6
|
-
import { matchSyncRequest, WebSocketAttachmentSchema, } from "../shared.js";
|
|
7
|
-
import
|
|
5
|
+
import { Effect, FetchHttpClient, Layer, Logger, Otlp, References, RpcMessage, Schema, } from '@livestore/utils/effect';
|
|
6
|
+
import { extractForwardedHeaders, matchSyncRequest, WebSocketAttachmentSchema, } from "../shared.js";
|
|
7
|
+
import * as DoCtx from "./layer.js";
|
|
8
8
|
import { createDoRpcHandler } from "./transport/do-rpc-server.js";
|
|
9
9
|
import { createHttpRpcHandler } from "./transport/http-rpc-server.js";
|
|
10
10
|
import { makeRpcServer } from "./transport/ws-rpc-server.js";
|
|
11
|
-
const
|
|
11
|
+
const Response = CfDeclare.Response;
|
|
12
|
+
const WebSocketPair = CfDeclare.WebSocketPair;
|
|
13
|
+
const WebSocketRequestResponsePair = CfDeclare.WebSocketRequestResponsePair;
|
|
14
|
+
/** Module-scoped JSON encoder; keeping the sync codec out of Effect generators avoids `schemaSyncInEffect`. */
|
|
15
|
+
const jsonStringify = Schema.encodeSync(Schema.fromJsonString(Schema.Unknown));
|
|
16
|
+
const DurableObjectBase = DurableObject;
|
|
12
17
|
/**
|
|
13
18
|
* Creates a Durable Object class for handling WebSocket-based sync.
|
|
14
|
-
* A sync
|
|
19
|
+
* A sync Durable Object is uniquely scoped to a specific `storeId`.
|
|
15
20
|
*
|
|
16
21
|
* The sync DO supports 3 transport modes:
|
|
17
22
|
* - HTTP JSON-RPC
|
|
@@ -47,9 +52,8 @@ const DurableObjectBase = (DurableObject);
|
|
|
47
52
|
*/
|
|
48
53
|
export const makeDurableObject = (options) => {
|
|
49
54
|
const enabledTransports = options?.enabledTransports ?? new Set(['http', 'ws', 'do-rpc']);
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
? Otlp.layer({
|
|
55
|
+
const Observability = options?.otel?.baseUrl !== undefined
|
|
56
|
+
? Otlp.layerJson({
|
|
53
57
|
baseUrl: options.otel.baseUrl,
|
|
54
58
|
tracerExportInterval: 50,
|
|
55
59
|
resource: {
|
|
@@ -63,7 +67,7 @@ export const makeDurableObject = (options) => {
|
|
|
63
67
|
super(ctx, env);
|
|
64
68
|
const WebSocketRpcServerLive = makeRpcServer({ doSelf: this, doOptions: options });
|
|
65
69
|
// This registers the `webSocketMessage` and `webSocketClose` handlers
|
|
66
|
-
if (enabledTransports.has('ws')) {
|
|
70
|
+
if (enabledTransports.has('ws') === true) {
|
|
67
71
|
setupDurableObjectWebSocketRpc({
|
|
68
72
|
doSelf: this,
|
|
69
73
|
rpcLayer: WebSocketRpcServerLive,
|
|
@@ -74,7 +78,7 @@ export const makeDurableObject = (options) => {
|
|
|
74
78
|
if (request._tag === 'Request' && request.tag === 'SyncWsRpc.Pull') {
|
|
75
79
|
// Is Pull request: add requestId to pullRequestIds
|
|
76
80
|
const attachment = ws.deserializeAttachment();
|
|
77
|
-
const { pullRequestIds, ...rest } = Schema.
|
|
81
|
+
const { pullRequestIds, ...rest } = Schema.decodeUnknownSync(WebSocketAttachmentSchema)(attachment);
|
|
78
82
|
ws.serializeAttachment(Schema.encodeSync(WebSocketAttachmentSchema)({
|
|
79
83
|
...rest,
|
|
80
84
|
pullRequestIds: [...pullRequestIds, request.id],
|
|
@@ -83,7 +87,7 @@ export const makeDurableObject = (options) => {
|
|
|
83
87
|
else if (request._tag === 'Interrupt') {
|
|
84
88
|
// Is Interrupt request: remove requestId from pullRequestIds
|
|
85
89
|
const attachment = ws.deserializeAttachment();
|
|
86
|
-
const { pullRequestIds, ...rest } = Schema.
|
|
90
|
+
const { pullRequestIds, ...rest } = Schema.decodeUnknownSync(WebSocketAttachmentSchema)(attachment);
|
|
87
91
|
ws.serializeAttachment(Schema.encodeSync(WebSocketAttachmentSchema)({
|
|
88
92
|
...rest,
|
|
89
93
|
pullRequestIds: pullRequestIds.filter((id) => id !== request.requestId),
|
|
@@ -95,7 +99,7 @@ export const makeDurableObject = (options) => {
|
|
|
95
99
|
});
|
|
96
100
|
}
|
|
97
101
|
}
|
|
98
|
-
fetch = async (request) => Effect.gen(this, function* () {
|
|
102
|
+
fetch = async (request) => Effect.gen({ self: this }, function* () {
|
|
99
103
|
const searchParams = matchSyncRequest(request);
|
|
100
104
|
if (searchParams === undefined) {
|
|
101
105
|
throw new Error('No search params found in request URL');
|
|
@@ -104,17 +108,29 @@ export const makeDurableObject = (options) => {
|
|
|
104
108
|
if (enabledTransports.has(transport) === false) {
|
|
105
109
|
throw new Error(`Transport ${transport} is not enabled (based on \`options.enabledTransports\`)`);
|
|
106
110
|
}
|
|
111
|
+
// Extract headers to forward based on configuration (available for all transports)
|
|
112
|
+
const headers = extractForwardedHeaders(request, options?.forwardHeaders);
|
|
107
113
|
if (transport === 'http') {
|
|
108
|
-
return yield* this.handleHttp(request);
|
|
114
|
+
return yield* this.handleHttp(request, headers);
|
|
109
115
|
}
|
|
110
116
|
if (transport === 'ws') {
|
|
111
117
|
const { 0: client, 1: server } = new WebSocketPair();
|
|
112
118
|
// Since we're using websocket hibernation, we need to remember the storeId for subsequent `webSocketMessage` calls
|
|
113
|
-
|
|
119
|
+
// Also store forwarded headers so they're available after hibernation resume
|
|
120
|
+
// Encoding known-valid domain data: an encode failure is an invariant violation (a defect),
|
|
121
|
+
// so `Effect.orDie` is the correct modeling. serializeAttachment takes the value synchronously,
|
|
122
|
+
// so resolve the encoded value first, then pass it in.
|
|
123
|
+
const attachment = yield* Schema.encodeEffect(WebSocketAttachmentSchema)({
|
|
124
|
+
storeId,
|
|
125
|
+
payload,
|
|
126
|
+
pullRequestIds: [],
|
|
127
|
+
headers,
|
|
128
|
+
}).pipe(Effect.orDie);
|
|
129
|
+
server.serializeAttachment(attachment);
|
|
114
130
|
// See https://developers.cloudflare.com/durable-objects/examples/websocket-hibernation-server
|
|
115
131
|
this.ctx.acceptWebSocket(server);
|
|
116
132
|
// Ping requests are sent by Effect RPC internally
|
|
117
|
-
this.ctx.setWebSocketAutoResponse(new WebSocketRequestResponsePair(
|
|
133
|
+
this.ctx.setWebSocketAutoResponse(new WebSocketRequestResponsePair(jsonStringify(RpcMessage.constPing), jsonStringify(RpcMessage.constPong)));
|
|
118
134
|
return new Response(null, {
|
|
119
135
|
status: 101,
|
|
120
136
|
webSocket: client,
|
|
@@ -126,7 +142,7 @@ export const makeDurableObject = (options) => {
|
|
|
126
142
|
statusText: 'Bad Request',
|
|
127
143
|
});
|
|
128
144
|
}).pipe(Effect.tapCauseLogPretty, // Also log errors to console before catching them
|
|
129
|
-
Effect.
|
|
145
|
+
Effect.catchCause((cause) => Effect.succeed(new Response('Error', { status: 500, statusText: cause.toString() }))), Effect.withSpan('@livestore/sync-cf:durable-object:fetch'), Effect.provide(DoCtx.layer({ doSelf: this, doOptions: options, from: request })), this.runEffectAsPromise);
|
|
130
146
|
/**
|
|
131
147
|
* Handles DO <-> DO RPC calls
|
|
132
148
|
*/
|
|
@@ -141,10 +157,12 @@ export const makeDurableObject = (options) => {
|
|
|
141
157
|
*
|
|
142
158
|
* Requires the `enable_request_signal` compatibility flag to properly support `pull` streaming responses
|
|
143
159
|
*/
|
|
144
|
-
handleHttp = (request) => createHttpRpcHandler({
|
|
160
|
+
handleHttp = (request, forwardedHeaders) => createHttpRpcHandler({
|
|
145
161
|
request,
|
|
162
|
+
...(options?.http?.responseHeaders !== undefined ? { responseHeaders: options.http.responseHeaders } : {}),
|
|
163
|
+
...(forwardedHeaders !== undefined ? { forwardedHeaders } : {}),
|
|
146
164
|
}).pipe(Effect.withSpan('@livestore/sync-cf:durable-object:handleHttp'));
|
|
147
|
-
runEffectAsPromise = (effect) => effect.pipe(Effect.tapCauseLogPretty,
|
|
165
|
+
runEffectAsPromise = (effect) => effect.pipe(Effect.tapCauseLogPretty, Effect.annotateLogs({ thread: 'SyncDo' }), Effect.provide(Layer.mergeAll(Observability, Logger.layer([Logger.consoleStructured]), Layer.succeed(References.MinimumLogLevel, 'Debug'))), Effect.scoped, Effect.runPromise);
|
|
148
166
|
};
|
|
149
167
|
};
|
|
150
168
|
//# sourceMappingURL=durable-object.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"durable-object.js","sourceRoot":"","sources":["../../../src/cf-worker/do/durable-object.ts"],"names":[],"mappings":"AAAA,mDAAmD;AAEnD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;
|
|
1
|
+
{"version":3,"file":"durable-object.js","sourceRoot":"","sources":["../../../src/cf-worker/do/durable-object.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { EventSequenceNumber } from '@livestore/common/schema';
|
|
1
|
+
import { UnknownError } from '@livestore/common';
|
|
3
2
|
import type { CfTypes } from '@livestore/common-cf';
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
6
|
-
|
|
3
|
+
import { EventSequenceNumber } from '@livestore/common/schema';
|
|
4
|
+
import { Context, Effect, Layer, Semaphore } from '@livestore/utils/effect';
|
|
5
|
+
import type { Env, MakeDurableObjectClassOptions } from '../shared.ts';
|
|
6
|
+
import { type SyncStorage } from './sync-storage.ts';
|
|
7
|
+
export interface Options {
|
|
7
8
|
doSelf: CfTypes.DurableObject & {
|
|
8
9
|
ctx: CfTypes.DurableObjectState;
|
|
9
10
|
env: Env;
|
|
@@ -13,22 +14,25 @@ export interface DoCtxInput {
|
|
|
13
14
|
storeId: string;
|
|
14
15
|
};
|
|
15
16
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}
|
|
17
|
+
export type DoCtxInput = Options;
|
|
18
|
+
export interface Service {
|
|
19
|
+
readonly storeId: string;
|
|
20
|
+
readonly backendId: string;
|
|
21
|
+
readonly currentHeadRef: {
|
|
22
|
+
current: EventSequenceNumber.Global.Type;
|
|
23
|
+
};
|
|
24
|
+
readonly updateCurrentHead: (currentHead: EventSequenceNumber.Global.Type) => void;
|
|
25
|
+
/** Serializes push admission across concurrent RPC fibers for this Durable Object instance. */
|
|
26
|
+
readonly pushSemaphore: Semaphore.Semaphore;
|
|
27
|
+
readonly storage: SyncStorage;
|
|
28
|
+
readonly doOptions: MakeDurableObjectClassOptions | undefined;
|
|
29
|
+
readonly env: Env;
|
|
30
|
+
readonly ctx: CfTypes.DurableObjectState;
|
|
31
|
+
}
|
|
32
|
+
declare const DoCtx_base: Context.ServiceClass<DoCtx, "@livestore/sync-cf/DoCtx", Service>;
|
|
31
33
|
export declare class DoCtx extends DoCtx_base {
|
|
32
34
|
}
|
|
35
|
+
export declare const make: (args_0: Options) => Effect.Effect<Service, UnknownError, never>;
|
|
36
|
+
export declare const layer: (options: Options) => Layer.Layer<DoCtx, UnknownError, never>;
|
|
33
37
|
export {};
|
|
34
38
|
//# sourceMappingURL=layer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layer.d.ts","sourceRoot":"","sources":["../../../src/cf-worker/do/layer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"layer.d.ts","sourceRoot":"","sources":["../../../src/cf-worker/do/layer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAChD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAA;AACnD,OAAO,EAAE,mBAAmB,EAAS,MAAM,0BAA0B,CAAA;AAErE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAa,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAGtF,OAAO,KAAK,EAAE,GAAG,EAAE,6BAA6B,EAAE,MAAM,cAAc,CAAA;AAEtE,OAAO,EAAmC,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAKrF,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE,OAAO,CAAC,aAAa,GAAG;QAC9B,GAAG,EAAE,OAAO,CAAC,kBAAkB,CAAA;QAC/B,GAAG,EAAE,GAAG,CAAA;KACT,CAAA;IACD,SAAS,EAAE,6BAA6B,GAAG,SAAS,CAAA;IACpD,IAAI,EAAE,OAAO,CAAC,OAAO,GAAG;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;CAC5C;AAED,MAAM,MAAM,UAAU,GAAG,OAAO,CAAA;AAEhC,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,cAAc,EAAE;QAAE,OAAO,EAAE,mBAAmB,CAAC,MAAM,CAAC,IAAI,CAAA;KAAE,CAAA;IACrE,QAAQ,CAAC,iBAAiB,EAAE,CAAC,WAAW,EAAE,mBAAmB,CAAC,MAAM,CAAC,IAAI,KAAK,IAAI,CAAA;IAClF,+FAA+F;IAC/F,QAAQ,CAAC,aAAa,EAAE,SAAS,CAAC,SAAS,CAAA;IAC3C,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAA;IAC7B,QAAQ,CAAC,SAAS,EAAE,6BAA6B,GAAG,SAAS,CAAA;IAC7D,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAA;IACjB,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC,kBAAkB,CAAA;CACzC;;AAED,qBAAa,KAAM,SAAQ,UAA6D;CAAG;AAO3F,eAAO,MAAM,IAAI,kEAqGhB,CAAA;AAED,eAAO,MAAM,KAAK,GAAI,SAAS,OAAO,4CAAuC,CAAA"}
|
|
@@ -1,30 +1,48 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { UnknownError } from '@livestore/common';
|
|
2
2
|
import { EventSequenceNumber, State } from '@livestore/common/schema';
|
|
3
3
|
import { shouldNeverHappen } from '@livestore/utils';
|
|
4
|
-
import { Effect, Predicate } from '@livestore/utils/effect';
|
|
4
|
+
import { Context, Effect, Layer, Predicate, Semaphore } from '@livestore/utils/effect';
|
|
5
5
|
import { nanoid } from '@livestore/utils/nanoid';
|
|
6
6
|
import { contextTable, eventlogTable } from "./sqlite.js";
|
|
7
7
|
import { makeStorage } from "./sync-storage.js";
|
|
8
8
|
const CacheSymbol = Symbol('Cache');
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
const InitializationSemaphoreSymbol = Symbol('InitializationSemaphore');
|
|
10
|
+
export class DoCtx extends Context.Service()('@livestore/sync-cf/DoCtx') {
|
|
11
|
+
}
|
|
12
|
+
export const make = Effect.fn(function* ({ doSelf, doOptions, from }) {
|
|
13
|
+
const cacheHost = doSelf;
|
|
14
|
+
if (cacheHost[CacheSymbol] !== undefined) {
|
|
15
|
+
return DoCtx.of(cacheHost[CacheSymbol]);
|
|
16
|
+
}
|
|
17
|
+
// Request layers can be constructed concurrently during the first RPCs to a DO.
|
|
18
|
+
// Install this lock synchronously so every contender shares the same initializer.
|
|
19
|
+
const initializationSemaphore = cacheHost[InitializationSemaphoreSymbol] ?? Semaphore.makeUnsafe(1);
|
|
20
|
+
cacheHost[InitializationSemaphoreSymbol] = initializationSemaphore;
|
|
21
|
+
return yield* initializationSemaphore.withPermits(1)(Effect.gen(function* () {
|
|
22
|
+
if (cacheHost[CacheSymbol] !== undefined) {
|
|
23
|
+
return DoCtx.of(cacheHost[CacheSymbol]);
|
|
13
24
|
}
|
|
14
25
|
const getStoreId = (from) => {
|
|
15
|
-
if (Predicate.hasProperty(from, 'url')) {
|
|
26
|
+
if (Predicate.hasProperty(from, 'url') === true) {
|
|
16
27
|
const url = new URL(from.url);
|
|
17
28
|
return (url.searchParams.get('storeId') ?? shouldNeverHappen(`No storeId provided in request URL search params`));
|
|
18
29
|
}
|
|
19
30
|
return from.storeId;
|
|
20
31
|
};
|
|
21
32
|
const storeId = getStoreId(from);
|
|
22
|
-
const
|
|
33
|
+
const engine = yield* resolveStorageEngine(doOptions?.storage, doSelf.env);
|
|
34
|
+
const storage = makeStorage(doSelf.ctx, storeId, engine);
|
|
23
35
|
// Initialize database tables
|
|
24
36
|
{
|
|
25
37
|
const colSpec = State.SQLite.makeColumnSpec(eventlogTable.sqliteDef.ast);
|
|
26
|
-
|
|
27
|
-
|
|
38
|
+
if (engine._tag === 'd1') {
|
|
39
|
+
// D1 database is async, so we need to use a promise
|
|
40
|
+
yield* Effect.promise(() => engine.db.exec(`CREATE TABLE IF NOT EXISTS "${storage.dbName}" (${colSpec}) strict`));
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
// DO SQLite table lives in Durable Object storage
|
|
44
|
+
doSelf.ctx.storage.sql.exec(`CREATE TABLE IF NOT EXISTS "${storage.dbName}" (${colSpec}) strict`);
|
|
45
|
+
}
|
|
28
46
|
}
|
|
29
47
|
{
|
|
30
48
|
const colSpec = State.SQLite.makeColumnSpec(contextTable.sqliteDef.ast);
|
|
@@ -33,36 +51,51 @@ export class DoCtx extends Effect.Service()('DoCtx', {
|
|
|
33
51
|
const storageRow = doSelf.ctx.storage.sql
|
|
34
52
|
.exec(`SELECT * FROM "${contextTable.sqliteDef.name}" WHERE storeId = ?`, storeId)
|
|
35
53
|
.toArray()[0];
|
|
36
|
-
const currentHeadRef = { current: storageRow?.currentHead ?? EventSequenceNumber.ROOT.global };
|
|
37
|
-
|
|
38
|
-
//
|
|
54
|
+
const currentHeadRef = { current: storageRow?.currentHead ?? EventSequenceNumber.Client.ROOT.global };
|
|
55
|
+
const pushSemaphore = yield* Semaphore.make(1);
|
|
56
|
+
// TODO: Reconcile this persisted head with the event log's highest sequence number.
|
|
57
|
+
// D1 event batches and this DO-local context row cannot be updated atomically, so a
|
|
58
|
+
// failure between those writes can leave push admission using a stale head after restart.
|
|
59
|
+
// Should be the same backendId for lifetime of the Durable Object
|
|
39
60
|
const backendId = storageRow?.backendId ?? nanoid();
|
|
40
61
|
const updateCurrentHead = (currentHead) => {
|
|
41
62
|
doSelf.ctx.storage.sql.exec(`INSERT OR REPLACE INTO "${contextTable.sqliteDef.name}" (storeId, currentHead, backendId) VALUES (?, ?, ?)`, storeId, currentHead, backendId);
|
|
42
63
|
currentHeadRef.current = currentHead;
|
|
43
|
-
// I still don't know why we need to re-assign this ref to the `doSelf` object but somehow this seems to be needed 😵💫
|
|
44
|
-
// @ts-expect-error
|
|
45
|
-
doSelf[CacheSymbol].currentHeadRef = { current: currentHead };
|
|
46
64
|
};
|
|
47
|
-
const rpcSubscriptions = new Map();
|
|
48
65
|
const storageCache = {
|
|
49
66
|
storeId,
|
|
50
67
|
backendId,
|
|
51
68
|
currentHeadRef,
|
|
52
69
|
updateCurrentHead,
|
|
70
|
+
pushSemaphore,
|
|
53
71
|
storage,
|
|
54
72
|
doOptions,
|
|
55
73
|
env: doSelf.env,
|
|
56
74
|
ctx: doSelf.ctx,
|
|
57
|
-
rpcSubscriptions,
|
|
58
75
|
};
|
|
59
|
-
|
|
76
|
+
cacheHost[CacheSymbol] = storageCache;
|
|
60
77
|
// Set initial current head to root
|
|
61
78
|
if (storageRow === undefined) {
|
|
62
|
-
updateCurrentHead(EventSequenceNumber.ROOT.global);
|
|
79
|
+
updateCurrentHead(EventSequenceNumber.Client.ROOT.global);
|
|
63
80
|
}
|
|
64
|
-
return storageCache;
|
|
65
|
-
}
|
|
66
|
-
})
|
|
67
|
-
|
|
81
|
+
return DoCtx.of(storageCache);
|
|
82
|
+
}));
|
|
83
|
+
}, UnknownError.mapToUnknownError, Effect.withSpan('@livestore/sync-cf:durable-object:makeDoCtx'));
|
|
84
|
+
export const layer = (options) => Layer.effect(DoCtx, make(options));
|
|
85
|
+
/** Resolves storage configuration into the concrete database handle used at runtime. */
|
|
86
|
+
const resolveStorageEngine = Effect.fn(function* (storageOption, env) {
|
|
87
|
+
if (storageOption === undefined || storageOption._tag === 'do-sqlite') {
|
|
88
|
+
return { _tag: 'do-sqlite' };
|
|
89
|
+
}
|
|
90
|
+
if (storageOption._tag === 'd1') {
|
|
91
|
+
const db = env[storageOption.binding];
|
|
92
|
+
if (db === undefined) {
|
|
93
|
+
return yield* UnknownError.make({
|
|
94
|
+
cause: new Error(`D1 binding '${storageOption.binding}' not found on env`),
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
return { _tag: 'd1', db };
|
|
98
|
+
}
|
|
99
|
+
return shouldNeverHappen(`Invalid storage engine`, storageOption);
|
|
100
|
+
});
|
|
68
101
|
//# sourceMappingURL=layer.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layer.js","sourceRoot":"","sources":["../../../src/cf-worker/do/layer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"layer.js","sourceRoot":"","sources":["../../../src/cf-worker/do/layer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAEhD,OAAO,EAAE,mBAAmB,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAA;AACrE,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AACtF,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAGhD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AACzD,OAAO,EAAE,WAAW,EAAwC,MAAM,mBAAmB,CAAA;AAErF,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,CAAC,CAAA;AACnC,MAAM,6BAA6B,GAAG,MAAM,CAAC,yBAAyB,CAAC,CAAA;AA0BvE,MAAM,OAAO,KAAM,SAAQ,OAAO,CAAC,OAAO,EAAkB,CAAC,0BAA0B,CAAC;CAAG;AAO3F,MAAM,CAAC,MAAM,IAAI,GAAG,MAAM,CAAC,EAAE,CAC3B,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAW;IAC7C,MAAM,SAAS,GAAG,MAAgC,CAAA;IAClD,IAAI,SAAS,CAAC,WAAW,CAAC,KAAK,SAAS,EAAE,CAAC;QACzC,OAAO,KAAK,CAAC,EAAE,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAA;IACzC,CAAC;IAED,gFAAgF;IAChF,kFAAkF;IAClF,MAAM,uBAAuB,GAAG,SAAS,CAAC,6BAA6B,CAAC,IAAI,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,CAAA;IACnG,SAAS,CAAC,6BAA6B,CAAC,GAAG,uBAAuB,CAAA;IAElE,OAAO,KAAK,CAAC,CAAC,uBAAuB,CAAC,WAAW,CAAC,CAAC,CAAC,CAClD,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAClB,IAAI,SAAS,CAAC,WAAW,CAAC,KAAK,SAAS,EAAE,CAAC;YACzC,OAAO,KAAK,CAAC,EAAE,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAA;QACzC,CAAC;QAED,MAAM,UAAU,GAAG,CAAC,IAA2C,EAAE,EAAE;YACjE,IAAI,SAAS,CAAC,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC;gBAChD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;gBAC7B,OAAO,CACL,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,iBAAiB,CAAC,kDAAkD,CAAC,CACzG,CAAA;YACH,CAAC;YACD,OAAO,IAAI,CAAC,OAAO,CAAA;QACrB,CAAC,CAAA;QAED,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,CAAC,CAAA;QAChC,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,oBAAoB,CAAC,SAAS,EAAE,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC,CAAA;QAE1E,MAAM,OAAO,GAAG,WAAW,CAAC,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,CAAA;QAExD,6BAA6B;QAC7B,CAAC;YACC,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,cAAc,CAAC,aAAa,CAAC,SAAS,CAAC,GAAG,CAAC,CAAA;YACxE,IAAI,MAAM,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;gBACzB,oDAAoD;gBACpD,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,CACzB,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,+BAA+B,OAAO,CAAC,MAAM,MAAM,OAAO,UAAU,CAAC,CACrF,CAAA;YACH,CAAC;iBAAM,CAAC;gBACN,kDAAkD;gBAClD,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,+BAA+B,OAAO,CAAC,MAAM,MAAM,OAAO,UAAU,CAAC,CAAA;YACnG,CAAC;QACH,CAAC;QACD,CAAC;YACC,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,cAAc,CAAC,YAAY,CAAC,SAAS,CAAC,GAAG,CAAC,CAAA;YACvE,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,+BAA+B,YAAY,CAAC,SAAS,CAAC,IAAI,MAAM,OAAO,UAAU,CAAC,CAAA;QAChH,CAAC;QAED,MAAM,UAAU,GAAG,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG;aACtC,IAAI,CAAC,kBAAkB,YAAY,CAAC,SAAS,CAAC,IAAI,qBAAqB,EAAE,OAAO,CAAC;aACjF,OAAO,EAAE,CAAC,CAAC,CAAmD,CAAA;QAEjE,MAAM,cAAc,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,IAAI,mBAAmB,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAA;QACrG,MAAM,aAAa,GAAG,KAAK,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QAE9C,oFAAoF;QACpF,oFAAoF;QACpF,0FAA0F;QAE1F,kEAAkE;QAClE,MAAM,SAAS,GAAG,UAAU,EAAE,SAAS,IAAI,MAAM,EAAE,CAAA;QAEnD,MAAM,iBAAiB,GAAG,CAAC,WAA4C,EAAE,EAAE;YACzE,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CACzB,2BAA2B,YAAY,CAAC,SAAS,CAAC,IAAI,sDAAsD,EAC5G,OAAO,EACP,WAAW,EACX,SAAS,CACV,CAAA;YAED,cAAc,CAAC,OAAO,GAAG,WAAW,CAAA;QACtC,CAAC,CAAA;QAED,MAAM,YAAY,GAAG;YACnB,OAAO;YACP,SAAS;YACT,cAAc;YACd,iBAAiB;YACjB,aAAa;YACb,OAAO;YACP,SAAS;YACT,GAAG,EAAE,MAAM,CAAC,GAAG;YACf,GAAG,EAAE,MAAM,CAAC,GAAG;SAChB,CAAA;QAED,SAAS,CAAC,WAAW,CAAC,GAAG,YAAY,CAAA;QAErC,mCAAmC;QACnC,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC7B,iBAAiB,CAAC,mBAAmB,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QAC3D,CAAC;QAED,OAAO,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,CAAA;IAC/B,CAAC,CAAC,CACH,CAAA;AACH,CAAC,EACD,YAAY,CAAC,iBAAiB,EAC9B,MAAM,CAAC,QAAQ,CAAC,6CAA6C,CAAC,CAC/D,CAAA;AAED,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,OAAgB,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAA;AAE7E,wFAAwF;AACxF,MAAM,oBAAoB,GAAG,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,EAC9C,aAAuD,EACvD,GAAQ;IAER,IAAI,aAAa,KAAK,SAAS,IAAI,aAAa,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;QACtE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,CAAA;IAC9B,CAAC;IAED,IAAI,aAAa,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;QAChC,MAAM,EAAE,GAAI,GAAsD,CAAC,aAAa,CAAC,OAAO,CAAC,CAAA;QACzF,IAAI,EAAE,KAAK,SAAS,EAAE,CAAC;YACrB,OAAO,KAAK,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC;gBAC9B,KAAK,EAAE,IAAI,KAAK,CAAC,eAAe,aAAa,CAAC,OAAO,oBAAoB,CAAC;aAC3E,CAAC,CAAA;QACJ,CAAC;QAED,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAA;IAC3B,CAAC;IAED,OAAO,iBAAiB,CAAC,wBAAwB,EAAE,aAAa,CAAC,CAAA;AACnE,CAAC,CAAC,CAAA"}
|
|
@@ -1,6 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BackendIdMismatchError, UnknownError } from '@livestore/common';
|
|
2
2
|
import { Schema, Stream } from '@livestore/utils/effect';
|
|
3
3
|
import { SyncMessage } from '../../common/mod.ts';
|
|
4
|
-
import {
|
|
5
|
-
|
|
4
|
+
import type { ForwardedHeaders } from '../shared.ts';
|
|
5
|
+
import * as DoCtx from './layer.ts';
|
|
6
|
+
export declare const makeEndingPullStream: ({ req, payload, headers, }: {
|
|
7
|
+
req: SyncMessage.PullRequest;
|
|
8
|
+
payload: Schema.Json | undefined;
|
|
9
|
+
headers: ForwardedHeaders | undefined;
|
|
10
|
+
}) => Stream.Stream<SyncMessage.PullResponse, UnknownError | BackendIdMismatchError, DoCtx.DoCtx>;
|
|
6
11
|
//# sourceMappingURL=pull.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pull.d.ts","sourceRoot":"","sources":["../../../src/cf-worker/do/pull.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"pull.d.ts","sourceRoot":"","sources":["../../../src/cf-worker/do/pull.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAe,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAErF,OAAO,EAAkB,MAAM,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAGxE,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AACpD,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AAanC,eAAO,MAAM,oBAAoB,GAAI,4BAIlC;IACD,GAAG,EAAE,WAAW,CAAC,WAAW,CAAA;IAC5B,OAAO,EAAE,MAAM,CAAC,IAAI,GAAG,SAAS,CAAA;IAChC,OAAO,EAAE,gBAAgB,GAAG,SAAS,CAAA;CACtC,KAAG,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,YAAY,EAAE,YAAY,GAAG,sBAAsB,EAAE,KAAK,CAAC,KAAK,CAiE3F,CAAA"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { BackendIdMismatchError,
|
|
2
|
-
import {
|
|
1
|
+
import { BackendIdMismatchError, SyncBackend, UnknownError } from '@livestore/common';
|
|
2
|
+
import { splitArrayBySize } from '@livestore/common/sync';
|
|
3
|
+
import { Effect, Option, Schema, Stream } from '@livestore/utils/effect';
|
|
4
|
+
import { MAX_PULL_EVENTS_PER_MESSAGE, MAX_WS_MESSAGE_BYTES } from "../../common/constants.js";
|
|
3
5
|
import { SyncMessage } from "../../common/mod.js";
|
|
4
|
-
import
|
|
5
|
-
import { DoCtx } from "./layer.js";
|
|
6
|
-
import { splitChunkBySize } from "./ws-chunking.js";
|
|
6
|
+
import * as DoCtx from "./layer.js";
|
|
7
7
|
const encodePullResponse = Schema.encodeSync(SyncMessage.PullResponse);
|
|
8
8
|
// Notes on stream handling:
|
|
9
9
|
// We're intentionally closing the stream once we've read all existing events
|
|
@@ -14,34 +14,39 @@ const encodePullResponse = Schema.encodeSync(SyncMessage.PullResponse);
|
|
|
14
14
|
// DO RPC:
|
|
15
15
|
// - Further chunks will be emitted manually in `push.ts`
|
|
16
16
|
// - If the client sends a `Interrupt` RPC message, TODO
|
|
17
|
-
export const makeEndingPullStream = (req, payload) => Effect.gen(function* () {
|
|
18
|
-
const { doOptions, backendId, storeId, storage } = yield* DoCtx;
|
|
19
|
-
if (doOptions?.onPull) {
|
|
20
|
-
yield* Effect.
|
|
17
|
+
export const makeEndingPullStream = ({ req, payload, headers, }) => Effect.gen(function* () {
|
|
18
|
+
const { doOptions, backendId, storeId, storage } = yield* DoCtx.DoCtx;
|
|
19
|
+
if (doOptions?.onPull !== undefined) {
|
|
20
|
+
yield* Effect.trySyncOrPromiseOrEffect(() => doOptions.onPull(req, {
|
|
21
|
+
storeId,
|
|
22
|
+
...(payload !== undefined ? { payload } : {}),
|
|
23
|
+
...(headers !== undefined ? { headers } : {}),
|
|
24
|
+
})).pipe(UnknownError.mapToUnknownError);
|
|
21
25
|
}
|
|
22
26
|
if (req.cursor._tag === 'Some' && req.cursor.value.backendId !== backendId) {
|
|
23
27
|
return yield* new BackendIdMismatchError({ expected: backendId, received: req.cursor.value.backendId });
|
|
24
28
|
}
|
|
25
29
|
const { stream: storedEvents, total } = yield* storage.getEvents(Option.getOrUndefined(req.cursor)?.eventSequenceNumber);
|
|
26
|
-
return storedEvents.pipe(Stream.
|
|
30
|
+
return storedEvents.pipe(Stream.mapArrayEffect(splitArrayBySize({
|
|
27
31
|
maxItems: MAX_PULL_EVENTS_PER_MESSAGE,
|
|
28
32
|
maxBytes: MAX_WS_MESSAGE_BYTES,
|
|
29
33
|
encode: (batch) => encodePullResponse(SyncMessage.PullResponse.make({ batch, pageInfo: SyncBackend.pageInfoNoMore, backendId })),
|
|
30
|
-
})), Stream.mapAccum(total, (remaining,
|
|
31
|
-
const
|
|
32
|
-
const nextRemaining = Math.max(0, remaining - asArray.length);
|
|
34
|
+
})), Stream.mapAccum(() => total, (remaining, array) => {
|
|
35
|
+
const nextRemaining = Math.max(0, remaining - array.length);
|
|
33
36
|
return [
|
|
34
37
|
nextRemaining,
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
[
|
|
39
|
+
SyncMessage.PullResponse.make({
|
|
40
|
+
batch: array,
|
|
41
|
+
pageInfo: nextRemaining > 0 ? SyncBackend.pageInfoMoreKnown(nextRemaining) : SyncBackend.pageInfoNoMore,
|
|
42
|
+
backendId,
|
|
43
|
+
}),
|
|
44
|
+
],
|
|
40
45
|
];
|
|
41
46
|
}), Stream.tap(Effect.fn(function* (res) {
|
|
42
|
-
if (doOptions?.onPullRes) {
|
|
43
|
-
yield* Effect.
|
|
47
|
+
if (doOptions?.onPullRes !== undefined) {
|
|
48
|
+
yield* Effect.trySyncOrPromiseOrEffect(() => doOptions.onPullRes(res)).pipe(UnknownError.mapToUnknownError);
|
|
44
49
|
}
|
|
45
50
|
})), Stream.emitIfEmpty(SyncMessage.emptyPullResponse(backendId)));
|
|
46
|
-
}).pipe(Stream.unwrap, Stream.mapError((cause) =>
|
|
51
|
+
}).pipe(Stream.unwrap, Stream.mapError((cause) => cause._tag === 'BackendIdMismatchError' || cause._tag === 'UnknownError' ? cause : new UnknownError({ cause })), Stream.withSpan('cloudflare-provider:pull'));
|
|
47
52
|
//# sourceMappingURL=pull.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pull.js","sourceRoot":"","sources":["../../../src/cf-worker/do/pull.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,
|
|
1
|
+
{"version":3,"file":"pull.js","sourceRoot":"","sources":["../../../src/cf-worker/do/pull.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,14 +1,28 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BackendIdMismatchError, ServerAheadError, UnknownError } from '@livestore/common';
|
|
2
2
|
import { type CfTypes } from '@livestore/common-cf';
|
|
3
3
|
import { Effect, Schema } from '@livestore/utils/effect';
|
|
4
4
|
import { SyncMessage } from '../../common/mod.ts';
|
|
5
|
-
import { type Env, type MakeDurableObjectClassOptions, type StoreId } from '../shared.ts';
|
|
6
|
-
import
|
|
7
|
-
export declare const makePush: ({ payload, options, storeId, ctx, env, }: {
|
|
8
|
-
payload: Schema.
|
|
5
|
+
import { type Env, type ForwardedHeaders, type MakeDurableObjectClassOptions, type StoreId } from '../shared.ts';
|
|
6
|
+
import * as DoCtx from './layer.ts';
|
|
7
|
+
export declare const makePush: ({ payload, headers, options, storeId, ctx, env, }: {
|
|
8
|
+
payload: Schema.Json | undefined;
|
|
9
|
+
headers: ForwardedHeaders | undefined;
|
|
9
10
|
options: MakeDurableObjectClassOptions | undefined;
|
|
10
11
|
storeId: StoreId;
|
|
11
12
|
ctx: CfTypes.DurableObjectState;
|
|
12
13
|
env: Env;
|
|
13
|
-
}) => (pushRequest: Omit<SyncMessage.PushRequest, "_tag">) => Effect.Effect<{},
|
|
14
|
+
}) => (pushRequest: Omit<SyncMessage.PushRequest, "_tag">) => Effect.Effect<{}, UnknownError | BackendIdMismatchError | ServerAheadError, DoCtx.DoCtx>;
|
|
15
|
+
/**
|
|
16
|
+
* Serializes the complete push admission lifecycle, including publication to pull subscribers.
|
|
17
|
+
*
|
|
18
|
+
* This complements `blockConcurrencyWhile`: that Cloudflare primitive makes the durable state transition
|
|
19
|
+
* atomic with respect to other Durable Object requests, whereas this semaphore preserves push order after
|
|
20
|
+
* the storage gate is released and broadcasting begins. Keeping broadcast outside `blockConcurrencyWhile`
|
|
21
|
+
* avoids holding Cloudflare's concurrency gate across network I/O.
|
|
22
|
+
*
|
|
23
|
+
* Once admitted, the effect is uninterruptible so cancellation cannot leave a committed head without its
|
|
24
|
+
* matching pull response. Such a gap would make later pushers receive `ServerAhead` while waiting for a
|
|
25
|
+
* response that was never published.
|
|
26
|
+
*/
|
|
27
|
+
export declare const runSerializedPushAdmission: <A, E, R>(semaphore: DoCtx.Service["pushSemaphore"], admission: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>;
|
|
14
28
|
//# sourceMappingURL=push.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"push.d.ts","sourceRoot":"","sources":["../../../src/cf-worker/do/push.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"push.d.ts","sourceRoot":"","sources":["../../../src/cf-worker/do/push.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,gBAAgB,EAAe,YAAY,EAAE,MAAM,mBAAmB,CAAA;AACvG,OAAO,EAAE,KAAK,OAAO,EAAsB,MAAM,sBAAsB,CAAA;AAEvE,OAAO,EAAE,MAAM,EAAyD,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAG/G,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACjD,OAAO,EACL,KAAK,GAAG,EACR,KAAK,gBAAgB,EACrB,KAAK,6BAA6B,EAGlC,KAAK,OAAO,EAEb,MAAM,cAAc,CAAA;AACrB,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AAQnC,eAAO,MAAM,QAAQ,GAClB,mDAOE;IACD,OAAO,EAAE,MAAM,CAAC,IAAI,GAAG,SAAS,CAAA;IAChC,OAAO,EAAE,gBAAgB,GAAG,SAAS,CAAA;IACrC,OAAO,EAAE,6BAA6B,GAAG,SAAS,CAAA;IAClD,OAAO,EAAE,OAAO,CAAA;IAChB,GAAG,EAAE,OAAO,CAAC,kBAAkB,CAAA;IAC/B,GAAG,EAAE,GAAG,CAAA;CACT,MACA,aAAa,IAAI,CAAC,WAAW,CAAC,WAAW,EAAE,MAAM,CAAC,6FA0KhD,CAAA;AAEL;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,0BAA0B,GAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAChD,WAAW,KAAK,CAAC,OAAO,CAAC,eAAe,CAAC,EACzC,WAAW,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,KAChC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAqE,CAAA"}
|