@syncular/server-workers 0.15.48 → 0.17.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 +24 -15
- package/dist/realtime-do.d.ts +3 -1
- package/dist/realtime-do.js +8 -1
- package/package.json +4 -4
- package/src/realtime-do.ts +10 -0
package/README.md
CHANGED
|
@@ -101,21 +101,23 @@ See `wrangler.toml.example` for the binding config.
|
|
|
101
101
|
|
|
102
102
|
## Schema migration (D1)
|
|
103
103
|
|
|
104
|
-
`
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
The
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
104
|
+
Run `storage.migrateSchema(compileSchema(schema))` from an authenticated
|
|
105
|
+
maintenance handler before admitting sync traffic. The method creates core
|
|
106
|
+
and application tables and rewrites stored rows. It returns
|
|
107
|
+
`{ complete, statementsExecuted }`; call it again in a new Worker invocation
|
|
108
|
+
when `complete` is false.
|
|
109
|
+
|
|
110
|
+
Each call defaults to 50 statements. Set `{ maxStatements: 40 }` to leave
|
|
111
|
+
room for other queries, or choose another integer from 10 through 1000 for
|
|
112
|
+
your D1 plan. Run at most one call per invocation. Progress and row updates
|
|
113
|
+
commit together, so interrupted requests can resume with the same schema.
|
|
114
|
+
The storage rejects row reads and transaction commits during migration.
|
|
115
|
+
|
|
116
|
+
`ensureSchema` performs one step and throws
|
|
117
|
+
`sync.storage.schema_migration_pending` when another invocation is needed.
|
|
118
|
+
Drain older Syncular deployments before starting an upgrade: they do not
|
|
119
|
+
check the migration state. See [the migration guide](https://syncular.dev/server-workers/#schema-migration)
|
|
120
|
+
for a maintenance handler and the remaining D1 limits.
|
|
119
121
|
|
|
120
122
|
## Storage: D1 (`D1ServerStorage`)
|
|
121
123
|
|
|
@@ -139,6 +141,10 @@ from a Worker scheduler, queue consumer, Workflow step, or Durable Object
|
|
|
139
141
|
alarm according to the application's hosting model.
|
|
140
142
|
|
|
141
143
|
Schedule `pruneReactions` per partition as a separate maintenance pass.
|
|
144
|
+
For commit-log pruning, expose the `SyncularRealtimeHost.pruneCommitLog` method
|
|
145
|
+
through the owning Durable Object and call its RPC from the scheduler. This
|
|
146
|
+
method uses the existing partition FIFO. Direct D1 pruning requires the same
|
|
147
|
+
external serialization assertion as push application.
|
|
142
148
|
Defaults retain completed rows for 30 days and dead-lettered rows for 90 days,
|
|
143
149
|
with at most 1,000 deletions per pass. Repeat while `mayHaveMore` is true.
|
|
144
150
|
Pending and leased rows are never eligible. D1 executes each bounded cleanup
|
|
@@ -263,6 +269,9 @@ const realtimeDOConfig = (env: Env): RealtimeDOConfig => ({
|
|
|
263
269
|
export class SyncularRealtimeDO extends DurableObject<Env> {
|
|
264
270
|
#host = new SyncularRealtimeHost(this.ctx, this.env.DB, realtimeDOConfig(this.env));
|
|
265
271
|
fetch(request: Request) { return this.#host.fetch(request); }
|
|
272
|
+
pruneCommitLog(partition: string, nowMs: number) {
|
|
273
|
+
return this.#host.pruneCommitLog({ partition, nowMs });
|
|
274
|
+
}
|
|
266
275
|
webSocketMessage(ws: WebSocket, msg: ArrayBuffer | string) {
|
|
267
276
|
return this.#host.webSocketMessage(ws, msg);
|
|
268
277
|
}
|
package/dist/realtime-do.d.ts
CHANGED
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
* partition serialization may call `/__wake` after its own commit so sockets
|
|
68
68
|
* re-pull. See `durableObjectRealtimeNotifier` for that caller side.
|
|
69
69
|
*/
|
|
70
|
-
import { D1ServerStorage, type RealtimeHubConfig } from '@syncular/server';
|
|
70
|
+
import { D1ServerStorage, type PruneOptions, type RealtimeHubConfig } from '@syncular/server';
|
|
71
71
|
export interface DurableObjectStateLike {
|
|
72
72
|
acceptWebSocket(ws: WebSocketLike, tags?: string[]): void;
|
|
73
73
|
getWebSockets(tag?: string): WebSocketLike[];
|
|
@@ -153,6 +153,8 @@ export declare class SyncularRealtimeHost {
|
|
|
153
153
|
* and accepts external-command wakes at `/__syncular_realtime/wake`.
|
|
154
154
|
*/
|
|
155
155
|
fetch(request: Request): Promise<Response>;
|
|
156
|
+
/** Trusted maintenance shares the partition FIFO with HTTP/socket writes. */
|
|
157
|
+
pruneCommitLog(options: Omit<PruneOptions, 'storage'>): Promise<number>;
|
|
156
158
|
/** Hibernation callback: an inbound frame. */
|
|
157
159
|
webSocketMessage(ws: WebSocketLike, message: ArrayBuffer | string): Promise<void>;
|
|
158
160
|
/** Hibernation callback: the socket closed. */
|
package/dist/realtime-do.js
CHANGED
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
* partition serialization may call `/__wake` after its own commit so sockets
|
|
68
68
|
* re-pull. See `durableObjectRealtimeNotifier` for that caller side.
|
|
69
69
|
*/
|
|
70
|
-
import { createRealtimeHub, D1ServerStorage, errorBody, handleSyncRequest, SSP2_CONTENT_TYPE, SyncError, } from '@syncular/server';
|
|
70
|
+
import { createRealtimeHub, D1ServerStorage, errorBody, handleSyncRequest, pruneCommitLog, SSP2_CONTENT_TYPE, SyncError, } from '@syncular/server';
|
|
71
71
|
function isAttachment(value) {
|
|
72
72
|
return (typeof value === 'object' &&
|
|
73
73
|
value !== null &&
|
|
@@ -158,6 +158,13 @@ export class SyncularRealtimeHost {
|
|
|
158
158
|
}
|
|
159
159
|
return new Response('not found', { status: 404 });
|
|
160
160
|
}
|
|
161
|
+
/** Trusted maintenance shares the partition FIFO with HTTP/socket writes. */
|
|
162
|
+
pruneCommitLog(options) {
|
|
163
|
+
return this.#serializePartition(async () => {
|
|
164
|
+
await this.#storage.migrate();
|
|
165
|
+
return pruneCommitLog({ ...options, storage: this.#storage });
|
|
166
|
+
});
|
|
167
|
+
}
|
|
161
168
|
#serializePartition(operation) {
|
|
162
169
|
const result = this.#partitionTail.then(operation, operation);
|
|
163
170
|
this.#partitionTail = result.then(() => undefined, () => undefined);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@syncular/server-workers",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.0",
|
|
4
4
|
"description": "Cloudflare Workers adapter for the Syncular sync server",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Benjamin Kniffler",
|
|
@@ -45,10 +45,10 @@
|
|
|
45
45
|
"!dist/**/*.test.d.ts"
|
|
46
46
|
],
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@syncular/server": "0.
|
|
49
|
-
"@syncular/server-hono": "0.
|
|
48
|
+
"@syncular/server": "0.17.0",
|
|
49
|
+
"@syncular/server-hono": "0.17.0"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
|
-
"@syncular/core": "0.
|
|
52
|
+
"@syncular/core": "0.17.0"
|
|
53
53
|
}
|
|
54
54
|
}
|
package/src/realtime-do.ts
CHANGED
|
@@ -72,6 +72,8 @@ import {
|
|
|
72
72
|
D1ServerStorage,
|
|
73
73
|
errorBody,
|
|
74
74
|
handleSyncRequest,
|
|
75
|
+
pruneCommitLog,
|
|
76
|
+
type PruneOptions,
|
|
75
77
|
type RealtimeHub,
|
|
76
78
|
type RealtimeHubConfig,
|
|
77
79
|
type RealtimeSession,
|
|
@@ -249,6 +251,14 @@ export class SyncularRealtimeHost {
|
|
|
249
251
|
return new Response('not found', { status: 404 });
|
|
250
252
|
}
|
|
251
253
|
|
|
254
|
+
/** Trusted maintenance shares the partition FIFO with HTTP/socket writes. */
|
|
255
|
+
pruneCommitLog(options: Omit<PruneOptions, 'storage'>): Promise<number> {
|
|
256
|
+
return this.#serializePartition(async () => {
|
|
257
|
+
await this.#storage.migrate();
|
|
258
|
+
return pruneCommitLog({ ...options, storage: this.#storage });
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
|
|
252
262
|
#serializePartition<T>(operation: () => Promise<T>): Promise<T> {
|
|
253
263
|
const result = this.#partitionTail.then(operation, operation);
|
|
254
264
|
this.#partitionTail = result.then(
|