@powersync/service-core 0.0.0-dev-20250813080357 → 0.0.0-dev-20250819134004
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 +10 -6
- package/dist/api/diagnostics.js +1 -1
- package/dist/api/diagnostics.js.map +1 -1
- package/dist/events/EventsEngine.d.ts +11 -0
- package/dist/{emitters/EmitterEngine.js → events/EventsEngine.js} +2 -2
- package/dist/events/EventsEngine.js.map +1 -0
- package/dist/routes/configure-fastify.d.ts +40 -0
- package/dist/routes/endpoints/socket-route.js +4 -7
- package/dist/routes/endpoints/socket-route.js.map +1 -1
- package/dist/routes/endpoints/sync-rules.js +1 -27
- package/dist/routes/endpoints/sync-rules.js.map +1 -1
- package/dist/routes/endpoints/sync-stream.d.ts +80 -0
- package/dist/routes/endpoints/sync-stream.js +7 -11
- package/dist/routes/endpoints/sync-stream.js.map +1 -1
- package/dist/storage/ReportStorage.d.ts +8 -0
- package/dist/storage/ReportStorage.js +2 -0
- package/dist/storage/ReportStorage.js.map +1 -0
- package/dist/storage/StorageEngine.d.ts +2 -2
- package/dist/storage/StorageEngine.js.map +1 -1
- package/dist/storage/StorageProvider.d.ts +3 -3
- package/dist/storage/storage-index.d.ts +1 -1
- package/dist/storage/storage-index.js +1 -1
- package/dist/storage/storage-index.js.map +1 -1
- package/dist/sync/BucketChecksumState.d.ts +34 -8
- package/dist/sync/BucketChecksumState.js +153 -18
- package/dist/sync/BucketChecksumState.js.map +1 -1
- package/dist/sync/sync.d.ts +1 -2
- package/dist/sync/sync.js +8 -10
- package/dist/sync/sync.js.map +1 -1
- package/dist/system/ServiceContext.d.ts +3 -3
- package/dist/system/ServiceContext.js +7 -4
- package/dist/system/ServiceContext.js.map +1 -1
- package/dist/util/protocol-types.d.ts +153 -5
- package/dist/util/protocol-types.js +41 -2
- package/dist/util/protocol-types.js.map +1 -1
- package/package.json +6 -6
- package/src/api/diagnostics.ts +1 -1
- package/src/{emitters/EmitterEngine.ts → events/EventsEngine.ts} +5 -6
- package/src/routes/endpoints/socket-route.ts +5 -9
- package/src/routes/endpoints/sync-rules.ts +1 -28
- package/src/routes/endpoints/sync-stream.ts +8 -13
- package/src/storage/ReportStorage.ts +11 -0
- package/src/storage/StorageEngine.ts +3 -3
- package/src/storage/StorageProvider.ts +3 -4
- package/src/storage/storage-index.ts +1 -1
- package/src/sync/BucketChecksumState.ts +183 -26
- package/src/sync/sync.ts +15 -13
- package/src/system/ServiceContext.ts +8 -5
- package/src/util/protocol-types.ts +138 -5
- package/test/src/sync/BucketChecksumState.test.ts +366 -34
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/emitters/EmitterEngine.d.ts +0 -12
- package/dist/emitters/EmitterEngine.js.map +0 -1
- package/dist/emitters/emitter-interfaces.d.ts +0 -8
- package/dist/emitters/emitter-interfaces.js +0 -2
- package/dist/emitters/emitter-interfaces.js.map +0 -1
- package/dist/storage/ReportStorageFactory.d.ts +0 -8
- package/dist/storage/ReportStorageFactory.js +0 -2
- package/dist/storage/ReportStorageFactory.js.map +0 -1
- package/src/emitters/emitter-interfaces.ts +0 -12
- package/src/storage/ReportStorageFactory.ts +0 -9
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ServiceContext.js","sourceRoot":"","sources":["../../src/system/ServiceContext.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,gBAAgB,EAAqB,MAAM,mCAAmC,CAAC;AAErH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,KAAK,OAAO,MAAM,6BAA6B,CAAC;AAEvD,OAAO,KAAK,WAAW,MAAM,qCAAqC,CAAC;AACnE,OAAO,KAAK,MAAM,MAAM,2BAA2B,CAAC;AACpD,OAAO,KAAK,OAAO,MAAM,6BAA6B,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,KAAK,KAAK,MAAM,uBAAuB,CAAC;AAC/C,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"ServiceContext.js","sourceRoot":"","sources":["../../src/system/ServiceContext.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as t from 'ts-codec';
|
|
2
|
-
import {
|
|
2
|
+
import { BucketPriority, SqliteJsonRow } from '@powersync/service-sync-rules';
|
|
3
3
|
import { JsonContainer } from '@powersync/service-jsonbig';
|
|
4
4
|
export declare const BucketRequest: t.ObjectCodec<{
|
|
5
5
|
name: t.IdentityCodec<t.CodecType.String>;
|
|
@@ -9,9 +9,62 @@ export declare const BucketRequest: t.ObjectCodec<{
|
|
|
9
9
|
after: t.IdentityCodec<t.CodecType.String>;
|
|
10
10
|
}>;
|
|
11
11
|
export type BucketRequest = t.Decoded<typeof BucketRequest>;
|
|
12
|
+
/**
|
|
13
|
+
* A sync steam that a client has expressed interest in by explicitly opening it on the client side.
|
|
14
|
+
*/
|
|
15
|
+
export declare const RequestedStreamSubscription: t.ObjectCodec<{
|
|
16
|
+
/**
|
|
17
|
+
* The defined name of the stream as it appears in sync stream definitions.
|
|
18
|
+
*/
|
|
19
|
+
stream: t.IdentityCodec<t.CodecType.String>;
|
|
20
|
+
/**
|
|
21
|
+
* An optional dictionary of parameters to pass to this specific stream.
|
|
22
|
+
*/
|
|
23
|
+
parameters: t.OptionalCodec<t.Codec<Record<string, any>, Record<string, any>, string, t.CodecProps>>;
|
|
24
|
+
/**
|
|
25
|
+
* Set when the client wishes to re-assign a different priority to this stream.
|
|
26
|
+
*
|
|
27
|
+
* Streams and sync rules can also assign a default priority, but clients are allowed to override those. This can be
|
|
28
|
+
* useful when the priority for partial syncs depends on e.g. the current page opened in a client.
|
|
29
|
+
*/
|
|
30
|
+
override_priority: t.Union<t.IdentityCodec<t.CodecType.Number>, t.Codec<null, null, t.CodecType.Null, t.CodecProps>>;
|
|
31
|
+
}>;
|
|
32
|
+
export type RequestedStreamSubscription = t.Decoded<typeof RequestedStreamSubscription>;
|
|
33
|
+
/**
|
|
34
|
+
* An overview of all subscribed streams as part of a streaming sync request.
|
|
35
|
+
*/
|
|
36
|
+
export declare const StreamSubscriptionRequest: t.ObjectCodec<{
|
|
37
|
+
/**
|
|
38
|
+
* Whether to sync default streams.
|
|
39
|
+
*
|
|
40
|
+
* When disabled, only explicitly-opened subscriptions are included.
|
|
41
|
+
*/
|
|
42
|
+
include_defaults: t.OptionalCodec<t.Codec<boolean, boolean, string, t.CodecProps>>;
|
|
43
|
+
/**
|
|
44
|
+
* An array of sync streams the client has opened explicitly.
|
|
45
|
+
*/
|
|
46
|
+
subscriptions: t.ArrayCodec<t.ObjectCodec<{
|
|
47
|
+
/**
|
|
48
|
+
* The defined name of the stream as it appears in sync stream definitions.
|
|
49
|
+
*/
|
|
50
|
+
stream: t.IdentityCodec<t.CodecType.String>;
|
|
51
|
+
/**
|
|
52
|
+
* An optional dictionary of parameters to pass to this specific stream.
|
|
53
|
+
*/
|
|
54
|
+
parameters: t.OptionalCodec<t.Codec<Record<string, any>, Record<string, any>, string, t.CodecProps>>;
|
|
55
|
+
/**
|
|
56
|
+
* Set when the client wishes to re-assign a different priority to this stream.
|
|
57
|
+
*
|
|
58
|
+
* Streams and sync rules can also assign a default priority, but clients are allowed to override those. This can be
|
|
59
|
+
* useful when the priority for partial syncs depends on e.g. the current page opened in a client.
|
|
60
|
+
*/
|
|
61
|
+
override_priority: t.Union<t.IdentityCodec<t.CodecType.Number>, t.Codec<null, null, t.CodecType.Null, t.CodecProps>>;
|
|
62
|
+
}>>;
|
|
63
|
+
}>;
|
|
64
|
+
export type StreamSubscriptionRequest = t.Decoded<typeof StreamSubscriptionRequest>;
|
|
12
65
|
export declare const StreamingSyncRequest: t.ObjectCodec<{
|
|
13
66
|
/**
|
|
14
|
-
* Existing bucket states.
|
|
67
|
+
* Existing client-side bucket states.
|
|
15
68
|
*/
|
|
16
69
|
buckets: t.OptionalCodec<t.Codec<{
|
|
17
70
|
name: string;
|
|
@@ -44,6 +97,24 @@ export declare const StreamingSyncRequest: t.ObjectCodec<{
|
|
|
44
97
|
* Unique client id.
|
|
45
98
|
*/
|
|
46
99
|
client_id: t.OptionalCodec<t.Codec<string, string, string, t.CodecProps>>;
|
|
100
|
+
/**
|
|
101
|
+
* If the client is aware of streams, an array of streams the client has opened.
|
|
102
|
+
*/
|
|
103
|
+
streams: t.OptionalCodec<t.Codec<{
|
|
104
|
+
subscriptions: {
|
|
105
|
+
stream: string;
|
|
106
|
+
override_priority: number | null;
|
|
107
|
+
parameters?: Record<string, any> | undefined;
|
|
108
|
+
}[];
|
|
109
|
+
include_defaults?: boolean | undefined;
|
|
110
|
+
}, {
|
|
111
|
+
subscriptions: {
|
|
112
|
+
stream: string;
|
|
113
|
+
override_priority: number | null;
|
|
114
|
+
parameters?: Record<string, any> | undefined;
|
|
115
|
+
}[];
|
|
116
|
+
include_defaults?: boolean | undefined;
|
|
117
|
+
}, string, t.CodecProps>>;
|
|
47
118
|
}>;
|
|
48
119
|
export type StreamingSyncRequest = t.Decoded<typeof StreamingSyncRequest>;
|
|
49
120
|
export interface StreamingSyncCheckpoint {
|
|
@@ -53,7 +124,7 @@ export interface StreamingSyncCheckpointDiff {
|
|
|
53
124
|
checkpoint_diff: {
|
|
54
125
|
last_op_id: ProtocolOpId;
|
|
55
126
|
write_checkpoint?: ProtocolOpId;
|
|
56
|
-
updated_buckets:
|
|
127
|
+
updated_buckets: CheckpointBucket[];
|
|
57
128
|
removed_buckets: string[];
|
|
58
129
|
};
|
|
59
130
|
}
|
|
@@ -79,10 +150,49 @@ export type StreamingSyncLine = StreamingSyncData | StreamingSyncCheckpoint | St
|
|
|
79
150
|
* 64-bit unsigned number, as a base-10 string.
|
|
80
151
|
*/
|
|
81
152
|
export type ProtocolOpId = string;
|
|
153
|
+
export interface StreamDescription {
|
|
154
|
+
/**
|
|
155
|
+
* The name of the stream as it appears in the sync configuration.
|
|
156
|
+
*/
|
|
157
|
+
name: string;
|
|
158
|
+
/**
|
|
159
|
+
* Whether this stream is subscribed to by default.
|
|
160
|
+
*
|
|
161
|
+
* For default streams, this field is still `true` if clients have an explicit subscription to the stream.
|
|
162
|
+
*/
|
|
163
|
+
is_default: boolean;
|
|
164
|
+
/**
|
|
165
|
+
* If some subscriptions on this stream could not be resolved, e.g. due to an error, this array contains the faulty
|
|
166
|
+
* subscriptions along with an error message.
|
|
167
|
+
*/
|
|
168
|
+
errors: StreamSubscriptionError[];
|
|
169
|
+
}
|
|
170
|
+
export interface StreamSubscriptionError {
|
|
171
|
+
/**
|
|
172
|
+
* The subscription that errored - either the default subscription or some of the explicit subscriptions.
|
|
173
|
+
*/
|
|
174
|
+
subscription: 'default' | number;
|
|
175
|
+
/**
|
|
176
|
+
* A message describing the error on the subscription.
|
|
177
|
+
*/
|
|
178
|
+
message: string;
|
|
179
|
+
}
|
|
82
180
|
export interface Checkpoint {
|
|
83
181
|
last_op_id: ProtocolOpId;
|
|
84
182
|
write_checkpoint?: ProtocolOpId;
|
|
85
|
-
buckets:
|
|
183
|
+
buckets: CheckpointBucket[];
|
|
184
|
+
/**
|
|
185
|
+
* All streams that the client is subscribed to.
|
|
186
|
+
*
|
|
187
|
+
* This field has two purposes:
|
|
188
|
+
*
|
|
189
|
+
* 1. It allows clients to determine which of their subscriptions actually works. E.g. if a user does
|
|
190
|
+
* `db.syncStream('non_existent_stream').subscribe()`, clients don't immediately know that the stream doesn't
|
|
191
|
+
* exist. Only after the next `checkpoint` line can they query this field and mark unresolved subscriptions.
|
|
192
|
+
*. 2. It allows clients to learn which default streams they have been subscribed to. This is relevant for APIs
|
|
193
|
+
* listing all streams on the client-side.
|
|
194
|
+
*/
|
|
195
|
+
streams: StreamDescription[];
|
|
86
196
|
}
|
|
87
197
|
export interface BucketState {
|
|
88
198
|
bucket: string;
|
|
@@ -126,5 +236,43 @@ export interface BucketChecksum {
|
|
|
126
236
|
*/
|
|
127
237
|
count: number;
|
|
128
238
|
}
|
|
129
|
-
|
|
239
|
+
/**
|
|
240
|
+
* The reason a particular bucket is included in a checkpoint.
|
|
241
|
+
*
|
|
242
|
+
* This information allows clients to associate individual buckets with sync streams they're subscribed to. Having that
|
|
243
|
+
* association is useful because it enables clients to track progress for individual sync streams.
|
|
244
|
+
*/
|
|
245
|
+
export type BucketSubscriptionReason = BucketDerivedFromDefaultStream | BucketDerivedFromExplicitSubscription;
|
|
246
|
+
/**
|
|
247
|
+
* A bucket has been included in a checkpoint because it's part of a default stream.
|
|
248
|
+
*/
|
|
249
|
+
export type BucketDerivedFromDefaultStream = {
|
|
250
|
+
/**
|
|
251
|
+
* The index (into {@link Checkpoint.streams}) of the stream defining the bucket.
|
|
252
|
+
*/
|
|
253
|
+
default: number;
|
|
254
|
+
};
|
|
255
|
+
/**
|
|
256
|
+
* The bucket has been included in a checkpoint because it's part of a stream that a client has explicitly subscribed
|
|
257
|
+
* to.
|
|
258
|
+
*/
|
|
259
|
+
export type BucketDerivedFromExplicitSubscription = {
|
|
260
|
+
/**
|
|
261
|
+
* The index (into {@link StreamSubscriptionRequest.subscriptions}) of the subscription yielding this bucket.
|
|
262
|
+
*/
|
|
263
|
+
sub: number;
|
|
264
|
+
};
|
|
265
|
+
export interface ClientBucketDescription {
|
|
266
|
+
/**
|
|
267
|
+
* An opaque id of the bucket.
|
|
268
|
+
*/
|
|
269
|
+
bucket: string;
|
|
270
|
+
/**
|
|
271
|
+
* The priority used to synchronize this bucket, derived from its definition and an optional priority override from
|
|
272
|
+
* the stream subscription.
|
|
273
|
+
*/
|
|
274
|
+
priority: BucketPriority;
|
|
275
|
+
subscriptions: BucketSubscriptionReason[];
|
|
276
|
+
}
|
|
277
|
+
export interface CheckpointBucket extends BucketChecksum, ClientBucketDescription {
|
|
130
278
|
}
|
|
@@ -6,9 +6,44 @@ export const BucketRequest = t.object({
|
|
|
6
6
|
*/
|
|
7
7
|
after: t.string
|
|
8
8
|
});
|
|
9
|
+
/**
|
|
10
|
+
* A sync steam that a client has expressed interest in by explicitly opening it on the client side.
|
|
11
|
+
*/
|
|
12
|
+
export const RequestedStreamSubscription = t.object({
|
|
13
|
+
/**
|
|
14
|
+
* The defined name of the stream as it appears in sync stream definitions.
|
|
15
|
+
*/
|
|
16
|
+
stream: t.string,
|
|
17
|
+
/**
|
|
18
|
+
* An optional dictionary of parameters to pass to this specific stream.
|
|
19
|
+
*/
|
|
20
|
+
parameters: t.record(t.any).optional(),
|
|
21
|
+
/**
|
|
22
|
+
* Set when the client wishes to re-assign a different priority to this stream.
|
|
23
|
+
*
|
|
24
|
+
* Streams and sync rules can also assign a default priority, but clients are allowed to override those. This can be
|
|
25
|
+
* useful when the priority for partial syncs depends on e.g. the current page opened in a client.
|
|
26
|
+
*/
|
|
27
|
+
override_priority: t.union(t.number, t.Null)
|
|
28
|
+
});
|
|
29
|
+
/**
|
|
30
|
+
* An overview of all subscribed streams as part of a streaming sync request.
|
|
31
|
+
*/
|
|
32
|
+
export const StreamSubscriptionRequest = t.object({
|
|
33
|
+
/**
|
|
34
|
+
* Whether to sync default streams.
|
|
35
|
+
*
|
|
36
|
+
* When disabled, only explicitly-opened subscriptions are included.
|
|
37
|
+
*/
|
|
38
|
+
include_defaults: t.boolean.optional(),
|
|
39
|
+
/**
|
|
40
|
+
* An array of sync streams the client has opened explicitly.
|
|
41
|
+
*/
|
|
42
|
+
subscriptions: t.array(RequestedStreamSubscription)
|
|
43
|
+
});
|
|
9
44
|
export const StreamingSyncRequest = t.object({
|
|
10
45
|
/**
|
|
11
|
-
* Existing bucket states.
|
|
46
|
+
* Existing client-side bucket states.
|
|
12
47
|
*/
|
|
13
48
|
buckets: t.array(BucketRequest).optional(),
|
|
14
49
|
/**
|
|
@@ -34,6 +69,10 @@ export const StreamingSyncRequest = t.object({
|
|
|
34
69
|
/**
|
|
35
70
|
* Unique client id.
|
|
36
71
|
*/
|
|
37
|
-
client_id: t.string.optional()
|
|
72
|
+
client_id: t.string.optional(),
|
|
73
|
+
/**
|
|
74
|
+
* If the client is aware of streams, an array of streams the client has opened.
|
|
75
|
+
*/
|
|
76
|
+
streams: StreamSubscriptionRequest.optional()
|
|
38
77
|
});
|
|
39
78
|
//# sourceMappingURL=protocol-types.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocol-types.js","sourceRoot":"","sources":["../../src/util/protocol-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,UAAU,CAAC;AAI9B,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC,MAAM,CAAC;IACpC,IAAI,EAAE,CAAC,CAAC,MAAM;IAEd;;OAEG;IACH,KAAK,EAAE,CAAC,CAAC,MAAM;CAChB,CAAC,CAAC;AAIH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C;;OAEG;IACH,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,QAAQ,EAAE;IAE1C;;OAEG;IACH,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE;IAElC;;OAEG;IACH,gBAAgB,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE;IAEtC;;OAEG;IACH,QAAQ,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE;IAE9B;;OAEG;IACH,WAAW,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE;IAEjC;;OAEG;IACH,UAAU,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE;IAEtC;;OAEG;IACH,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,QAAQ,EAAE;
|
|
1
|
+
{"version":3,"file":"protocol-types.js","sourceRoot":"","sources":["../../src/util/protocol-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,UAAU,CAAC;AAI9B,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC,MAAM,CAAC;IACpC,IAAI,EAAE,CAAC,CAAC,MAAM;IAEd;;OAEG;IACH,KAAK,EAAE,CAAC,CAAC,MAAM;CAChB,CAAC,CAAC;AAIH;;GAEG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,CAAC,MAAM,CAAC;IAClD;;OAEG;IACH,MAAM,EAAE,CAAC,CAAC,MAAM;IAChB;;OAEG;IACH,UAAU,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE;IACtC;;;;;OAKG;IACH,iBAAiB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC;CAC7C,CAAC,CAAC;AAIH;;GAEG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC,MAAM,CAAC;IAChD;;;;OAIG;IACH,gBAAgB,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE;IAEtC;;OAEG;IACH,aAAa,EAAE,CAAC,CAAC,KAAK,CAAC,2BAA2B,CAAC;CACpD,CAAC,CAAC;AAIH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C;;OAEG;IACH,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,QAAQ,EAAE;IAE1C;;OAEG;IACH,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE;IAElC;;OAEG;IACH,gBAAgB,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE;IAEtC;;OAEG;IACH,QAAQ,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE;IAE9B;;OAEG;IACH,WAAW,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE;IAEjC;;OAEG;IACH,UAAU,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE;IAEtC;;OAEG;IACH,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,QAAQ,EAAE;IAE9B;;OAEG;IACH,OAAO,EAAE,yBAAyB,CAAC,QAAQ,EAAE;CAC9C,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
8
|
-
"version": "0.0.0-dev-
|
|
8
|
+
"version": "0.0.0-dev-20250819134004",
|
|
9
9
|
"main": "dist/index.js",
|
|
10
10
|
"license": "FSL-1.1-ALv2",
|
|
11
11
|
"type": "module",
|
|
@@ -33,11 +33,11 @@
|
|
|
33
33
|
"uuid": "^11.1.0",
|
|
34
34
|
"winston": "^3.13.0",
|
|
35
35
|
"yaml": "^2.3.2",
|
|
36
|
-
"@powersync/lib-services-framework": "0.0.0-dev-
|
|
37
|
-
"@powersync/service-jsonbig": "0.0.0-dev-
|
|
38
|
-
"@powersync/service-rsocket-router": "0.0.0-dev-
|
|
39
|
-
"@powersync/service-sync-rules": "0.0.0-dev-
|
|
40
|
-
"@powersync/service-types": "0.0.0-dev-
|
|
36
|
+
"@powersync/lib-services-framework": "0.0.0-dev-20250819134004",
|
|
37
|
+
"@powersync/service-jsonbig": "0.0.0-dev-20250819134004",
|
|
38
|
+
"@powersync/service-rsocket-router": "0.0.0-dev-20250819134004",
|
|
39
|
+
"@powersync/service-sync-rules": "0.0.0-dev-20250819134004",
|
|
40
|
+
"@powersync/service-types": "0.0.0-dev-20250819134004"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@types/async": "^3.2.24",
|
package/src/api/diagnostics.ts
CHANGED
|
@@ -134,7 +134,7 @@ export async function getSyncRulesStatus(
|
|
|
134
134
|
})
|
|
135
135
|
);
|
|
136
136
|
|
|
137
|
-
if (live_status && status?.active
|
|
137
|
+
if (live_status && status?.active) {
|
|
138
138
|
// Check replication lag for active sync rules.
|
|
139
139
|
// Right now we exclude mysql, since it we don't have consistent keepalives for it.
|
|
140
140
|
if (sync_rules.last_checkpoint_ts == null && sync_rules.last_keepalive_ts == null) {
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import EventEmitter from 'node:events';
|
|
2
2
|
import { logger } from '@powersync/lib-services-framework';
|
|
3
3
|
import { event_types } from '@powersync/service-types';
|
|
4
|
-
import { BaseEmitterEngine } from './emitter-interfaces.js';
|
|
5
4
|
|
|
6
|
-
export class
|
|
5
|
+
export class EventsEngine {
|
|
7
6
|
private emitter: EventEmitter;
|
|
8
|
-
events: Set<event_types.
|
|
7
|
+
private events: Set<event_types.EventsEngineEventType> = new Set();
|
|
9
8
|
constructor() {
|
|
10
9
|
this.emitter = new EventEmitter({ captureRejections: true });
|
|
11
10
|
this.emitter.on('error', (error: Error) => {
|
|
@@ -13,18 +12,18 @@ export class EmitterEngine implements BaseEmitterEngine {
|
|
|
13
12
|
});
|
|
14
13
|
}
|
|
15
14
|
|
|
16
|
-
subscribe<K extends event_types.
|
|
15
|
+
subscribe<K extends event_types.EventsEngineEventType>(event: event_types.EmitterEvent<K>): void {
|
|
17
16
|
if (!this.events.has(event.event)) {
|
|
18
17
|
this.events.add(event.event);
|
|
19
18
|
}
|
|
20
19
|
this.emitter.on(event.event, event.handler.bind(event));
|
|
21
20
|
}
|
|
22
21
|
|
|
23
|
-
get listEvents(): event_types.
|
|
22
|
+
get listEvents(): event_types.EventsEngineEventType[] {
|
|
24
23
|
return Array.from(this.events.values());
|
|
25
24
|
}
|
|
26
25
|
|
|
27
|
-
countListeners(eventName: event_types.
|
|
26
|
+
countListeners(eventName: event_types.EventsEngineEventType): number {
|
|
28
27
|
return this.emitter.listenerCount(eventName);
|
|
29
28
|
}
|
|
30
29
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { ErrorCode, errors, schema } from '@powersync/lib-services-framework';
|
|
2
|
-
import { RequestParameters } from '@powersync/service-sync-rules';
|
|
3
2
|
|
|
4
3
|
import * as sync from '../../sync/sync-index.js';
|
|
5
4
|
import * as util from '../../util/util-index.js';
|
|
@@ -23,12 +22,12 @@ export const syncStreamReactive: SocketRouteGenerator = (router) =>
|
|
|
23
22
|
user_agent: context.user_agent
|
|
24
23
|
};
|
|
25
24
|
|
|
26
|
-
const sdkData: event_types.
|
|
25
|
+
const sdkData: event_types.ConnectedUserData & event_types.ClientConnectionEventData = {
|
|
27
26
|
client_id: params.client_id,
|
|
28
27
|
user_id: context.user_id!,
|
|
29
28
|
user_agent: context.user_agent,
|
|
30
29
|
jwt_exp: context.token_payload?.exp ? new Date(context.token_payload.exp * 1000) : undefined,
|
|
31
|
-
|
|
30
|
+
connected_at: new Date(streamStart)
|
|
32
31
|
};
|
|
33
32
|
|
|
34
33
|
// Best effort guess on why the stream was closed.
|
|
@@ -66,8 +65,6 @@ export const syncStreamReactive: SocketRouteGenerator = (router) =>
|
|
|
66
65
|
return;
|
|
67
66
|
}
|
|
68
67
|
|
|
69
|
-
const syncParams = new RequestParameters(context.token_payload!, params.parameters ?? {});
|
|
70
|
-
|
|
71
68
|
const {
|
|
72
69
|
storageEngine: { activeBucketStorage }
|
|
73
70
|
} = service_context;
|
|
@@ -93,7 +90,7 @@ export const syncStreamReactive: SocketRouteGenerator = (router) =>
|
|
|
93
90
|
});
|
|
94
91
|
|
|
95
92
|
metricsEngine.getUpDownCounter(APIMetric.CONCURRENT_CONNECTIONS).add(1);
|
|
96
|
-
service_context.
|
|
93
|
+
service_context.eventsEngine.emit(event_types.EventsEngineEventType.SDK_CONNECT_EVENT, sdkData);
|
|
97
94
|
const tracker = new sync.RequestTracker(metricsEngine);
|
|
98
95
|
try {
|
|
99
96
|
for await (const data of sync.streamResponse({
|
|
@@ -104,7 +101,6 @@ export const syncStreamReactive: SocketRouteGenerator = (router) =>
|
|
|
104
101
|
...params,
|
|
105
102
|
binary_data: true // always true for web sockets
|
|
106
103
|
},
|
|
107
|
-
syncParams,
|
|
108
104
|
token: context!.token_payload!,
|
|
109
105
|
tokenStreamOptions: {
|
|
110
106
|
// RSocket handles keepalive events by default
|
|
@@ -168,9 +164,9 @@ export const syncStreamReactive: SocketRouteGenerator = (router) =>
|
|
|
168
164
|
close_reason: closeReason ?? 'unknown'
|
|
169
165
|
});
|
|
170
166
|
metricsEngine.getUpDownCounter(APIMetric.CONCURRENT_CONNECTIONS).add(-1);
|
|
171
|
-
service_context.
|
|
167
|
+
service_context.eventsEngine.emit(event_types.EventsEngineEventType.SDK_DISCONNECT_EVENT, {
|
|
172
168
|
...sdkData,
|
|
173
|
-
|
|
169
|
+
disconnected_at: new Date()
|
|
174
170
|
});
|
|
175
171
|
}
|
|
176
172
|
}
|
|
@@ -202,34 +202,7 @@ async function debugSyncRules(apiHandler: RouteAPI, sync_rules: string) {
|
|
|
202
202
|
|
|
203
203
|
return {
|
|
204
204
|
valid: true,
|
|
205
|
-
bucket_definitions: rules.
|
|
206
|
-
let all_parameter_queries = [...d.parameterQueries.values()].flat();
|
|
207
|
-
let all_data_queries = [...d.dataQueries.values()].flat();
|
|
208
|
-
return {
|
|
209
|
-
name: d.name,
|
|
210
|
-
bucket_parameters: d.bucketParameters,
|
|
211
|
-
global_parameter_queries: d.globalParameterQueries.map((q) => {
|
|
212
|
-
return {
|
|
213
|
-
sql: q.sql
|
|
214
|
-
};
|
|
215
|
-
}),
|
|
216
|
-
parameter_queries: all_parameter_queries.map((q) => {
|
|
217
|
-
return {
|
|
218
|
-
sql: q.sql,
|
|
219
|
-
table: q.sourceTable,
|
|
220
|
-
input_parameters: q.inputParameters
|
|
221
|
-
};
|
|
222
|
-
}),
|
|
223
|
-
|
|
224
|
-
data_queries: all_data_queries.map((q) => {
|
|
225
|
-
return {
|
|
226
|
-
sql: q.sql,
|
|
227
|
-
table: q.sourceTable,
|
|
228
|
-
columns: q.columnOutputNames()
|
|
229
|
-
};
|
|
230
|
-
})
|
|
231
|
-
};
|
|
232
|
-
}),
|
|
205
|
+
bucket_definitions: rules.bucketSources.map((source) => source.debugRepresentation()),
|
|
233
206
|
source_tables: resolved_tables,
|
|
234
207
|
data_tables: rules.debugGetOutputTables()
|
|
235
208
|
};
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { ErrorCode, errors, router, schema } from '@powersync/lib-services-framework';
|
|
2
|
-
import { RequestParameters } from '@powersync/service-sync-rules';
|
|
3
2
|
import { Readable } from 'stream';
|
|
4
3
|
import Negotiator from 'negotiator';
|
|
5
4
|
|
|
@@ -42,12 +41,12 @@ export const syncStreamed = routeDefinition({
|
|
|
42
41
|
user_id: payload.context.user_id,
|
|
43
42
|
bson: useBson
|
|
44
43
|
};
|
|
45
|
-
const sdkData: event_types.
|
|
44
|
+
const sdkData: event_types.ConnectedUserData & event_types.ClientConnectionEventData = {
|
|
46
45
|
client_id: clientId,
|
|
47
46
|
user_id: payload.context.user_id!,
|
|
48
47
|
user_agent: userAgent as string,
|
|
49
48
|
jwt_exp: token_payload?.exp ? new Date(token_payload?.exp * 1000) : undefined,
|
|
50
|
-
|
|
49
|
+
connected_at: new Date(streamStart)
|
|
51
50
|
};
|
|
52
51
|
|
|
53
52
|
if (routerEngine.closed) {
|
|
@@ -58,9 +57,6 @@ export const syncStreamed = routeDefinition({
|
|
|
58
57
|
});
|
|
59
58
|
}
|
|
60
59
|
|
|
61
|
-
const params: util.StreamingSyncRequest = payload.params;
|
|
62
|
-
const syncParams = new RequestParameters(payload.context.token_payload!, payload.params.parameters ?? {});
|
|
63
|
-
|
|
64
60
|
const bucketStorage = await storageEngine.activeBucketStorage.getActiveStorage();
|
|
65
61
|
|
|
66
62
|
if (bucketStorage == null) {
|
|
@@ -77,12 +73,12 @@ export const syncStreamed = routeDefinition({
|
|
|
77
73
|
const tracker = new sync.RequestTracker(metricsEngine);
|
|
78
74
|
try {
|
|
79
75
|
metricsEngine.getUpDownCounter(APIMetric.CONCURRENT_CONNECTIONS).add(1);
|
|
76
|
+
service_context.eventsEngine.emit(event_types.EventsEngineEventType.SDK_CONNECT_EVENT, sdkData);
|
|
80
77
|
const syncLines = sync.streamResponse({
|
|
81
78
|
syncContext: syncContext,
|
|
82
79
|
bucketStorage,
|
|
83
80
|
syncRules: syncRules,
|
|
84
|
-
params,
|
|
85
|
-
syncParams,
|
|
81
|
+
params: payload.params,
|
|
86
82
|
token: payload.context.token_payload!,
|
|
87
83
|
tracker,
|
|
88
84
|
signal: controller.signal,
|
|
@@ -94,7 +90,6 @@ export const syncStreamed = routeDefinition({
|
|
|
94
90
|
objectMode: false,
|
|
95
91
|
highWaterMark: 16 * 1024
|
|
96
92
|
});
|
|
97
|
-
service_context.emitterEngine.emit(event_types.EmitterEngineEvents.SDK_CONNECT_EVENT, sdkData);
|
|
98
93
|
|
|
99
94
|
// Best effort guess on why the stream was closed.
|
|
100
95
|
// We use the `??=` operator everywhere, so that we catch the first relevant
|
|
@@ -138,9 +133,9 @@ export const syncStreamed = routeDefinition({
|
|
|
138
133
|
}
|
|
139
134
|
controller.abort();
|
|
140
135
|
metricsEngine.getUpDownCounter(APIMetric.CONCURRENT_CONNECTIONS).add(-1);
|
|
141
|
-
service_context.
|
|
136
|
+
service_context.eventsEngine.emit(event_types.EventsEngineEventType.SDK_DISCONNECT_EVENT, {
|
|
142
137
|
...sdkData,
|
|
143
|
-
|
|
138
|
+
disconnected_at: new Date()
|
|
144
139
|
});
|
|
145
140
|
logger.info(`Sync stream complete`, {
|
|
146
141
|
...tracker.getLogMeta(),
|
|
@@ -152,9 +147,9 @@ export const syncStreamed = routeDefinition({
|
|
|
152
147
|
} catch (ex) {
|
|
153
148
|
controller.abort();
|
|
154
149
|
metricsEngine.getUpDownCounter(APIMetric.CONCURRENT_CONNECTIONS).add(-1);
|
|
155
|
-
service_context.
|
|
150
|
+
service_context.eventsEngine.emit(event_types.EventsEngineEventType.SDK_DISCONNECT_EVENT, {
|
|
156
151
|
...sdkData,
|
|
157
|
-
|
|
152
|
+
disconnected_at: new Date()
|
|
158
153
|
});
|
|
159
154
|
}
|
|
160
155
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { event_types } from '@powersync/service-types';
|
|
2
|
+
|
|
3
|
+
export interface ReportStorage extends AsyncDisposable {
|
|
4
|
+
reportClientConnection(data: event_types.ClientConnectionBucketData): Promise<void>;
|
|
5
|
+
reportClientDisconnection(data: event_types.ClientDisconnectionEventData): Promise<void>;
|
|
6
|
+
getConnectedClients(data: event_types.ClientConnectionsRequest): Promise<event_types.ClientConnectionReport>;
|
|
7
|
+
getClientConnectionReports(
|
|
8
|
+
data: event_types.ClientConnectionReportRequest
|
|
9
|
+
): Promise<event_types.ClientConnectionReport>;
|
|
10
|
+
deleteOldConnectionData(data: event_types.DeleteOldConnectionData): Promise<void>;
|
|
11
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { BaseObserver, logger, ServiceError } from '@powersync/lib-services-framework';
|
|
2
2
|
import { ResolvedPowerSyncConfig } from '../util/util-index.js';
|
|
3
3
|
import { BucketStorageFactory } from './BucketStorageFactory.js';
|
|
4
|
-
import { ActiveStorage,
|
|
4
|
+
import { ActiveStorage, StorageProvider } from './StorageProvider.js';
|
|
5
5
|
|
|
6
6
|
export type StorageEngineOptions = {
|
|
7
7
|
configuration: ResolvedPowerSyncConfig;
|
|
@@ -14,7 +14,7 @@ export interface StorageEngineListener {
|
|
|
14
14
|
|
|
15
15
|
export class StorageEngine extends BaseObserver<StorageEngineListener> {
|
|
16
16
|
// TODO: This will need to revisited when we actually support multiple storage providers.
|
|
17
|
-
private storageProviders: Map<string,
|
|
17
|
+
private storageProviders: Map<string, StorageProvider> = new Map();
|
|
18
18
|
private currentActiveStorage: ActiveStorage | null = null;
|
|
19
19
|
|
|
20
20
|
constructor(private options: StorageEngineOptions) {
|
|
@@ -37,7 +37,7 @@ export class StorageEngine extends BaseObserver<StorageEngineListener> {
|
|
|
37
37
|
* Register a provider which generates a {@link BucketStorageFactory}
|
|
38
38
|
* given the matching config specified in the loaded {@link ResolvedPowerSyncConfig}
|
|
39
39
|
*/
|
|
40
|
-
registerProvider(provider:
|
|
40
|
+
registerProvider(provider: StorageProvider) {
|
|
41
41
|
this.storageProviders.set(provider.type, provider);
|
|
42
42
|
}
|
|
43
43
|
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { ServiceError } from '@powersync/lib-services-framework';
|
|
2
2
|
import * as util from '../util/util-index.js';
|
|
3
3
|
import { BucketStorageFactory } from './BucketStorageFactory.js';
|
|
4
|
-
import {
|
|
4
|
+
import { ReportStorage } from './ReportStorage.js';
|
|
5
5
|
|
|
6
6
|
export interface ActiveStorage {
|
|
7
7
|
storage: BucketStorageFactory;
|
|
8
|
-
|
|
9
|
-
reportStorage: ReportStorageFactory | null;
|
|
8
|
+
reportStorage: ReportStorage;
|
|
10
9
|
shutDown(): Promise<void>;
|
|
11
10
|
|
|
12
11
|
/**
|
|
@@ -25,7 +24,7 @@ export interface GetStorageOptions {
|
|
|
25
24
|
/**
|
|
26
25
|
* Represents a provider that can create a storage instance for a specific storage type from configuration.
|
|
27
26
|
*/
|
|
28
|
-
export interface
|
|
27
|
+
export interface StorageProvider {
|
|
29
28
|
/**
|
|
30
29
|
* The storage type that this provider provides.
|
|
31
30
|
* The type should match the `type` field in the config.
|