@korajs/sync 1.0.0-beta.4 → 1.0.0-beta.6
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/dist/index.cjs +347 -44
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +91 -2
- package/dist/index.d.ts +91 -2
- package/dist/index.js +347 -44
- package/dist/index.js.map +1 -1
- package/dist/internal.d.cts +1 -1
- package/dist/internal.d.ts +1 -1
- package/dist/{transport-BGr-_eH8.d.cts → transport-ByWfWBbB.d.cts} +59 -0
- package/dist/{transport-BGr-_eH8.d.ts → transport-ByWfWBbB.d.ts} +59 -0
- package/package.json +3 -3
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { S as SyncScopeMap, D as DeltaCursor, a as SyncMessage, b as SerializedOperation, W as WireFormat, c as SyncTransport, T as TransportOptions, d as TransportMessageHandler, e as TransportCloseHandler, f as TransportErrorHandler, B as BlobChunkRequestMessage, g as BlobChunkResponseMessage, h as BlobChunkPushMessage, i as SyncEncryptionConfig, V as VersionedKey, Y as YjsDocUpdateMessage, Q as QueueStorage, j as SyncState, k as SyncStatusInfo, l as SyncConfig, R as RejectedOperationStorage, m as SyncStatePersistence, n as SyncQuerySubset, o as RejectedOperation } from './transport-
|
|
2
|
-
export { A as AcknowledgmentMessage, p as AwarenessStateWire, q as AwarenessUpdateMessage, E as EncryptedPayload, r as ErrorMessage, H as HandshakeMessage, s as HandshakeResponseMessage, I as InvalidScopeError, M as MemoryRejectedOperationStorage, O as OperationBatchMessage, t as OperationRejectedMessage, u as SYNC_STATES, v as SYNC_STATUSES, w as ScopeViolationError, x as SyncEncryptionAlgorithm, y as SyncScopeContext, z as SyncStatus, C as dedupeQuerySubsets, F as isAcknowledgmentMessage, G as isAwarenessUpdateMessage, J as isBlobChunkPushMessage, K as isBlobChunkRequestMessage, L as isBlobChunkResponseMessage, N as isErrorMessage, P as isHandshakeMessage, U as isHandshakeResponseMessage, X as isOperationBatchMessage, Z as isOperationRejectedMessage, _ as isSyncMessage, $ as isYjsDocUpdateMessage, a0 as operationMatchesQuerySubsets } from './transport-
|
|
1
|
+
import { S as SyncScopeMap, D as DeltaCursor, a as SyncMessage, b as SerializedOperation, W as WireFormat, c as SyncTransport, T as TransportOptions, d as TransportMessageHandler, e as TransportCloseHandler, f as TransportErrorHandler, B as BlobChunkRequestMessage, g as BlobChunkResponseMessage, h as BlobChunkPushMessage, i as SyncEncryptionConfig, V as VersionedKey, Y as YjsDocUpdateMessage, Q as QueueStorage, j as SyncState, k as SyncStatusInfo, l as SyncConfig, R as RejectedOperationStorage, m as SyncStatePersistence, n as SyncQuerySubset, o as RejectedOperation } from './transport-ByWfWBbB.cjs';
|
|
2
|
+
export { A as AcknowledgmentMessage, p as AwarenessStateWire, q as AwarenessUpdateMessage, E as EncryptedPayload, r as ErrorMessage, H as HandshakeMessage, s as HandshakeResponseMessage, I as InvalidScopeError, M as MemoryRejectedOperationStorage, O as OperationBatchMessage, t as OperationRejectedMessage, u as SYNC_STATES, v as SYNC_STATUSES, w as ScopeViolationError, x as SyncEncryptionAlgorithm, y as SyncScopeContext, z as SyncStatus, C as dedupeQuerySubsets, F as isAcknowledgmentMessage, G as isAwarenessUpdateMessage, J as isBlobChunkPushMessage, K as isBlobChunkRequestMessage, L as isBlobChunkResponseMessage, N as isErrorMessage, P as isHandshakeMessage, U as isHandshakeResponseMessage, X as isOperationBatchMessage, Z as isOperationRejectedMessage, _ as isSyncMessage, $ as isYjsDocUpdateMessage, a0 as operationMatchesQuerySubsets } from './transport-ByWfWBbB.cjs';
|
|
3
3
|
import * as _korajs_core from '@korajs/core';
|
|
4
4
|
import { Operation, VersionVector, ApplyResult, KoraEventEmitter, TimeSource, SyncError, ConnectionQuality } from '@korajs/core';
|
|
5
5
|
export { ApplyFailureReason, ApplyResult } from '@korajs/core';
|
|
@@ -95,6 +95,17 @@ interface SyncStore {
|
|
|
95
95
|
idMapping: Record<string, string>;
|
|
96
96
|
rebasedCount: number;
|
|
97
97
|
}>;
|
|
98
|
+
/**
|
|
99
|
+
* Optional: read a record's current materialized field values, used to backfill
|
|
100
|
+
* scope / query-subset fields that a partial update (or a delete) does not carry
|
|
101
|
+
* in its own data. Without it, such an operation would be judged out of scope by
|
|
102
|
+
* its changed fields alone and wrongly dropped from sync. Optional so hand-rolled
|
|
103
|
+
* SyncStore implementations keep working; when absent, the engine falls back to
|
|
104
|
+
* judging visibility from the operation's own data.
|
|
105
|
+
*
|
|
106
|
+
* @returns the record's fields, or null when it cannot be read.
|
|
107
|
+
*/
|
|
108
|
+
readRecordFields?(collection: string, recordId: string): Promise<Record<string, unknown> | null>;
|
|
98
109
|
}
|
|
99
110
|
|
|
100
111
|
/** Prefix for handshake rejection when client schema version is unsupported. */
|
|
@@ -272,6 +283,14 @@ interface ChaosConfig {
|
|
|
272
283
|
maxLatency?: number;
|
|
273
284
|
/** Injectable random source for deterministic testing. Returns value in [0, 1). */
|
|
274
285
|
randomSource?: () => number;
|
|
286
|
+
/**
|
|
287
|
+
* Deterministic targeted drop. When it returns true for a message and direction,
|
|
288
|
+
* that message is dropped unconditionally (independent of `dropRate`). Enables
|
|
289
|
+
* reproducing an exact gap (e.g. drop one specific operation) instead of relying
|
|
290
|
+
* on probabilistic drops. `direction` is 'outgoing' for `send` and 'incoming' for
|
|
291
|
+
* messages arriving from the inner transport.
|
|
292
|
+
*/
|
|
293
|
+
dropPredicate?: (message: SyncMessage, direction: 'outgoing' | 'incoming') => boolean;
|
|
275
294
|
}
|
|
276
295
|
/**
|
|
277
296
|
* Chaos transport that wraps another transport and injects faults.
|
|
@@ -287,6 +306,7 @@ declare class ChaosTransport implements SyncTransport {
|
|
|
287
306
|
private readonly reorderRate;
|
|
288
307
|
private readonly maxLatency;
|
|
289
308
|
private readonly random;
|
|
309
|
+
private readonly dropPredicate;
|
|
290
310
|
private messageHandler;
|
|
291
311
|
private reorderBuffer;
|
|
292
312
|
private pending;
|
|
@@ -926,6 +946,7 @@ declare class SyncEngine {
|
|
|
926
946
|
private readonly outboundQueue;
|
|
927
947
|
private readonly rejectedStorage;
|
|
928
948
|
private readonly batchSize;
|
|
949
|
+
private readonly outboundAckTimeoutMs;
|
|
929
950
|
private readonly encryptor;
|
|
930
951
|
private readonly awarenessManager;
|
|
931
952
|
private readonly richtextDocChannel;
|
|
@@ -945,6 +966,9 @@ declare class SyncEngine {
|
|
|
945
966
|
private clockBlocked;
|
|
946
967
|
private clockSkewMs;
|
|
947
968
|
private blobStorageEnabled;
|
|
969
|
+
private outboundAckTimer;
|
|
970
|
+
private startPromise;
|
|
971
|
+
private stopPromise;
|
|
948
972
|
private deltaBatchesReceived;
|
|
949
973
|
private deltaReceiveComplete;
|
|
950
974
|
private deltaSendComplete;
|
|
@@ -964,15 +988,36 @@ declare class SyncEngine {
|
|
|
964
988
|
/** Resume cursor for paginated initial sync (persisted across reconnects) */
|
|
965
989
|
private resumeDeltaCursor;
|
|
966
990
|
private initialSyncTotalBatches;
|
|
991
|
+
/**
|
|
992
|
+
* The delivery watermark for the CURRENT sync view: the highest server delivery
|
|
993
|
+
* sequence up to which every operation in the current view (scope + active query
|
|
994
|
+
* subscriptions) has been contiguously applied. Advanced only through the server's
|
|
995
|
+
* gap-free delivery stream (never through live relay), so it is a durable lower bound
|
|
996
|
+
* on what this client holds for this view. Reported at handshake to resume the stream.
|
|
997
|
+
*
|
|
998
|
+
* The watermark is keyed by view: switching views (a scope or subscription change)
|
|
999
|
+
* saves the current view's watermark and loads the target view's, so returning to a
|
|
1000
|
+
* previously-synced view resumes exactly where it left off instead of re-syncing. This
|
|
1001
|
+
* is correct because a view's watermark is a lower bound specific to that view's
|
|
1002
|
+
* filter; a widened view is simply a different (initially unsynced) view.
|
|
1003
|
+
*/
|
|
1004
|
+
private deliveryWatermark;
|
|
1005
|
+
/**
|
|
1006
|
+
* In-memory cache of watermark per view signature, preloaded from persistence at start
|
|
1007
|
+
* so a view switch resolves synchronously (no race with the reconnect it triggers).
|
|
1008
|
+
*/
|
|
1009
|
+
private readonly deliverySignatureWatermarks;
|
|
967
1010
|
constructor(options: SyncEngineOptions);
|
|
968
1011
|
/**
|
|
969
1012
|
* Start the sync engine: connect → handshake → delta exchange → streaming.
|
|
970
1013
|
*/
|
|
971
1014
|
start(): Promise<void>;
|
|
1015
|
+
private startInternal;
|
|
972
1016
|
/**
|
|
973
1017
|
* Stop the sync engine. Disconnects the transport.
|
|
974
1018
|
*/
|
|
975
1019
|
stop(): Promise<void>;
|
|
1020
|
+
private stopInternal;
|
|
976
1021
|
private ensureDisconnected;
|
|
977
1022
|
/**
|
|
978
1023
|
* Push a local operation to the outbound queue.
|
|
@@ -1056,6 +1101,41 @@ declare class SyncEngine {
|
|
|
1056
1101
|
* @param scopeMap - New per-collection scope filters, or undefined to remove scope
|
|
1057
1102
|
*/
|
|
1058
1103
|
updateScope(scopeMap: SyncScopeMap | undefined): void;
|
|
1104
|
+
/**
|
|
1105
|
+
* A stable identifier for the current sync view: the auth/tenant scope plus the set of
|
|
1106
|
+
* active query subscriptions, canonicalized so the same view always produces the same
|
|
1107
|
+
* string. The delivery watermark is keyed by this, so each distinct view resumes from
|
|
1108
|
+
* its own last position.
|
|
1109
|
+
*/
|
|
1110
|
+
private deliverySignature;
|
|
1111
|
+
/**
|
|
1112
|
+
* Switch the active delivery watermark to the current view after a scope or subscription
|
|
1113
|
+
* change. The prior view's watermark is saved so returning to it resumes; the new view's
|
|
1114
|
+
* watermark is restored from the in-memory cache (0 for a never-synced view, which then
|
|
1115
|
+
* does a one-time resync under that view). No data is lost: a view's watermark is a lower
|
|
1116
|
+
* bound for that specific view's filter.
|
|
1117
|
+
*/
|
|
1118
|
+
private switchDeliveryView;
|
|
1119
|
+
/**
|
|
1120
|
+
* Record a view's watermark in the in-memory cache as the most-recently-used entry (the
|
|
1121
|
+
* Map preserves insertion order, so re-inserting moves it to the tail), then evict cold
|
|
1122
|
+
* views past the retention cap. This is the single place the cache is written, so LRU
|
|
1123
|
+
* order and the size bound are always maintained together.
|
|
1124
|
+
*/
|
|
1125
|
+
private setViewWatermark;
|
|
1126
|
+
/**
|
|
1127
|
+
* Trim the per-view watermark cache to `MAX_DELIVERY_VIEW_WATERMARKS`, evicting the
|
|
1128
|
+
* least-recently-used views. The default view ('') and the live view are never evicted
|
|
1129
|
+
* (evicting the live view would force an immediate re-scan of what we are actively
|
|
1130
|
+
* syncing). Each eviction also removes the persisted row, bounding storage. Safe by
|
|
1131
|
+
* construction: an evicted view simply back-fills from 0 (deduplicated) when next seen.
|
|
1132
|
+
*/
|
|
1133
|
+
private evictColdViewWatermarks;
|
|
1134
|
+
/**
|
|
1135
|
+
* Remove a view's persisted watermark row (best-effort; a persistence layer that omits
|
|
1136
|
+
* the delete simply keeps the row, which is harmless).
|
|
1137
|
+
*/
|
|
1138
|
+
private deleteDeliveryWatermark;
|
|
1059
1139
|
/**
|
|
1060
1140
|
* Get the currently active scope map. Returns undefined if no scope is configured.
|
|
1061
1141
|
*/
|
|
@@ -1119,6 +1199,8 @@ declare class SyncEngine {
|
|
|
1119
1199
|
private markDeltaSendCompleteIfReady;
|
|
1120
1200
|
private collectDelta;
|
|
1121
1201
|
private handleOperationBatch;
|
|
1202
|
+
/** Acknowledge a delivery batch (used for duplicates) without re-applying it. */
|
|
1203
|
+
private sendDeliveryAck;
|
|
1122
1204
|
private handleAcknowledgment;
|
|
1123
1205
|
private handleError;
|
|
1124
1206
|
/**
|
|
@@ -1160,13 +1242,20 @@ declare class SyncEngine {
|
|
|
1160
1242
|
*/
|
|
1161
1243
|
private reconcileOutboundFromOpLog;
|
|
1162
1244
|
private flushQueue;
|
|
1245
|
+
private startOutboundAckTimer;
|
|
1246
|
+
private clearOutboundAckTimer;
|
|
1247
|
+
private handleOutboundAckTimeout;
|
|
1163
1248
|
private handleAwarenessUpdate;
|
|
1164
1249
|
private handleTransportClose;
|
|
1165
1250
|
private handleTransportError;
|
|
1166
1251
|
private transitionTo;
|
|
1167
1252
|
private setSerializerWireFormat;
|
|
1168
1253
|
private operationAllowedForSync;
|
|
1254
|
+
private matchesScopeAndSubsets;
|
|
1255
|
+
private readRecordForBackfill;
|
|
1256
|
+
private filterAllowedForSync;
|
|
1169
1257
|
private persistDeltaCursor;
|
|
1258
|
+
private persistDeliveryWatermark;
|
|
1170
1259
|
private scheduleQuerySubsetReconnect;
|
|
1171
1260
|
private reconnectForQuerySubsets;
|
|
1172
1261
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { S as SyncScopeMap, D as DeltaCursor, a as SyncMessage, b as SerializedOperation, W as WireFormat, c as SyncTransport, T as TransportOptions, d as TransportMessageHandler, e as TransportCloseHandler, f as TransportErrorHandler, B as BlobChunkRequestMessage, g as BlobChunkResponseMessage, h as BlobChunkPushMessage, i as SyncEncryptionConfig, V as VersionedKey, Y as YjsDocUpdateMessage, Q as QueueStorage, j as SyncState, k as SyncStatusInfo, l as SyncConfig, R as RejectedOperationStorage, m as SyncStatePersistence, n as SyncQuerySubset, o as RejectedOperation } from './transport-
|
|
2
|
-
export { A as AcknowledgmentMessage, p as AwarenessStateWire, q as AwarenessUpdateMessage, E as EncryptedPayload, r as ErrorMessage, H as HandshakeMessage, s as HandshakeResponseMessage, I as InvalidScopeError, M as MemoryRejectedOperationStorage, O as OperationBatchMessage, t as OperationRejectedMessage, u as SYNC_STATES, v as SYNC_STATUSES, w as ScopeViolationError, x as SyncEncryptionAlgorithm, y as SyncScopeContext, z as SyncStatus, C as dedupeQuerySubsets, F as isAcknowledgmentMessage, G as isAwarenessUpdateMessage, J as isBlobChunkPushMessage, K as isBlobChunkRequestMessage, L as isBlobChunkResponseMessage, N as isErrorMessage, P as isHandshakeMessage, U as isHandshakeResponseMessage, X as isOperationBatchMessage, Z as isOperationRejectedMessage, _ as isSyncMessage, $ as isYjsDocUpdateMessage, a0 as operationMatchesQuerySubsets } from './transport-
|
|
1
|
+
import { S as SyncScopeMap, D as DeltaCursor, a as SyncMessage, b as SerializedOperation, W as WireFormat, c as SyncTransport, T as TransportOptions, d as TransportMessageHandler, e as TransportCloseHandler, f as TransportErrorHandler, B as BlobChunkRequestMessage, g as BlobChunkResponseMessage, h as BlobChunkPushMessage, i as SyncEncryptionConfig, V as VersionedKey, Y as YjsDocUpdateMessage, Q as QueueStorage, j as SyncState, k as SyncStatusInfo, l as SyncConfig, R as RejectedOperationStorage, m as SyncStatePersistence, n as SyncQuerySubset, o as RejectedOperation } from './transport-ByWfWBbB.js';
|
|
2
|
+
export { A as AcknowledgmentMessage, p as AwarenessStateWire, q as AwarenessUpdateMessage, E as EncryptedPayload, r as ErrorMessage, H as HandshakeMessage, s as HandshakeResponseMessage, I as InvalidScopeError, M as MemoryRejectedOperationStorage, O as OperationBatchMessage, t as OperationRejectedMessage, u as SYNC_STATES, v as SYNC_STATUSES, w as ScopeViolationError, x as SyncEncryptionAlgorithm, y as SyncScopeContext, z as SyncStatus, C as dedupeQuerySubsets, F as isAcknowledgmentMessage, G as isAwarenessUpdateMessage, J as isBlobChunkPushMessage, K as isBlobChunkRequestMessage, L as isBlobChunkResponseMessage, N as isErrorMessage, P as isHandshakeMessage, U as isHandshakeResponseMessage, X as isOperationBatchMessage, Z as isOperationRejectedMessage, _ as isSyncMessage, $ as isYjsDocUpdateMessage, a0 as operationMatchesQuerySubsets } from './transport-ByWfWBbB.js';
|
|
3
3
|
import * as _korajs_core from '@korajs/core';
|
|
4
4
|
import { Operation, VersionVector, ApplyResult, KoraEventEmitter, TimeSource, SyncError, ConnectionQuality } from '@korajs/core';
|
|
5
5
|
export { ApplyFailureReason, ApplyResult } from '@korajs/core';
|
|
@@ -95,6 +95,17 @@ interface SyncStore {
|
|
|
95
95
|
idMapping: Record<string, string>;
|
|
96
96
|
rebasedCount: number;
|
|
97
97
|
}>;
|
|
98
|
+
/**
|
|
99
|
+
* Optional: read a record's current materialized field values, used to backfill
|
|
100
|
+
* scope / query-subset fields that a partial update (or a delete) does not carry
|
|
101
|
+
* in its own data. Without it, such an operation would be judged out of scope by
|
|
102
|
+
* its changed fields alone and wrongly dropped from sync. Optional so hand-rolled
|
|
103
|
+
* SyncStore implementations keep working; when absent, the engine falls back to
|
|
104
|
+
* judging visibility from the operation's own data.
|
|
105
|
+
*
|
|
106
|
+
* @returns the record's fields, or null when it cannot be read.
|
|
107
|
+
*/
|
|
108
|
+
readRecordFields?(collection: string, recordId: string): Promise<Record<string, unknown> | null>;
|
|
98
109
|
}
|
|
99
110
|
|
|
100
111
|
/** Prefix for handshake rejection when client schema version is unsupported. */
|
|
@@ -272,6 +283,14 @@ interface ChaosConfig {
|
|
|
272
283
|
maxLatency?: number;
|
|
273
284
|
/** Injectable random source for deterministic testing. Returns value in [0, 1). */
|
|
274
285
|
randomSource?: () => number;
|
|
286
|
+
/**
|
|
287
|
+
* Deterministic targeted drop. When it returns true for a message and direction,
|
|
288
|
+
* that message is dropped unconditionally (independent of `dropRate`). Enables
|
|
289
|
+
* reproducing an exact gap (e.g. drop one specific operation) instead of relying
|
|
290
|
+
* on probabilistic drops. `direction` is 'outgoing' for `send` and 'incoming' for
|
|
291
|
+
* messages arriving from the inner transport.
|
|
292
|
+
*/
|
|
293
|
+
dropPredicate?: (message: SyncMessage, direction: 'outgoing' | 'incoming') => boolean;
|
|
275
294
|
}
|
|
276
295
|
/**
|
|
277
296
|
* Chaos transport that wraps another transport and injects faults.
|
|
@@ -287,6 +306,7 @@ declare class ChaosTransport implements SyncTransport {
|
|
|
287
306
|
private readonly reorderRate;
|
|
288
307
|
private readonly maxLatency;
|
|
289
308
|
private readonly random;
|
|
309
|
+
private readonly dropPredicate;
|
|
290
310
|
private messageHandler;
|
|
291
311
|
private reorderBuffer;
|
|
292
312
|
private pending;
|
|
@@ -926,6 +946,7 @@ declare class SyncEngine {
|
|
|
926
946
|
private readonly outboundQueue;
|
|
927
947
|
private readonly rejectedStorage;
|
|
928
948
|
private readonly batchSize;
|
|
949
|
+
private readonly outboundAckTimeoutMs;
|
|
929
950
|
private readonly encryptor;
|
|
930
951
|
private readonly awarenessManager;
|
|
931
952
|
private readonly richtextDocChannel;
|
|
@@ -945,6 +966,9 @@ declare class SyncEngine {
|
|
|
945
966
|
private clockBlocked;
|
|
946
967
|
private clockSkewMs;
|
|
947
968
|
private blobStorageEnabled;
|
|
969
|
+
private outboundAckTimer;
|
|
970
|
+
private startPromise;
|
|
971
|
+
private stopPromise;
|
|
948
972
|
private deltaBatchesReceived;
|
|
949
973
|
private deltaReceiveComplete;
|
|
950
974
|
private deltaSendComplete;
|
|
@@ -964,15 +988,36 @@ declare class SyncEngine {
|
|
|
964
988
|
/** Resume cursor for paginated initial sync (persisted across reconnects) */
|
|
965
989
|
private resumeDeltaCursor;
|
|
966
990
|
private initialSyncTotalBatches;
|
|
991
|
+
/**
|
|
992
|
+
* The delivery watermark for the CURRENT sync view: the highest server delivery
|
|
993
|
+
* sequence up to which every operation in the current view (scope + active query
|
|
994
|
+
* subscriptions) has been contiguously applied. Advanced only through the server's
|
|
995
|
+
* gap-free delivery stream (never through live relay), so it is a durable lower bound
|
|
996
|
+
* on what this client holds for this view. Reported at handshake to resume the stream.
|
|
997
|
+
*
|
|
998
|
+
* The watermark is keyed by view: switching views (a scope or subscription change)
|
|
999
|
+
* saves the current view's watermark and loads the target view's, so returning to a
|
|
1000
|
+
* previously-synced view resumes exactly where it left off instead of re-syncing. This
|
|
1001
|
+
* is correct because a view's watermark is a lower bound specific to that view's
|
|
1002
|
+
* filter; a widened view is simply a different (initially unsynced) view.
|
|
1003
|
+
*/
|
|
1004
|
+
private deliveryWatermark;
|
|
1005
|
+
/**
|
|
1006
|
+
* In-memory cache of watermark per view signature, preloaded from persistence at start
|
|
1007
|
+
* so a view switch resolves synchronously (no race with the reconnect it triggers).
|
|
1008
|
+
*/
|
|
1009
|
+
private readonly deliverySignatureWatermarks;
|
|
967
1010
|
constructor(options: SyncEngineOptions);
|
|
968
1011
|
/**
|
|
969
1012
|
* Start the sync engine: connect → handshake → delta exchange → streaming.
|
|
970
1013
|
*/
|
|
971
1014
|
start(): Promise<void>;
|
|
1015
|
+
private startInternal;
|
|
972
1016
|
/**
|
|
973
1017
|
* Stop the sync engine. Disconnects the transport.
|
|
974
1018
|
*/
|
|
975
1019
|
stop(): Promise<void>;
|
|
1020
|
+
private stopInternal;
|
|
976
1021
|
private ensureDisconnected;
|
|
977
1022
|
/**
|
|
978
1023
|
* Push a local operation to the outbound queue.
|
|
@@ -1056,6 +1101,41 @@ declare class SyncEngine {
|
|
|
1056
1101
|
* @param scopeMap - New per-collection scope filters, or undefined to remove scope
|
|
1057
1102
|
*/
|
|
1058
1103
|
updateScope(scopeMap: SyncScopeMap | undefined): void;
|
|
1104
|
+
/**
|
|
1105
|
+
* A stable identifier for the current sync view: the auth/tenant scope plus the set of
|
|
1106
|
+
* active query subscriptions, canonicalized so the same view always produces the same
|
|
1107
|
+
* string. The delivery watermark is keyed by this, so each distinct view resumes from
|
|
1108
|
+
* its own last position.
|
|
1109
|
+
*/
|
|
1110
|
+
private deliverySignature;
|
|
1111
|
+
/**
|
|
1112
|
+
* Switch the active delivery watermark to the current view after a scope or subscription
|
|
1113
|
+
* change. The prior view's watermark is saved so returning to it resumes; the new view's
|
|
1114
|
+
* watermark is restored from the in-memory cache (0 for a never-synced view, which then
|
|
1115
|
+
* does a one-time resync under that view). No data is lost: a view's watermark is a lower
|
|
1116
|
+
* bound for that specific view's filter.
|
|
1117
|
+
*/
|
|
1118
|
+
private switchDeliveryView;
|
|
1119
|
+
/**
|
|
1120
|
+
* Record a view's watermark in the in-memory cache as the most-recently-used entry (the
|
|
1121
|
+
* Map preserves insertion order, so re-inserting moves it to the tail), then evict cold
|
|
1122
|
+
* views past the retention cap. This is the single place the cache is written, so LRU
|
|
1123
|
+
* order and the size bound are always maintained together.
|
|
1124
|
+
*/
|
|
1125
|
+
private setViewWatermark;
|
|
1126
|
+
/**
|
|
1127
|
+
* Trim the per-view watermark cache to `MAX_DELIVERY_VIEW_WATERMARKS`, evicting the
|
|
1128
|
+
* least-recently-used views. The default view ('') and the live view are never evicted
|
|
1129
|
+
* (evicting the live view would force an immediate re-scan of what we are actively
|
|
1130
|
+
* syncing). Each eviction also removes the persisted row, bounding storage. Safe by
|
|
1131
|
+
* construction: an evicted view simply back-fills from 0 (deduplicated) when next seen.
|
|
1132
|
+
*/
|
|
1133
|
+
private evictColdViewWatermarks;
|
|
1134
|
+
/**
|
|
1135
|
+
* Remove a view's persisted watermark row (best-effort; a persistence layer that omits
|
|
1136
|
+
* the delete simply keeps the row, which is harmless).
|
|
1137
|
+
*/
|
|
1138
|
+
private deleteDeliveryWatermark;
|
|
1059
1139
|
/**
|
|
1060
1140
|
* Get the currently active scope map. Returns undefined if no scope is configured.
|
|
1061
1141
|
*/
|
|
@@ -1119,6 +1199,8 @@ declare class SyncEngine {
|
|
|
1119
1199
|
private markDeltaSendCompleteIfReady;
|
|
1120
1200
|
private collectDelta;
|
|
1121
1201
|
private handleOperationBatch;
|
|
1202
|
+
/** Acknowledge a delivery batch (used for duplicates) without re-applying it. */
|
|
1203
|
+
private sendDeliveryAck;
|
|
1122
1204
|
private handleAcknowledgment;
|
|
1123
1205
|
private handleError;
|
|
1124
1206
|
/**
|
|
@@ -1160,13 +1242,20 @@ declare class SyncEngine {
|
|
|
1160
1242
|
*/
|
|
1161
1243
|
private reconcileOutboundFromOpLog;
|
|
1162
1244
|
private flushQueue;
|
|
1245
|
+
private startOutboundAckTimer;
|
|
1246
|
+
private clearOutboundAckTimer;
|
|
1247
|
+
private handleOutboundAckTimeout;
|
|
1163
1248
|
private handleAwarenessUpdate;
|
|
1164
1249
|
private handleTransportClose;
|
|
1165
1250
|
private handleTransportError;
|
|
1166
1251
|
private transitionTo;
|
|
1167
1252
|
private setSerializerWireFormat;
|
|
1168
1253
|
private operationAllowedForSync;
|
|
1254
|
+
private matchesScopeAndSubsets;
|
|
1255
|
+
private readRecordForBackfill;
|
|
1256
|
+
private filterAllowedForSync;
|
|
1169
1257
|
private persistDeltaCursor;
|
|
1258
|
+
private persistDeliveryWatermark;
|
|
1170
1259
|
private scheduleQuerySubsetReconnect;
|
|
1171
1260
|
private reconnectForQuerySubsets;
|
|
1172
1261
|
}
|