@powerhousedao/reactor 6.0.0-dev.43 → 6.0.0-dev.44

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.
Files changed (97) hide show
  1. package/dist/src/cache/kysely-operation-index.d.ts.map +1 -1
  2. package/dist/src/cache/kysely-operation-index.js +7 -2
  3. package/dist/src/cache/kysely-operation-index.js.map +1 -1
  4. package/dist/src/cache/operation-index-types.d.ts +2 -0
  5. package/dist/src/cache/operation-index-types.d.ts.map +1 -1
  6. package/dist/src/cache/operation-index-types.js.map +1 -1
  7. package/dist/src/executor/document-action-handler.d.ts +1 -1
  8. package/dist/src/executor/document-action-handler.d.ts.map +1 -1
  9. package/dist/src/executor/document-action-handler.js +16 -11
  10. package/dist/src/executor/document-action-handler.js.map +1 -1
  11. package/dist/src/executor/simple-job-executor.d.ts.map +1 -1
  12. package/dist/src/executor/simple-job-executor.js +32 -19
  13. package/dist/src/executor/simple-job-executor.js.map +1 -1
  14. package/dist/src/index.d.ts +2 -2
  15. package/dist/src/index.d.ts.map +1 -1
  16. package/dist/src/index.js +1 -1
  17. package/dist/src/index.js.map +1 -1
  18. package/dist/src/storage/interfaces.d.ts +3 -1
  19. package/dist/src/storage/interfaces.d.ts.map +1 -1
  20. package/dist/src/storage/kysely/sync-cursor-storage.d.ts +1 -1
  21. package/dist/src/storage/kysely/sync-cursor-storage.d.ts.map +1 -1
  22. package/dist/src/storage/kysely/sync-cursor-storage.js +6 -2
  23. package/dist/src/storage/kysely/sync-cursor-storage.js.map +1 -1
  24. package/dist/src/storage/kysely/types.d.ts +2 -0
  25. package/dist/src/storage/kysely/types.d.ts.map +1 -1
  26. package/dist/src/storage/migrations/011_add_cursor_type_column.d.ts +3 -0
  27. package/dist/src/storage/migrations/011_add_cursor_type_column.d.ts.map +1 -0
  28. package/dist/src/storage/migrations/011_add_cursor_type_column.js +29 -0
  29. package/dist/src/storage/migrations/011_add_cursor_type_column.js.map +1 -0
  30. package/dist/src/storage/migrations/012_add_source_remote_column.d.ts +3 -0
  31. package/dist/src/storage/migrations/012_add_source_remote_column.d.ts.map +1 -0
  32. package/dist/src/storage/migrations/012_add_source_remote_column.js +7 -0
  33. package/dist/src/storage/migrations/012_add_source_remote_column.js.map +1 -0
  34. package/dist/src/storage/migrations/migrator.d.ts.map +1 -1
  35. package/dist/src/storage/migrations/migrator.js +4 -0
  36. package/dist/src/storage/migrations/migrator.js.map +1 -1
  37. package/dist/src/sync/batch-aggregator.d.ts +25 -0
  38. package/dist/src/sync/batch-aggregator.d.ts.map +1 -0
  39. package/dist/src/sync/batch-aggregator.js +94 -0
  40. package/dist/src/sync/batch-aggregator.js.map +1 -0
  41. package/dist/src/sync/buffered-mailbox.d.ts +14 -8
  42. package/dist/src/sync/buffered-mailbox.d.ts.map +1 -1
  43. package/dist/src/sync/buffered-mailbox.js +34 -6
  44. package/dist/src/sync/buffered-mailbox.js.map +1 -1
  45. package/dist/src/sync/channels/composite-channel-factory.d.ts +0 -6
  46. package/dist/src/sync/channels/composite-channel-factory.d.ts.map +1 -1
  47. package/dist/src/sync/channels/composite-channel-factory.js +4 -10
  48. package/dist/src/sync/channels/composite-channel-factory.js.map +1 -1
  49. package/dist/src/sync/channels/gql-channel-factory.js +2 -2
  50. package/dist/src/sync/channels/gql-channel-factory.js.map +1 -1
  51. package/dist/src/sync/channels/{gql-channel.d.ts → gql-req-channel.d.ts} +8 -27
  52. package/dist/src/sync/channels/gql-req-channel.d.ts.map +1 -0
  53. package/dist/src/sync/channels/{gql-channel.js → gql-req-channel.js} +142 -182
  54. package/dist/src/sync/channels/gql-req-channel.js.map +1 -0
  55. package/dist/src/sync/channels/gql-res-channel.d.ts +25 -0
  56. package/dist/src/sync/channels/gql-res-channel.d.ts.map +1 -0
  57. package/dist/src/sync/channels/gql-res-channel.js +79 -0
  58. package/dist/src/sync/channels/gql-res-channel.js.map +1 -0
  59. package/dist/src/sync/channels/index.d.ts +5 -5
  60. package/dist/src/sync/channels/index.d.ts.map +1 -1
  61. package/dist/src/sync/channels/index.js +5 -5
  62. package/dist/src/sync/channels/index.js.map +1 -1
  63. package/dist/src/sync/channels/utils.d.ts +15 -1
  64. package/dist/src/sync/channels/utils.d.ts.map +1 -1
  65. package/dist/src/sync/channels/utils.js +66 -2
  66. package/dist/src/sync/channels/utils.js.map +1 -1
  67. package/dist/src/sync/index.d.ts +6 -6
  68. package/dist/src/sync/index.d.ts.map +1 -1
  69. package/dist/src/sync/index.js +5 -5
  70. package/dist/src/sync/index.js.map +1 -1
  71. package/dist/src/sync/interfaces.d.ts +4 -18
  72. package/dist/src/sync/interfaces.d.ts.map +1 -1
  73. package/dist/src/sync/mailbox.d.ts +39 -18
  74. package/dist/src/sync/mailbox.d.ts.map +1 -1
  75. package/dist/src/sync/mailbox.js +50 -20
  76. package/dist/src/sync/mailbox.js.map +1 -1
  77. package/dist/src/sync/sync-manager.d.ts +5 -13
  78. package/dist/src/sync/sync-manager.d.ts.map +1 -1
  79. package/dist/src/sync/sync-manager.js +91 -275
  80. package/dist/src/sync/sync-manager.js.map +1 -1
  81. package/dist/src/sync/sync-operation.d.ts.map +1 -1
  82. package/dist/src/sync/sync-operation.js +3 -0
  83. package/dist/src/sync/sync-operation.js.map +1 -1
  84. package/dist/src/sync/types.d.ts +1 -0
  85. package/dist/src/sync/types.d.ts.map +1 -1
  86. package/dist/src/sync/types.js.map +1 -1
  87. package/dist/src/sync/utils.d.ts +18 -2
  88. package/dist/src/sync/utils.d.ts.map +1 -1
  89. package/dist/src/sync/utils.js +120 -1
  90. package/dist/src/sync/utils.js.map +1 -1
  91. package/package.json +3 -3
  92. package/dist/src/sync/channels/gql-channel.d.ts.map +0 -1
  93. package/dist/src/sync/channels/gql-channel.js.map +0 -1
  94. package/dist/src/sync/channels/polling-channel.d.ts +0 -39
  95. package/dist/src/sync/channels/polling-channel.d.ts.map +0 -1
  96. package/dist/src/sync/channels/polling-channel.js +0 -72
  97. package/dist/src/sync/channels/polling-channel.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"mailbox.js","sourceRoot":"","sources":["../../../src/sync/mailbox.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mailbox.js","sourceRoot":"","sources":["../../../src/sync/mailbox.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { type IOperationIndex } from "../cache/operation-index-types.js";
1
+ import type { IOperationIndex } from "../cache/operation-index-types.js";
2
2
  import type { IReactor } from "../core/types.js";
3
3
  import type { IEventBus } from "../events/interfaces.js";
4
4
  import type { ILogger } from "../logging/types.js";
@@ -17,13 +17,10 @@ export declare class SyncManager implements ISyncManager {
17
17
  private readonly remotes;
18
18
  private readonly awaiter;
19
19
  private readonly syncAwaiter;
20
- private readonly jobSyncStates;
21
20
  private isShutdown;
22
21
  private eventUnsubscribe?;
23
22
  private failedEventUnsubscribe?;
24
- private writeReadyQueue;
25
- private processingWriteReady;
26
- private readonly pendingBatches;
23
+ private readonly batchAggregator;
27
24
  loadJobs: Map<string, JobInfo>;
28
25
  constructor(logger: ILogger, remoteStorage: ISyncRemoteStorage, cursorStorage: ISyncCursorStorage, channelFactory: IChannelFactory, operationIndex: IOperationIndex, reactor: IReactor, eventBus: IEventBus);
29
26
  startup(): Promise<void>;
@@ -31,21 +28,16 @@ export declare class SyncManager implements ISyncManager {
31
28
  getByName(name: string): Remote;
32
29
  getById(id: string): Remote;
33
30
  add(name: string, collectionId: string, channelConfig: ChannelConfig, filter?: RemoteFilter, options?: RemoteOptions, id?: string): Promise<Remote>;
34
- private backfillOutbox;
35
31
  remove(name: string): Promise<void>;
36
32
  list(): Remote[];
37
33
  waitForSync(jobId: string, signal?: AbortSignal): Promise<SyncResult>;
38
34
  private wireChannelCallbacks;
39
- private enqueueWriteReady;
40
- private processWriteReadyQueue;
41
- private handleWriteReadyAsync;
42
- private handleJobFailedForBatch;
35
+ private getRemotesForCollection;
43
36
  private processCompleteBatch;
44
37
  private handleInboxAdded;
45
- private handleOutboxJob;
46
38
  private applyInboxJob;
47
39
  private applyInboxBatch;
48
- private markSyncOpCompleted;
49
- private filterByCollectionMembership;
40
+ private updateOutbox;
41
+ private getOperationsForRemote;
50
42
  }
51
43
  //# sourceMappingURL=sync-manager.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sync-manager.d.ts","sourceRoot":"","sources":["../../../src/sync/sync-manager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sync-manager.d.ts","sourceRoot":"","sources":["../../../src/sync/sync-manager.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,KAAK,EAGV,QAAQ,EACT,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAMzD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAEnD,OAAO,EAEL,KAAK,OAAO,EACZ,KAAK,cAAc,EACpB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EACV,kBAAkB,EAClB,kBAAkB,EACnB,MAAM,0BAA0B,CAAC;AAGlC,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAG7E,OAAO,KAAK,EACV,aAAa,EACb,YAAY,EACZ,aAAa,EAGb,UAAU,EACX,MAAM,YAAY,CAAC;AAUpB,qBAAa,WAAY,YAAW,YAAY;IAC9C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAU;IACjC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAqB;IACnD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAqB;IACnD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAkB;IACjD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAkB;IACjD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAW;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAY;IACrC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsB;IAC9C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAa;IACrC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAc;IAC1C,OAAO,CAAC,UAAU,CAAU;IAC5B,OAAO,CAAC,gBAAgB,CAAC,CAAa;IACtC,OAAO,CAAC,sBAAsB,CAAC,CAAa;IAC5C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAkB;IAE3C,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAa;gBAGhD,MAAM,EAAE,OAAO,EACf,aAAa,EAAE,kBAAkB,EACjC,aAAa,EAAE,kBAAkB,EACjC,cAAc,EAAE,eAAe,EAC/B,cAAc,EAAE,eAAe,EAC/B,OAAO,EAAE,QAAQ,EACjB,QAAQ,EAAE,SAAS;IAoBf,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IA4D9B,QAAQ,IAAI,cAAc;IA8B1B,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAQ/B,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM;IASrB,GAAG,CACP,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,aAAa,EAC5B,MAAM,GAAE,YAAwD,EAChE,OAAO,GAAE,aAA4C,EACrD,EAAE,CAAC,EAAE,MAAM,GACV,OAAO,CAAC,MAAM,CAAC;IA0EZ,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBzC,IAAI,IAAI,MAAM,EAAE;IAIhB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;IAIrE,OAAO,CAAC,oBAAoB;IAuB5B,OAAO,CAAC,uBAAuB;YAMjB,oBAAoB;IAgClC,OAAO,CAAC,gBAAgB;YAyBV,aAAa;YA0Eb,eAAe;YAgFf,YAAY;YAmCZ,sBAAsB;CAyBrC"}
@@ -1,12 +1,12 @@
1
- import { driveCollectionId, } from "../cache/operation-index-types.js";
2
1
  import { ReactorEventTypes, } from "../events/types.js";
3
2
  import { JobAwaiter } from "../shared/awaiter.js";
4
3
  import { JobStatus, } from "../shared/types.js";
4
+ import { BatchAggregator } from "./batch-aggregator.js";
5
5
  import { ChannelError } from "./errors.js";
6
6
  import { SyncAwaiter } from "./sync-awaiter.js";
7
7
  import { SyncOperation } from "./sync-operation.js";
8
- import { ChannelErrorSource, SyncEventTypes, SyncOperationStatus, } from "./types.js";
9
- import { batchOperationsByDocument, createIdleHealth, filterOperations, } from "./utils.js";
8
+ import { ChannelErrorSource } from "./types.js";
9
+ import { batchOperationsByDocument, createIdleHealth, filterOperations, toOperationWithContext, trimMailboxFromBatch, } from "./utils.js";
10
10
  export class SyncManager {
11
11
  logger;
12
12
  remoteStorage;
@@ -18,13 +18,10 @@ export class SyncManager {
18
18
  remotes;
19
19
  awaiter;
20
20
  syncAwaiter;
21
- jobSyncStates;
22
21
  isShutdown;
23
22
  eventUnsubscribe;
24
23
  failedEventUnsubscribe;
25
- writeReadyQueue = [];
26
- processingWriteReady = false;
27
- pendingBatches = new Map();
24
+ batchAggregator;
28
25
  loadJobs = new Map();
29
26
  constructor(logger, remoteStorage, cursorStorage, channelFactory, operationIndex, reactor, eventBus) {
30
27
  this.logger = logger;
@@ -37,8 +34,8 @@ export class SyncManager {
37
34
  this.remotes = new Map();
38
35
  this.awaiter = new JobAwaiter(eventBus, (jobId, signal) => reactor.getJobStatus(jobId, signal));
39
36
  this.syncAwaiter = new SyncAwaiter(eventBus);
40
- this.jobSyncStates = new Map();
41
37
  this.isShutdown = false;
38
+ this.batchAggregator = new BatchAggregator(logger, (batch) => this.processCompleteBatch(batch));
42
39
  }
43
40
  async startup() {
44
41
  if (this.isShutdown) {
@@ -47,13 +44,6 @@ export class SyncManager {
47
44
  const remoteRecords = await this.remoteStorage.list();
48
45
  for (const record of remoteRecords) {
49
46
  const channel = this.channelFactory.instance(record.id, record.name, record.channelConfig, this.cursorStorage, record.collectionId, record.filter, this.operationIndex);
50
- try {
51
- await channel.init();
52
- }
53
- catch (error) {
54
- console.error(`Error initializing channel for remote ${record.name}: ${error instanceof Error ? error.message : String(error)}`);
55
- continue;
56
- }
57
47
  const remote = {
58
48
  id: record.id,
59
49
  name: record.name,
@@ -64,14 +54,26 @@ export class SyncManager {
64
54
  };
65
55
  this.remotes.set(record.name, remote);
66
56
  this.wireChannelCallbacks(remote);
57
+ try {
58
+ await channel.init();
59
+ }
60
+ catch (error) {
61
+ this.logger.error("Error initializing channel for remote (@name, @error)", record.name, error instanceof Error ? error.message : String(error));
62
+ this.remotes.delete(record.name);
63
+ continue;
64
+ }
65
+ // backfill channels
66
+ const outboxAckOrdinal = remote.channel.outbox.ackOrdinal;
67
+ if (outboxAckOrdinal > 0) {
68
+ await this.updateOutbox(remote, outboxAckOrdinal);
69
+ }
67
70
  }
68
- this.eventUnsubscribe = this.eventBus.subscribe(ReactorEventTypes.JOB_WRITE_READY, (_type, event) => this.enqueueWriteReady(event));
69
- this.failedEventUnsubscribe = this.eventBus.subscribe(ReactorEventTypes.JOB_FAILED, (_type, event) => this.handleJobFailedForBatch(event));
71
+ this.eventUnsubscribe = this.eventBus.subscribe(ReactorEventTypes.JOB_WRITE_READY, async (_type, event) => this.batchAggregator.enqueueWriteReady(event));
72
+ this.failedEventUnsubscribe = this.eventBus.subscribe(ReactorEventTypes.JOB_FAILED, async (_type, event) => this.batchAggregator.handleJobFailed(event));
70
73
  }
71
74
  shutdown() {
72
75
  this.isShutdown = true;
73
- this.writeReadyQueue = [];
74
- this.pendingBatches.clear();
76
+ this.batchAggregator.clear();
75
77
  if (this.eventUnsubscribe) {
76
78
  this.eventUnsubscribe();
77
79
  this.eventUnsubscribe = undefined;
@@ -82,18 +84,14 @@ export class SyncManager {
82
84
  }
83
85
  this.awaiter.shutdown();
84
86
  this.syncAwaiter.shutdown();
87
+ const promises = [];
85
88
  for (const remote of this.remotes.values()) {
86
- try {
87
- remote.channel.shutdown();
88
- }
89
- catch (error) {
90
- console.error(`Error shutting down channel for remote ${remote.name}: ${error instanceof Error ? error.message : String(error)}`);
91
- }
89
+ promises.push(remote.channel.shutdown());
92
90
  }
93
91
  this.remotes.clear();
94
92
  return {
95
93
  isShutdown: true,
96
- completed: Promise.resolve(),
94
+ completed: Promise.all(promises).then(() => undefined),
97
95
  };
98
96
  }
99
97
  getByName(name) {
@@ -135,7 +133,6 @@ export class SyncManager {
135
133
  };
136
134
  await this.remoteStorage.upsert(remoteRecord);
137
135
  const channel = this.channelFactory.instance(remoteId, name, channelConfig, this.cursorStorage, collectionId, filter, this.operationIndex);
138
- await channel.init();
139
136
  const remote = {
140
137
  id: remoteId,
141
138
  name,
@@ -146,55 +143,28 @@ export class SyncManager {
146
143
  };
147
144
  this.remotes.set(name, remote);
148
145
  this.wireChannelCallbacks(remote);
149
- await this.backfillOutbox(remote, collectionId, filter, options.sinceTimestampUtcMs);
150
- return remote;
151
- }
152
- async backfillOutbox(remote, collectionId, filter, sinceTimestampUtcMs) {
153
- let historicalOps;
154
146
  try {
155
- historicalOps = await this.operationIndex.find(collectionId);
156
- }
157
- catch {
158
- return;
147
+ await channel.init();
159
148
  }
160
- if (historicalOps.results.length === 0) {
161
- return;
162
- }
163
- const opsWithContext = historicalOps.results.map((entry) => ({
164
- operation: {
165
- id: entry.id,
166
- index: entry.index,
167
- skip: entry.skip,
168
- hash: entry.hash,
169
- timestampUtcMs: entry.timestampUtcMs,
170
- action: entry.action,
171
- },
172
- context: {
173
- documentId: entry.documentId,
174
- documentType: entry.documentType,
175
- scope: entry.scope,
176
- branch: entry.branch,
177
- ordinal: entry.ordinal ?? 0,
178
- },
179
- }));
180
- let filteredOps = filterOperations(opsWithContext, filter);
181
- filteredOps = filteredOps.filter((op) => op.operation.timestampUtcMs > sinceTimestampUtcMs);
182
- if (filteredOps.length === 0) {
183
- return;
184
- }
185
- const batches = batchOperationsByDocument(filteredOps);
186
- for (const batch of batches) {
187
- const syncOp = new SyncOperation(crypto.randomUUID(), "", [], remote.name, batch.documentId, [batch.scope], batch.branch, batch.operations);
188
- remote.channel.outbox.add(syncOp);
149
+ catch (error) {
150
+ this.remotes.delete(name);
151
+ await this.remoteStorage.remove(name);
152
+ throw error;
189
153
  }
154
+ // backfill
155
+ await this.updateOutbox(remote, 0);
156
+ return remote;
190
157
  }
191
158
  async remove(name) {
192
159
  const remote = this.remotes.get(name);
193
160
  if (!remote) {
194
161
  throw new Error(`Remote with name '${name}' does not exist`);
195
162
  }
163
+ // shutdown the channel
164
+ await remote.channel.shutdown();
165
+ // delete the remote's data
196
166
  await this.remoteStorage.remove(name);
197
- remote.channel.shutdown();
167
+ await this.cursorStorage.remove(name);
198
168
  this.remotes.delete(name);
199
169
  }
200
170
  list() {
@@ -204,168 +174,41 @@ export class SyncManager {
204
174
  return this.syncAwaiter.waitForSync(jobId, signal);
205
175
  }
206
176
  wireChannelCallbacks(remote) {
207
- remote.channel.inbox.onAdded((syncOps) => {
208
- this.handleInboxAdded(remote, syncOps);
177
+ remote.channel.inbox.onAdded((syncOps) => this.handleInboxAdded(remote, syncOps));
178
+ remote.channel.outbox.onAdded(() => {
179
+ // todo: handle sync status updates
209
180
  });
210
- remote.channel.outbox.onAdded((syncOps) => {
181
+ remote.channel.deadLetter.onAdded((syncOps) => {
211
182
  for (const syncOp of syncOps) {
212
- this.handleOutboxJob(remote, syncOp);
183
+ this.logger.error("Dead letter (@remote, @documentId, @jobId, @error, @dependencies)", remote.name, syncOp.documentId, syncOp.jobId, syncOp.error?.message ?? "unknown", syncOp.jobDependencies);
213
184
  }
214
185
  });
215
186
  }
216
- enqueueWriteReady(event) {
217
- this.writeReadyQueue.push(event);
218
- void this.processWriteReadyQueue();
219
- }
220
- processWriteReadyQueue() {
221
- if (this.processingWriteReady) {
222
- return;
223
- }
224
- this.processingWriteReady = true;
225
- while (this.writeReadyQueue.length > 0) {
226
- const event = this.writeReadyQueue.shift();
227
- this.handleWriteReadyAsync(event);
228
- }
229
- this.processingWriteReady = false;
230
- }
231
- handleWriteReadyAsync(event) {
232
- if (this.isShutdown) {
233
- return;
234
- }
235
- const { batchId, batchJobIds } = event.jobMeta;
236
- if (batchJobIds.length <= 1) {
237
- this.processCompleteBatch([event]);
238
- return;
239
- }
240
- let pending = this.pendingBatches.get(batchId);
241
- if (!pending) {
242
- pending = {
243
- expectedJobIds: new Set(batchJobIds),
244
- arrivedJobIds: new Set(),
245
- events: [],
246
- };
247
- this.pendingBatches.set(batchId, pending);
248
- }
249
- pending.arrivedJobIds.add(event.jobId);
250
- pending.events.push(event);
251
- if (pending.arrivedJobIds.size >= pending.expectedJobIds.size) {
252
- this.pendingBatches.delete(batchId);
253
- this.processCompleteBatch(pending.events);
254
- }
255
- }
256
- handleJobFailedForBatch(event) {
257
- if (this.isShutdown) {
258
- return;
259
- }
260
- const batchId = event.job?.meta.batchId;
261
- if (!batchId) {
262
- return;
263
- }
264
- const pending = this.pendingBatches.get(batchId);
265
- if (!pending) {
266
- return;
267
- }
268
- this.pendingBatches.delete(batchId);
269
- if (pending.events.length > 0) {
270
- void this.processCompleteBatch(pending.events);
271
- }
187
+ getRemotesForCollection(collectionId) {
188
+ return Array.from(this.remotes.values()).filter((remote) => remote.collectionId === collectionId);
272
189
  }
273
- processCompleteBatch(events) {
274
- const isBatch = events.length > 1;
275
- const mergedMemberships = {};
276
- for (const event of events) {
277
- if (event.collectionMemberships) {
278
- for (const [docId, collections] of Object.entries(event.collectionMemberships)) {
279
- if (!(docId in mergedMemberships)) {
280
- mergedMemberships[docId] = [];
281
- }
282
- for (const c of collections) {
283
- if (!mergedMemberships[docId].includes(c)) {
284
- mergedMemberships[docId].push(c);
285
- }
286
- }
287
- }
288
- }
289
- for (const op of event.operations) {
290
- const action = op.operation.action;
291
- if (action.type !== "ADD_RELATIONSHIP") {
292
- continue;
293
- }
294
- const input = action.input;
295
- if (!input?.sourceId || !input.targetId) {
296
- continue;
297
- }
298
- const collectionId = driveCollectionId(op.context.branch, input.sourceId);
299
- if (!(input.targetId in mergedMemberships)) {
300
- mergedMemberships[input.targetId] = [];
301
- }
302
- if (!mergedMemberships[input.targetId].includes(collectionId)) {
303
- mergedMemberships[input.targetId].push(collectionId);
190
+ async processCompleteBatch(batch) {
191
+ // get the unique set of collection ids
192
+ const collectionIds = [
193
+ ...new Set(Object.values(batch.collectionMemberships).flatMap((collections) => collections)),
194
+ ];
195
+ // get the unique set of affected remotes
196
+ const affectedRemotes = [];
197
+ for (const collectionId of collectionIds) {
198
+ const remotes = this.getRemotesForCollection(collectionId);
199
+ for (const remote of remotes) {
200
+ if (!affectedRemotes.includes(remote)) {
201
+ affectedRemotes.push(remote);
304
202
  }
305
203
  }
306
204
  }
307
- const priorJobIds = [];
308
- for (const event of events) {
309
- const sourceRemote = event.jobMeta.sourceRemote;
310
- const syncOpsWithRemote = [];
311
- const remoteNames = [];
312
- for (const remote of this.remotes.values()) {
313
- if (sourceRemote && remote.name === sourceRemote) {
314
- continue;
315
- }
316
- let filteredOps = filterOperations(event.operations, remote.filter);
317
- if (filteredOps.length === 0) {
318
- continue;
319
- }
320
- // If remote has empty documentId filter, it means "sync all docs in this collection"
321
- // In this case, we need to filter by collection membership
322
- if (remote.filter.documentId.length === 0) {
323
- filteredOps = this.filterByCollectionMembership(filteredOps, remote.collectionId, mergedMemberships);
324
- if (filteredOps.length === 0) {
325
- continue;
326
- }
327
- }
328
- const batches = batchOperationsByDocument(filteredOps);
329
- for (const batch of batches) {
330
- const syncOp = new SyncOperation(crypto.randomUUID(), event.jobId, isBatch ? [...priorJobIds] : [], remote.name, batch.documentId, [batch.scope], batch.branch, batch.operations);
331
- syncOpsWithRemote.push({ syncOp, remote });
332
- if (!remoteNames.includes(remote.name)) {
333
- remoteNames.push(remote.name);
334
- }
335
- }
336
- }
337
- if (syncOpsWithRemote.length > 0 && event.jobId) {
338
- this.jobSyncStates.set(event.jobId, {
339
- total: syncOpsWithRemote.length,
340
- completed: new Set(),
341
- failed: new Map(),
342
- remoteNames,
343
- });
344
- const pendingEvent = {
345
- jobId: event.jobId,
346
- syncOperationCount: syncOpsWithRemote.length,
347
- remoteNames,
348
- };
349
- void this.eventBus.emit(SyncEventTypes.SYNC_PENDING, pendingEvent);
350
- }
351
- for (const { syncOp, remote } of syncOpsWithRemote) {
352
- syncOp.on((op, _prev, next) => {
353
- if (next === SyncOperationStatus.Applied) {
354
- this.markSyncOpCompleted(op.jobId, op.id, true);
355
- }
356
- else if (next === SyncOperationStatus.Error) {
357
- this.markSyncOpCompleted(op.jobId, op.id, false, {
358
- remoteName: op.remoteName,
359
- documentId: op.documentId,
360
- error: op.error?.message ?? "Unknown error",
361
- });
362
- }
363
- });
364
- remote.channel.outbox.add(syncOp);
365
- }
366
- if (isBatch && event.jobId) {
367
- priorJobIds.push(event.jobId);
368
- }
205
+ // ack matching inbox items
206
+ for (const remote of affectedRemotes) {
207
+ trimMailboxFromBatch(remote.channel.inbox, batch);
208
+ }
209
+ // finally, work through the affected remotes and backfill based on the last operation in the outbox
210
+ for (const remote of affectedRemotes) {
211
+ await this.updateOutbox(remote, remote.channel.outbox.latestOrdinal);
369
212
  }
370
213
  }
371
214
  handleInboxAdded(remote, syncOps) {
@@ -389,16 +232,6 @@ export class SyncManager {
389
232
  void this.applyInboxBatch(keyed.map((syncOp) => ({ remote, syncOp })));
390
233
  }
391
234
  }
392
- handleOutboxJob(remote, syncOp) {
393
- syncOp.on((syncOp, _prev, next) => {
394
- if (next === SyncOperationStatus.Applied) {
395
- remote.channel.outbox.remove(syncOp);
396
- }
397
- else if (next === SyncOperationStatus.Error) {
398
- remote.channel.outbox.remove(syncOp);
399
- }
400
- });
401
- }
402
235
  async applyInboxJob(remote, syncOp) {
403
236
  const operations = syncOp.operations.map((op) => op.operation);
404
237
  let jobInfo;
@@ -449,7 +282,7 @@ export class SyncManager {
449
282
  scope: syncOp.scopes[0],
450
283
  branch: syncOp.branch,
451
284
  operations: syncOp.operations.map((op) => op.operation),
452
- dependsOn: syncOp.jobDependencies,
285
+ dependsOn: syncOp.jobDependencies.filter(Boolean),
453
286
  }));
454
287
  const request = { jobs };
455
288
  let result;
@@ -469,6 +302,11 @@ export class SyncManager {
469
302
  }
470
303
  for (const { remote, syncOp } of items) {
471
304
  if (!(syncOp.jobId in result.jobs)) {
305
+ this.logger.error("Job key missing from batch load result (@remote, @documentId, @jobId)", remote.name, syncOp.documentId, syncOp.jobId);
306
+ const error = new ChannelError(ChannelErrorSource.Inbox, new Error(`Job key '${syncOp.jobId}' missing from batch load result`));
307
+ syncOp.failed(error);
308
+ remote.channel.deadLetter.add(syncOp);
309
+ remote.channel.inbox.remove(syncOp);
472
310
  continue;
473
311
  }
474
312
  const jobInfo = result.jobs[syncOp.jobId];
@@ -497,55 +335,33 @@ export class SyncManager {
497
335
  remote.channel.inbox.remove(syncOp);
498
336
  }
499
337
  }
500
- markSyncOpCompleted(jobId, syncOpId, success, errorInfo) {
501
- if (!jobId) {
502
- return;
503
- }
504
- const state = this.jobSyncStates.get(jobId);
505
- if (!state) {
338
+ async updateOutbox(remote, ackOrdinal) {
339
+ const operations = await this.getOperationsForRemote(remote, ackOrdinal);
340
+ if (operations.length === 0) {
506
341
  return;
507
342
  }
508
- if (success) {
509
- state.completed.add(syncOpId);
510
- }
511
- else if (errorInfo) {
512
- state.failed.set(syncOpId, errorInfo);
513
- }
514
- const totalTerminal = state.completed.size + state.failed.size;
515
- if (totalTerminal === state.total) {
516
- if (state.failed.size === 0) {
517
- const succeededEvent = {
518
- jobId,
519
- syncOperationCount: state.total,
520
- };
521
- void this.eventBus.emit(SyncEventTypes.SYNC_SUCCEEDED, succeededEvent);
522
- }
523
- else {
524
- const failedEvent = {
525
- jobId,
526
- successCount: state.completed.size,
527
- failureCount: state.failed.size,
528
- errors: Array.from(state.failed.values()),
529
- };
530
- void this.eventBus.emit(SyncEventTypes.SYNC_FAILED, failedEvent);
531
- }
532
- this.jobSyncStates.delete(jobId);
343
+ // create sync operations, each batch has a dependency on the previous one
344
+ const batches = batchOperationsByDocument(operations);
345
+ let prevJobId;
346
+ const syncOps = [];
347
+ for (const batch of batches) {
348
+ const jobId = crypto.randomUUID();
349
+ const syncOp = new SyncOperation(crypto.randomUUID(), jobId, prevJobId ? [prevJobId] : [], remote.name, batch.documentId, [batch.scope], batch.branch, batch.operations);
350
+ syncOps.push(syncOp);
351
+ prevJobId = jobId;
533
352
  }
353
+ remote.channel.outbox.add(...syncOps);
534
354
  }
535
- filterByCollectionMembership(operations, collectionId, collectionMemberships) {
536
- // If no collection memberships provided, we can't verify membership
537
- // This maintains backwards compatibility but effectively disables routing
538
- // for remotes with empty documentId filter when membership info is missing
539
- if (!collectionMemberships) {
540
- return [];
541
- }
542
- return operations.filter((op) => {
543
- const documentId = op.context.documentId;
544
- if (!(documentId in collectionMemberships)) {
545
- return false;
546
- }
547
- return collectionMemberships[documentId].includes(collectionId);
548
- });
355
+ async getOperationsForRemote(remote, ackOrdinal) {
356
+ const results = await this.operationIndex.find(remote.collectionId, ackOrdinal, { excludeSourceRemote: remote.name });
357
+ let operations = results.results.map((entry) => toOperationWithContext(entry));
358
+ // apply the sinceTimestampUtcMs filter
359
+ const sinceTimestamp = remote.options.sinceTimestampUtcMs;
360
+ if (sinceTimestamp && sinceTimestamp !== "0") {
361
+ operations = operations.filter((op) => op.operation.timestampUtcMs >= sinceTimestamp);
362
+ }
363
+ // apply the remote filter
364
+ return filterOperations(operations, remote.filter);
549
365
  }
550
366
  }
551
367
  //# sourceMappingURL=sync-manager.js.map