@powerhousedao/reactor 6.0.0-dev.90 → 6.0.0-dev.91

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/src/index.js CHANGED
@@ -16723,6 +16723,17 @@ class BufferedMailbox {
16723
16723
  }
16724
16724
 
16725
16725
  // src/sync/errors.ts
16726
+ class GraphQLRequestError extends Error {
16727
+ statusCode;
16728
+ category;
16729
+ constructor(message, category, statusCode) {
16730
+ super(message);
16731
+ this.name = "GraphQLRequestError";
16732
+ this.category = category;
16733
+ this.statusCode = statusCode;
16734
+ }
16735
+ }
16736
+
16726
16737
  class PollingChannelError extends Error {
16727
16738
  constructor(message) {
16728
16739
  super(message);
@@ -17245,6 +17256,7 @@ class GqlRequestChannel {
17245
17256
  cursorStorage;
17246
17257
  operationIndex;
17247
17258
  pollTimer;
17259
+ abortController = new AbortController;
17248
17260
  isShutdown;
17249
17261
  failureCount;
17250
17262
  lastSuccessUtcMs;
@@ -17325,6 +17337,7 @@ class GqlRequestChannel {
17325
17337
  });
17326
17338
  }
17327
17339
  shutdown() {
17340
+ this.abortController.abort();
17328
17341
  this.bufferedOutbox.flush();
17329
17342
  this.isShutdown = true;
17330
17343
  this.pollTimer.stop();
@@ -17352,7 +17365,7 @@ class GqlRequestChannel {
17352
17365
  };
17353
17366
  }
17354
17367
  async init() {
17355
- await this.touchRemoteChannel();
17368
+ const { ackOrdinal } = await this.touchRemoteChannel();
17356
17369
  const cursors = await this.cursorStorage.list(this.remoteName);
17357
17370
  const inboxOrdinal = cursors.find((c) => c.cursorType === "inbox")?.cursorOrdinal ?? 0;
17358
17371
  const outboxOrdinal = cursors.find((c) => c.cursorType === "outbox")?.cursorOrdinal ?? 0;
@@ -17360,6 +17373,9 @@ class GqlRequestChannel {
17360
17373
  this.outbox.init(outboxOrdinal);
17361
17374
  this.lastPersistedInboxOrdinal = inboxOrdinal;
17362
17375
  this.lastPersistedOutboxOrdinal = outboxOrdinal;
17376
+ if (ackOrdinal > 0) {
17377
+ trimMailboxFromAckOrdinal(this.outbox, ackOrdinal);
17378
+ }
17363
17379
  this.pollTimer.setDelegate(() => this.poll());
17364
17380
  this.pollTimer.start();
17365
17381
  this.transitionConnectionState("connected");
@@ -17429,34 +17445,57 @@ class GqlRequestChannel {
17429
17445
  this.deadLetter.add(...syncOps);
17430
17446
  }
17431
17447
  handlePollError(error) {
17448
+ if (this.isShutdown)
17449
+ return true;
17432
17450
  const err = error instanceof Error ? error : new Error(String(error));
17433
17451
  if (err.message.includes("Channel not found")) {
17434
17452
  this.transitionConnectionState("reconnecting");
17435
17453
  this.recoverFromChannelNotFound();
17436
17454
  return true;
17437
17455
  }
17456
+ const classification = this.classifyError(err);
17438
17457
  this.failureCount++;
17439
17458
  this.lastFailureUtcMs = Date.now();
17440
- this.transitionConnectionState("error");
17441
17459
  const channelError = new ChannelError("inbox" /* Inbox */, err);
17442
- this.logger.error("GqlChannel poll error (@FailureCount): @Error", this.failureCount, channelError);
17460
+ this.logger.error("GqlChannel poll error (@FailureCount, @Classification): @Error", this.failureCount, classification, channelError);
17461
+ if (classification === "unrecoverable") {
17462
+ this.pollTimer.stop();
17463
+ this.transitionConnectionState("error");
17464
+ return true;
17465
+ }
17466
+ this.transitionConnectionState("error");
17443
17467
  return false;
17444
17468
  }
17445
17469
  recoverFromChannelNotFound() {
17446
17470
  this.logger.info("GqlChannel @ChannelId not found on remote, re-registering...", this.channelId);
17447
17471
  this.pollTimer.stop();
17448
- this.touchRemoteChannel().then(() => {
17449
- this.logger.info("GqlChannel @ChannelId re-registered successfully", this.channelId);
17450
- this.failureCount = 0;
17451
- this.pollTimer.start();
17452
- this.transitionConnectionState("connected");
17453
- }).catch((recoveryError) => {
17454
- this.logger.error("GqlChannel @ChannelId failed to re-register: @Error", this.channelId, recoveryError);
17455
- this.failureCount++;
17456
- this.lastFailureUtcMs = Date.now();
17457
- this.pollTimer.start();
17458
- this.transitionConnectionState("error");
17459
- });
17472
+ const attemptRecovery = (attempt) => {
17473
+ if (this.isShutdown)
17474
+ return;
17475
+ this.touchRemoteChannel().then(({ ackOrdinal }) => {
17476
+ this.logger.info("GqlChannel @ChannelId re-registered successfully", this.channelId);
17477
+ this.failureCount = 0;
17478
+ if (ackOrdinal > 0) {
17479
+ trimMailboxFromAckOrdinal(this.outbox, ackOrdinal);
17480
+ }
17481
+ this.pollTimer.start();
17482
+ this.transitionConnectionState("connected");
17483
+ }).catch((recoveryError) => {
17484
+ const err = recoveryError instanceof Error ? recoveryError : new Error(String(recoveryError));
17485
+ const classification = this.classifyError(err);
17486
+ this.logger.error("GqlChannel @ChannelId recovery attempt @Attempt failed (@Classification): @Error", this.channelId, attempt, classification, recoveryError);
17487
+ this.failureCount++;
17488
+ this.lastFailureUtcMs = Date.now();
17489
+ if (classification === "unrecoverable") {
17490
+ this.transitionConnectionState("error");
17491
+ return;
17492
+ }
17493
+ this.transitionConnectionState("reconnecting");
17494
+ const delay = calculateBackoffDelay(attempt, this.config.retryBaseDelayMs, this.config.retryMaxDelayMs, Math.random());
17495
+ setTimeout(() => attemptRecovery(attempt + 1), delay);
17496
+ });
17497
+ };
17498
+ attemptRecovery(1);
17460
17499
  }
17461
17500
  async pollSyncEnvelopes(ackOrdinal, latestOrdinal) {
17462
17501
  const query = `
@@ -17554,7 +17593,10 @@ class GqlRequestChannel {
17554
17593
  } catch {}
17555
17594
  const mutation = `
17556
17595
  mutation TouchChannel($input: TouchChannelInput!) {
17557
- touchChannel(input: $input)
17596
+ touchChannel(input: $input) {
17597
+ success
17598
+ ackOrdinal
17599
+ }
17558
17600
  }
17559
17601
  `;
17560
17602
  const variables = {
@@ -17570,7 +17612,11 @@ class GqlRequestChannel {
17570
17612
  sinceTimestampUtcMs
17571
17613
  }
17572
17614
  };
17573
- await this.executeGraphQL(mutation, variables);
17615
+ const data = await this.executeGraphQL(mutation, variables);
17616
+ if (!data.touchChannel.success) {
17617
+ throw new GraphQLRequestError("touchChannel returned success=false", "graphql");
17618
+ }
17619
+ return { ackOrdinal: data.touchChannel.ackOrdinal };
17574
17620
  }
17575
17621
  attemptPush(syncOps) {
17576
17622
  this.pushSyncOperations(syncOps).then(() => {
@@ -17580,8 +17626,11 @@ class GqlRequestChannel {
17580
17626
  this.transitionConnectionState("connected");
17581
17627
  }
17582
17628
  }).catch((error) => {
17629
+ if (this.isShutdown)
17630
+ return;
17583
17631
  const err = error instanceof Error ? error : new Error(String(error));
17584
- if (this.isRecoverablePushError(err)) {
17632
+ const classification = this.classifyError(err);
17633
+ if (classification === "recoverable") {
17585
17634
  this.pushFailureCount++;
17586
17635
  this.pushBlocked = true;
17587
17636
  this.logger.error("GqlChannel push failed (attempt @FailureCount), will retry: @Error", this.pushFailureCount, err);
@@ -17615,12 +17664,26 @@ class GqlRequestChannel {
17615
17664
  this.attemptPush([...allItems]);
17616
17665
  }, delay);
17617
17666
  }
17618
- isRecoverablePushError(error) {
17619
- if (error.message.startsWith("GraphQL errors:"))
17620
- return false;
17621
- if (error.message === "GraphQL response missing data field")
17622
- return false;
17623
- return true;
17667
+ classifyError(error) {
17668
+ if (!(error instanceof GraphQLRequestError)) {
17669
+ return "recoverable";
17670
+ }
17671
+ switch (error.category) {
17672
+ case "network":
17673
+ return "recoverable";
17674
+ case "http": {
17675
+ if (error.statusCode !== undefined && error.statusCode >= 500) {
17676
+ return "recoverable";
17677
+ }
17678
+ return "unrecoverable";
17679
+ }
17680
+ case "parse":
17681
+ return "recoverable";
17682
+ case "graphql":
17683
+ return "unrecoverable";
17684
+ case "missing-data":
17685
+ return "unrecoverable";
17686
+ }
17624
17687
  }
17625
17688
  async pushSyncOperations(syncOps) {
17626
17689
  for (const syncOp of syncOps) {
@@ -17697,26 +17760,27 @@ class GqlRequestChannel {
17697
17760
  body: JSON.stringify({
17698
17761
  query,
17699
17762
  variables
17700
- })
17763
+ }),
17764
+ signal: this.abortController.signal
17701
17765
  });
17702
17766
  } catch (error) {
17703
- throw new Error(`GraphQL request failed: ${error instanceof Error ? error.message : String(error)}`);
17767
+ throw new GraphQLRequestError(`GraphQL request failed: ${error instanceof Error ? error.message : String(error)}`, "network");
17704
17768
  }
17705
17769
  if (!response.ok) {
17706
- throw new Error(`GraphQL request failed: ${response.status} ${response.statusText}`);
17770
+ throw new GraphQLRequestError(`GraphQL request failed: ${response.status} ${response.statusText}`, "http", response.status);
17707
17771
  }
17708
17772
  let result;
17709
17773
  try {
17710
17774
  result = await response.json();
17711
17775
  } catch (error) {
17712
- throw new Error(`Failed to parse GraphQL response: ${error instanceof Error ? error.message : String(error)}`);
17776
+ throw new GraphQLRequestError(`Failed to parse GraphQL response: ${error instanceof Error ? error.message : String(error)}`, "parse");
17713
17777
  }
17714
17778
  this.logger.verbose("GQL response @channelId @operation status=@status data=@data errors=@errors", this.channelId, operationName, response.status, JSON.stringify(result.data), result.errors ? JSON.stringify(result.errors) : "none");
17715
17779
  if (result.errors) {
17716
- throw new Error(`GraphQL errors: ${JSON.stringify(result.errors, null, 2)}`);
17780
+ throw new GraphQLRequestError(`GraphQL errors: ${JSON.stringify(result.errors, null, 2)}`, "graphql");
17717
17781
  }
17718
17782
  if (!result.data) {
17719
- throw new Error("GraphQL response missing data field");
17783
+ throw new GraphQLRequestError("GraphQL response missing data field", "missing-data");
17720
17784
  }
17721
17785
  return result.data;
17722
17786
  }
@@ -18660,6 +18724,7 @@ class SyncManager {
18660
18724
  remotes;
18661
18725
  awaiter;
18662
18726
  syncAwaiter;
18727
+ abortController = new AbortController;
18663
18728
  isShutdown;
18664
18729
  eventUnsubscribe;
18665
18730
  failedEventUnsubscribe;
@@ -18720,6 +18785,7 @@ class SyncManager {
18720
18785
  }
18721
18786
  shutdown() {
18722
18787
  this.isShutdown = true;
18788
+ this.abortController.abort();
18723
18789
  this.batchAggregator.clear();
18724
18790
  if (this.eventUnsubscribe) {
18725
18791
  this.eventUnsubscribe();
@@ -18912,6 +18978,8 @@ class SyncManager {
18912
18978
  return Array.from(this.remotes.values()).filter((remote) => remote.collectionId === collectionId);
18913
18979
  }
18914
18980
  async processCompleteBatch(batch) {
18981
+ if (this.isShutdown)
18982
+ return;
18915
18983
  const collectionIds = [
18916
18984
  ...new Set(Object.values(batch.collectionMemberships).flatMap((collections) => collections))
18917
18985
  ];
@@ -18955,8 +19023,10 @@ class SyncManager {
18955
19023
  const operations = syncOp.operations.map((op) => op.operation);
18956
19024
  let jobInfo;
18957
19025
  try {
18958
- jobInfo = await this.reactor.load(syncOp.documentId, syncOp.branch, operations, undefined, { sourceRemote: remote.name });
19026
+ jobInfo = await this.reactor.load(syncOp.documentId, syncOp.branch, operations, this.abortController.signal, { sourceRemote: remote.name });
18959
19027
  } catch (error) {
19028
+ if (this.isShutdown)
19029
+ return;
18960
19030
  const err = error instanceof Error ? error : new Error(String(error));
18961
19031
  this.logger.error("Failed to load operations from inbox (@remote, @documentId, @error)", remote.name, syncOp.documentId, err.message);
18962
19032
  const channelError = new ChannelError("inbox" /* Inbox */, err);
@@ -18967,8 +19037,10 @@ class SyncManager {
18967
19037
  }
18968
19038
  let completedJobInfo;
18969
19039
  try {
18970
- completedJobInfo = await this.awaiter.waitForJob(jobInfo.id);
19040
+ completedJobInfo = await this.awaiter.waitForJob(jobInfo.id, this.abortController.signal);
18971
19041
  } catch (error) {
19042
+ if (this.isShutdown)
19043
+ return;
18972
19044
  const err = error instanceof Error ? error : new Error(String(error));
18973
19045
  this.logger.error("Failed to wait for job completion (@remote, @documentId, @jobId, @error)", remote.name, syncOp.documentId, jobInfo.id, err.message);
18974
19046
  const channelError = new ChannelError("inbox" /* Inbox */, err);
@@ -19003,10 +19075,10 @@ class SyncManager {
19003
19075
  const request = { jobs };
19004
19076
  let result;
19005
19077
  try {
19006
- result = await this.reactor.loadBatch(request, undefined, {
19007
- sourceRemote
19008
- });
19078
+ result = await this.reactor.loadBatch(request, this.abortController.signal, { sourceRemote });
19009
19079
  } catch (error) {
19080
+ if (this.isShutdown)
19081
+ return;
19010
19082
  for (const { remote, syncOp } of items) {
19011
19083
  const err = error instanceof Error ? error : new Error(String(error));
19012
19084
  syncOp.failed(new ChannelError("inbox" /* Inbox */, err));
@@ -19027,8 +19099,10 @@ class SyncManager {
19027
19099
  const jobInfo = result.jobs[syncOp.jobId];
19028
19100
  let completedJobInfo;
19029
19101
  try {
19030
- completedJobInfo = await this.awaiter.waitForJob(jobInfo.id);
19102
+ completedJobInfo = await this.awaiter.waitForJob(jobInfo.id, this.abortController.signal);
19031
19103
  } catch (error) {
19104
+ if (this.isShutdown)
19105
+ continue;
19032
19106
  const err = error instanceof Error ? error : new Error(String(error));
19033
19107
  syncOp.failed(new ChannelError("inbox" /* Inbox */, err));
19034
19108
  remote.channel.deadLetter.add(syncOp);
@@ -19075,7 +19149,7 @@ class SyncManager {
19075
19149
  remote.channel.outbox.add(...syncOps);
19076
19150
  }
19077
19151
  async getOperationsForRemote(remote, ackOrdinal) {
19078
- const results = await this.operationIndex.find(remote.collectionId, ackOrdinal, { excludeSourceRemote: remote.name });
19152
+ const results = await this.operationIndex.find(remote.collectionId, ackOrdinal, { excludeSourceRemote: remote.name }, undefined, this.abortController.signal);
19079
19153
  let operations = results.results.map((entry) => toOperationWithContext(entry));
19080
19154
  const sinceTimestamp = remote.options.sinceTimestampUtcMs;
19081
19155
  if (sinceTimestamp && sinceTimestamp !== "0") {
@@ -39,6 +39,7 @@ export declare class GqlRequestChannel implements IChannel {
39
39
  private readonly cursorStorage;
40
40
  private readonly operationIndex;
41
41
  private readonly pollTimer;
42
+ private readonly abortController;
42
43
  private isShutdown;
43
44
  private failureCount;
44
45
  private lastSuccessUtcMs?;
@@ -72,11 +73,13 @@ export declare class GqlRequestChannel implements IChannel {
72
73
  */
73
74
  private handleRemoteDeadLetters;
74
75
  /**
75
- * Handles polling errors with exponential backoff.
76
+ * Handles polling errors with error classification.
77
+ * Returns true if the error was handled (caller should not rethrow).
76
78
  */
77
79
  private handlePollError;
78
80
  /**
79
81
  * Recovers from a "Channel not found" error by re-registering and restarting polling.
82
+ * Self-retries with backoff instead of restarting the poll timer on failure.
80
83
  */
81
84
  private recoverFromChannelNotFound;
82
85
  /**
@@ -85,6 +88,7 @@ export declare class GqlRequestChannel implements IChannel {
85
88
  private pollSyncEnvelopes;
86
89
  /**
87
90
  * Registers or updates this channel on the remote server via GraphQL mutation.
91
+ * Returns the remote's ack ordinal so the client can trim its outbox.
88
92
  */
89
93
  private touchRemoteChannel;
90
94
  /**
@@ -99,10 +103,11 @@ export declare class GqlRequestChannel implements IChannel {
99
103
  */
100
104
  private schedulePushRetry;
101
105
  /**
102
- * Returns true if the error is recoverable (transient network/HTTP/parse
103
- * failure). Returns false for explicit GraphQL server rejections.
106
+ * Classifies an error as recoverable or unrecoverable based on its type.
107
+ * Recoverable errors are transient and worth retrying (network, 5xx, parse).
108
+ * Unrecoverable errors will not self-heal (auth, client errors, GraphQL rejections).
104
109
  */
105
- private isRecoverablePushError;
110
+ private classifyError;
106
111
  /**
107
112
  * Pushes multiple sync operations to the remote via a single GraphQL mutation.
108
113
  * Creates one SyncEnvelope per SyncOperation with key/dependsOn for batch ordering.
@@ -1 +1 @@
1
- {"version":3,"file":"gql-req-channel.d.ts","sourceRoot":"","sources":["../../../../src/sync/channels/gql-req-channel.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"gql-req-channel.d.ts","sourceRoot":"","sources":["../../../../src/sync/channels/gql-req-channel.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,10 @@
1
1
  import type { ChannelErrorSource } from "./types.js";
2
+ export type GraphQLRequestErrorCategory = "network" | "http" | "parse" | "graphql" | "missing-data";
3
+ export declare class GraphQLRequestError extends Error {
4
+ readonly statusCode: number | undefined;
5
+ readonly category: GraphQLRequestErrorCategory;
6
+ constructor(message: string, category: GraphQLRequestErrorCategory, statusCode?: number);
7
+ }
2
8
  export declare class PollingChannelError extends Error {
3
9
  constructor(message: string);
4
10
  }
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/sync/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD,qBAAa,mBAAoB,SAAQ,KAAK;gBAChC,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,YAAa,SAAQ,KAAK;IACrC,MAAM,EAAE,kBAAkB,CAAC;IAC3B,KAAK,EAAE,KAAK,CAAC;gBAED,MAAM,EAAE,kBAAkB,EAAE,KAAK,EAAE,KAAK;CAMrD"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/sync/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD,MAAM,MAAM,2BAA2B,GACnC,SAAS,GACT,MAAM,GACN,OAAO,GACP,SAAS,GACT,cAAc,CAAC;AAEnB,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,QAAQ,EAAE,2BAA2B,CAAC;gBAG7C,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,2BAA2B,EACrC,UAAU,CAAC,EAAE,MAAM;CAOtB;AAED,qBAAa,mBAAoB,SAAQ,KAAK;gBAChC,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,YAAa,SAAQ,KAAK;IACrC,MAAM,EAAE,kBAAkB,CAAC;IAC3B,KAAK,EAAE,KAAK,CAAC;gBAED,MAAM,EAAE,kBAAkB,EAAE,KAAK,EAAE,KAAK;CAMrD"}
@@ -19,6 +19,7 @@ export declare class SyncManager implements ISyncManager {
19
19
  private readonly remotes;
20
20
  private readonly awaiter;
21
21
  private readonly syncAwaiter;
22
+ private readonly abortController;
22
23
  private isShutdown;
23
24
  private eventUnsubscribe?;
24
25
  private failedEventUnsubscribe?;
@@ -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":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@powerhousedao/reactor",
3
- "version": "6.0.0-dev.90",
3
+ "version": "6.0.0-dev.91",
4
4
  "description": "",
5
5
  "repository": {
6
6
  "url": "https://github.com/powerhouse-inc/powerhouse",
@@ -33,14 +33,14 @@
33
33
  "tsx": "4.21.0",
34
34
  "vitest": "3.2.4",
35
35
  "@types/bun": "1.3.8",
36
- "document-model": "6.0.0-dev.90",
37
- "@powerhousedao/shared": "6.0.0-dev.90",
38
- "document-drive": "6.0.0-dev.90"
36
+ "@powerhousedao/shared": "6.0.0-dev.91",
37
+ "document-model": "6.0.0-dev.91",
38
+ "document-drive": "6.0.0-dev.91"
39
39
  },
40
40
  "peerDependencies": {
41
41
  "@electric-sql/pglite": ">=0.3.15",
42
- "document-model": "6.0.0-dev.90",
43
- "document-drive": "6.0.0-dev.90"
42
+ "document-model": "6.0.0-dev.91",
43
+ "document-drive": "6.0.0-dev.91"
44
44
  },
45
45
  "scripts": {
46
46
  "prebuild": "pnpm run clean",