@rocicorp/zero 1.11.0-canary.14 → 1.11.0-canary.16

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 (110) hide show
  1. package/out/replicache/src/bg-interval.d.ts +2 -1
  2. package/out/replicache/src/bg-interval.d.ts.map +1 -1
  3. package/out/replicache/src/bg-interval.js +13 -4
  4. package/out/replicache/src/bg-interval.js.map +1 -1
  5. package/out/replicache/src/dag/lazy-store.d.ts +17 -4
  6. package/out/replicache/src/dag/lazy-store.d.ts.map +1 -1
  7. package/out/replicache/src/dag/lazy-store.js +35 -9
  8. package/out/replicache/src/dag/lazy-store.js.map +1 -1
  9. package/out/replicache/src/dag/store-impl.d.ts.map +1 -1
  10. package/out/replicache/src/dag/store-impl.js +7 -1
  11. package/out/replicache/src/dag/store-impl.js.map +1 -1
  12. package/out/replicache/src/kv/sqlite-store.d.ts.map +1 -1
  13. package/out/replicache/src/kv/sqlite-store.js +4 -6
  14. package/out/replicache/src/kv/sqlite-store.js.map +1 -1
  15. package/out/replicache/src/persist/client-gc.d.ts +2 -1
  16. package/out/replicache/src/persist/client-gc.d.ts.map +1 -1
  17. package/out/replicache/src/persist/client-gc.js +2 -2
  18. package/out/replicache/src/persist/client-gc.js.map +1 -1
  19. package/out/replicache/src/persist/client-group-gc.d.ts +2 -1
  20. package/out/replicache/src/persist/client-group-gc.d.ts.map +1 -1
  21. package/out/replicache/src/persist/client-group-gc.js +2 -2
  22. package/out/replicache/src/persist/client-group-gc.js.map +1 -1
  23. package/out/replicache/src/persist/collect-idb-databases.d.ts +2 -1
  24. package/out/replicache/src/persist/collect-idb-databases.d.ts.map +1 -1
  25. package/out/replicache/src/persist/collect-idb-databases.js +2 -2
  26. package/out/replicache/src/persist/collect-idb-databases.js.map +1 -1
  27. package/out/replicache/src/persist/heartbeat.d.ts +2 -1
  28. package/out/replicache/src/persist/heartbeat.d.ts.map +1 -1
  29. package/out/replicache/src/persist/heartbeat.js +2 -2
  30. package/out/replicache/src/persist/heartbeat.js.map +1 -1
  31. package/out/replicache/src/replicache-impl.d.ts +34 -3
  32. package/out/replicache/src/replicache-impl.d.ts.map +1 -1
  33. package/out/replicache/src/replicache-impl.js +104 -27
  34. package/out/replicache/src/replicache-impl.js.map +1 -1
  35. package/out/zero/package.js +1 -1
  36. package/out/zero/package.js.map +1 -1
  37. package/out/zero-cache/src/config/normalize.d.ts.map +1 -1
  38. package/out/zero-cache/src/config/normalize.js +1 -1
  39. package/out/zero-cache/src/config/normalize.js.map +1 -1
  40. package/out/zero-cache/src/config/zero-config.d.ts +23 -0
  41. package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
  42. package/out/zero-cache/src/config/zero-config.js +67 -16
  43. package/out/zero-cache/src/config/zero-config.js.map +1 -1
  44. package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts +1 -1
  45. package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts.map +1 -1
  46. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js +4 -1
  47. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js.map +1 -1
  48. package/out/zero-cache/src/services/plannerz.d.ts +5 -1
  49. package/out/zero-cache/src/services/plannerz.d.ts.map +1 -1
  50. package/out/zero-cache/src/services/plannerz.js +8 -4
  51. package/out/zero-cache/src/services/plannerz.js.map +1 -1
  52. package/out/zero-cache/src/services/profz.d.ts +24 -1
  53. package/out/zero-cache/src/services/profz.d.ts.map +1 -1
  54. package/out/zero-cache/src/services/profz.js +43 -3
  55. package/out/zero-cache/src/services/profz.js.map +1 -1
  56. package/out/zero-cache/src/services/statz.d.ts +4 -0
  57. package/out/zero-cache/src/services/statz.d.ts.map +1 -1
  58. package/out/zero-cache/src/services/statz.js +22 -5
  59. package/out/zero-cache/src/services/statz.js.map +1 -1
  60. package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts.map +1 -1
  61. package/out/zero-cache/src/services/view-syncer/snapshotter.js +21 -2
  62. package/out/zero-cache/src/services/view-syncer/snapshotter.js.map +1 -1
  63. package/out/zero-client/src/client/mutator-proxy.d.ts.map +1 -1
  64. package/out/zero-client/src/client/mutator-proxy.js +3 -1
  65. package/out/zero-client/src/client/mutator-proxy.js.map +1 -1
  66. package/out/zero-client/src/client/options.d.ts +2 -1
  67. package/out/zero-client/src/client/options.d.ts.map +1 -1
  68. package/out/zero-client/src/client/options.js.map +1 -1
  69. package/out/zero-client/src/client/version.js +1 -1
  70. package/out/zero-client/src/client/zero.d.ts.map +1 -1
  71. package/out/zero-client/src/client/zero.js +2 -1
  72. package/out/zero-client/src/client/zero.js.map +1 -1
  73. package/out/zero-server/src/logging.d.ts +2 -2
  74. package/out/zero-server/src/logging.d.ts.map +1 -1
  75. package/out/zero-server/src/logging.js +2 -2
  76. package/out/zero-server/src/logging.js.map +1 -1
  77. package/out/zero-server/src/process-mutations.d.ts +12 -3
  78. package/out/zero-server/src/process-mutations.d.ts.map +1 -1
  79. package/out/zero-server/src/process-mutations.js +13 -8
  80. package/out/zero-server/src/process-mutations.js.map +1 -1
  81. package/out/zero-server/src/push-processor.d.ts +8 -2
  82. package/out/zero-server/src/push-processor.d.ts.map +1 -1
  83. package/out/zero-server/src/push-processor.js +12 -4
  84. package/out/zero-server/src/push-processor.js.map +1 -1
  85. package/out/zql/src/ivm/cap.d.ts.map +1 -1
  86. package/out/zql/src/ivm/cap.js +1 -0
  87. package/out/zql/src/ivm/cap.js.map +1 -1
  88. package/out/zql/src/ivm/flipped-join.d.ts.map +1 -1
  89. package/out/zql/src/ivm/flipped-join.js +1 -0
  90. package/out/zql/src/ivm/flipped-join.js.map +1 -1
  91. package/out/zql/src/ivm/join-utils.d.ts +1 -0
  92. package/out/zql/src/ivm/join-utils.d.ts.map +1 -1
  93. package/out/zql/src/ivm/join-utils.js.map +1 -1
  94. package/out/zql/src/ivm/join.d.ts.map +1 -1
  95. package/out/zql/src/ivm/join.js +1 -0
  96. package/out/zql/src/ivm/join.js.map +1 -1
  97. package/out/zql/src/ivm/memory-storage.d.ts +1 -0
  98. package/out/zql/src/ivm/memory-storage.d.ts.map +1 -1
  99. package/out/zql/src/ivm/memory-storage.js +1 -0
  100. package/out/zql/src/ivm/memory-storage.js.map +1 -1
  101. package/out/zql/src/ivm/operator.d.ts +6 -0
  102. package/out/zql/src/ivm/operator.d.ts.map +1 -1
  103. package/out/zql/src/ivm/operator.js.map +1 -1
  104. package/out/zql/src/ivm/take.d.ts.map +1 -1
  105. package/out/zql/src/ivm/take.js +1 -0
  106. package/out/zql/src/ivm/take.js.map +1 -1
  107. package/out/zqlite/src/database-storage.d.ts.map +1 -1
  108. package/out/zqlite/src/database-storage.js +9 -1
  109. package/out/zqlite/src/database-storage.js.map +1 -1
  110. package/package.json +1 -1
@@ -174,15 +174,23 @@ var ReplicacheImpl = class {
174
174
  #zero;
175
175
  #closeAbortController = new AbortController();
176
176
  /**
177
- * Aborted on close AND on a storage failure after the open. The store-using
178
- * background processes (heartbeat, client and client-group GC, database
179
- * collection, mutation recovery, the new-client channel's store read) run
180
- * on this signal, so the first detected failure stops them instead of
181
- * letting each retry the fault at its interval and log `Error running.`
182
- * every time. A failure during the open moves the stores onto memory
183
- * instead, where they keep running.
177
+ * Aborted on close, on a storage failure after the open, and by
178
+ * {@link stopPersist}. `persist()`, the persist scheduler and the
179
+ * store-writing background processes (heartbeat, client and client-group
180
+ * GC, database collection, mutation recovery) stop on this signal, so the
181
+ * first detected failure stops them instead of letting each retry the
182
+ * fault at its interval and log `Error running.` every time. A failure
183
+ * during the open moves the stores onto memory instead, where they keep
184
+ * running.
184
185
  */
185
- #storeProcessesAbortController = new AbortController();
186
+ #persistAbortController = new AbortController();
187
+ /**
188
+ * Aborted on close, on a storage failure after the open, and by
189
+ * {@link stopRefresh}. `refresh()`, the refresh scheduler and the
190
+ * store-reading background process (the new-client channel's store read)
191
+ * stop on this signal.
192
+ */
193
+ #refreshAbortController = new AbortController();
186
194
  #persistLock = new Lock();
187
195
  #enableScheduledPersist;
188
196
  #enableScheduledRefresh;
@@ -248,7 +256,8 @@ var ReplicacheImpl = class {
248
256
  * instance. A read that needs a chunk the in-memory dag has not loaded from
249
257
  * the store yet, or has since evicted from its cache, still goes to the
250
258
  * store and fails the way any store read does; that failure reaches its
251
- * caller and is not reclassified here. An invalid ref count reported while
259
+ * caller, and is reported here as well, whichever caller it was (a query,
260
+ * a mutation, a poke, a background process). An invalid ref count reported while
252
261
  * the store is failing with `cannot-open` or `io-error` is NOT treated as
253
262
  * corruption (the database is not dropped and {@link onClientStateNotFound}
254
263
  * is not called), because a store that cannot complete a read or write is
@@ -258,8 +267,10 @@ var ReplicacheImpl = class {
258
267
  *
259
268
  * After the open, the failure is detected when a transaction on the store
260
269
  * fails to begin or to commit, whichever caller ran it (`persist()`, the
261
- * heartbeat, garbage collection, ...), and when `persist()` or `refresh()`
262
- * fails. The background maintenance processes (heartbeat, client and
270
+ * heartbeat, garbage collection, ...), when `persist()` or `refresh()`
271
+ * fails, when the in-memory dag fails to load a chunk from the store for
272
+ * any caller, and when a background process fails on a store read inside
273
+ * its transaction. The background maintenance processes (heartbeat, client and
263
274
  * client-group GC, database collection, mutation recovery) stop on it
264
275
  * instead of retrying against the store at their interval.
265
276
  *
@@ -274,6 +285,18 @@ var ReplicacheImpl = class {
274
285
  */
275
286
  #storageFailure;
276
287
  /**
288
+ * The last persist queued on the persist lock, if any, so
289
+ * {@link stopPersist} can wait for it. The lock runs persists in order, so
290
+ * this one settles after every persist queued before it. Settled to
291
+ * `undefined` rather than left rejected.
292
+ */
293
+ #persistInFlight;
294
+ /**
295
+ * The refresh currently running, if any, so {@link stopRefresh} can wait
296
+ * for it. Settled to `undefined` rather than left rejected.
297
+ */
298
+ #refreshInFlight;
299
+ /**
277
300
  * `onUpdateNeeded` is called when a code update is needed.
278
301
  *
279
302
  * A code update can be needed because:
@@ -325,7 +348,10 @@ var ReplicacheImpl = class {
325
348
  name,
326
349
  "replicache version": version
327
350
  });
328
- this.#closeAbortController.signal.addEventListener("abort", () => this.#storeProcessesAbortController.abort(), { once: true });
351
+ this.#closeAbortController.signal.addEventListener("abort", () => {
352
+ this.#persistAbortController.abort();
353
+ this.#refreshAbortController.abort();
354
+ }, { once: true });
329
355
  this.#subscriptions = new SubscriptionsManagerImpl(this.#queryInternal, this.#lc, this.#closeAbortController.signal);
330
356
  const kvStoreProvider = new MemFallbackStoreProvider(getKVStoreProvider(this.#lc, options.kvStore), (failure) => this.#onMemFallBack(failure), (failure) => this.#handleStorageFailure(failure));
331
357
  this.#kvStoreProvider = kvStoreProvider;
@@ -333,7 +359,7 @@ var ReplicacheImpl = class {
333
359
  this.#perKVStore = perKVStore;
334
360
  this.#idbDatabases = new IDBDatabasesStore(kvStoreProvider.create);
335
361
  this.perdag = new StoreImpl(perKVStore, newRandomHash, assertHash, this.#onInvalidRefCount);
336
- this.memdag = new LazyStore(this.perdag, LAZY_STORE_SOURCE_CHUNK_CACHE_SIZE_LIMIT, newRandomHash, assertHash);
362
+ this.memdag = new LazyStore(this.perdag, LAZY_STORE_SOURCE_CHUNK_CACHE_SIZE_LIMIT, newRandomHash, assertHash, void 0, this.#reportStorageFailure);
337
363
  const readyResolver = resolver();
338
364
  this.#ready = readyResolver.promise;
339
365
  const { minDelayMs = 30, maxDelayMs = MAX_DELAY_MS } = requestOptions;
@@ -387,14 +413,14 @@ var ReplicacheImpl = class {
387
413
  this.pull().catch(noop);
388
414
  this.push().catch(noop);
389
415
  }
390
- const { signal } = this.#storeProcessesAbortController;
416
+ const { signal } = this.#persistAbortController;
391
417
  startHeartbeats(clientID, this.perdag, () => {
392
418
  this.#clientStateNotFoundOnClient(clientID);
393
- }, HEARTBEAT_INTERVAL, this.#lc, signal);
394
- initClientGC(clientID, this.perdag, clientMaxAgeMs, GC_INTERVAL, onClientsDeleted, this.#lc, signal);
395
- initCollectIDBDatabases(this.#idbDatabases, this.#kvStoreProvider, COLLECT_IDB_INTERVAL, INITIAL_COLLECT_IDB_DELAY, 2 * clientMaxAgeMs, enableMutationRecovery, onClientsDeleted, this.#lc, signal, (name, createKVStore) => new StoreImpl(createKVStore(name), newRandomHash, assertHash, name === this.idbName ? this.#onInvalidRefCount : void 0));
396
- initClientGroupGC(this.perdag, enableMutationRecovery, this.#lc, signal);
397
- initNewClientChannel(this.name, this.idbName, signal, client.clientGroupID, isNewClientGroup, () => {
419
+ }, HEARTBEAT_INTERVAL, this.#lc, signal, this.#reportStorageFailure);
420
+ initClientGC(clientID, this.perdag, clientMaxAgeMs, GC_INTERVAL, onClientsDeleted, this.#lc, signal, this.#reportStorageFailure);
421
+ initCollectIDBDatabases(this.#idbDatabases, this.#kvStoreProvider, COLLECT_IDB_INTERVAL, INITIAL_COLLECT_IDB_DELAY, 2 * clientMaxAgeMs, enableMutationRecovery, onClientsDeleted, this.#lc, signal, (name, createKVStore) => new StoreImpl(createKVStore(name), newRandomHash, assertHash, name === this.idbName ? this.#onInvalidRefCount : void 0), this.#reportStorageFailure);
422
+ initClientGroupGC(this.perdag, enableMutationRecovery, this.#lc, signal, this.#reportStorageFailure);
423
+ initNewClientChannel(this.name, this.idbName, this.#refreshAbortController.signal, client.clientGroupID, isNewClientGroup, () => {
398
424
  this.#fireOnUpdateNeeded(updateNeededReasonNewClientGroup);
399
425
  }, this.perdag);
400
426
  setIntervalWithSignal(() => this.recoverMutations(), RECOVER_MUTATIONS_INTERVAL_MS, signal);
@@ -716,10 +742,10 @@ var ReplicacheImpl = class {
716
742
  };
717
743
  }
718
744
  persist() {
719
- return this.#persistLock.withLock(async () => {
745
+ const run = this.#persistLock.withLock(async () => {
720
746
  const { clientID } = this;
721
747
  await this.#ready;
722
- if (this.#closed || this.#storageFailure) return;
748
+ if (this.#closed || this.#storageFailure || this.#persistAbortController.signal.aborted) return;
723
749
  try {
724
750
  await persistDD31(this.#lc, clientID, this.memdag, this.perdag, this.#mutatorRegistry, () => this.#closed, 7, this.#zero?.getTxData);
725
751
  } catch (e) {
@@ -742,11 +768,18 @@ var ReplicacheImpl = class {
742
768
  clientGroupID
743
769
  });
744
770
  });
771
+ this.#persistInFlight = run.catch(noop);
772
+ return run;
773
+ }
774
+ refresh() {
775
+ const run = this.#refresh();
776
+ this.#refreshInFlight = run.catch(noop);
777
+ return run;
745
778
  }
746
- async refresh() {
779
+ async #refresh() {
747
780
  await this.#ready;
748
781
  const { clientID } = this;
749
- if (this.#closed || this.#storageFailure || !this.#enableRefresh()) return;
782
+ if (this.#closed || this.#storageFailure || this.#refreshAbortController.signal.aborted || !this.#enableRefresh()) return;
750
783
  let refreshResult;
751
784
  try {
752
785
  refreshResult = await refresh(this.#lc, this.memdag, this.perdag, clientID, this.#mutatorRegistry, this.#subscriptions, () => this.closed, 7, this.#zero);
@@ -777,6 +810,15 @@ var ReplicacheImpl = class {
777
810
  */
778
811
  #corruptDatabaseRecovery;
779
812
  /**
813
+ * Handed to the in-memory dag and the background processes, which have no
814
+ * other way to reach this instance when a store read inside them fails.
815
+ * Skipped while closing: a read that fails because the store was closed
816
+ * under it is not a storage failure of the instance.
817
+ */
818
+ #reportStorageFailure = (failure) => {
819
+ if (!this.#closed) this.#handleStorageFailure(failure);
820
+ };
821
+ /**
780
822
  * A storage failure after the open. Records the first one, stops the
781
823
  * store-using background processes, logs it once and tells the app. Later
782
824
  * failures of the same instance are the same fault and are not reported
@@ -785,7 +827,8 @@ var ReplicacheImpl = class {
785
827
  #handleStorageFailure(failure) {
786
828
  if (this.#storageFailure !== void 0) return;
787
829
  this.#storageFailure = failure;
788
- this.#storeProcessesAbortController.abort();
830
+ this.#persistAbortController.abort();
831
+ this.#refreshAbortController.abort();
789
832
  this.#lc.warn?.(`Local store storage failed (${failure.kind}) for ${this.idbName}; persistence is stopped for this instance`, failure);
790
833
  this.#fireOnStorageFailure(failure);
791
834
  }
@@ -879,6 +922,40 @@ var ReplicacheImpl = class {
879
922
  await this.disableClientGroup();
880
923
  this.#fireOnClientStateNotFound();
881
924
  }
925
+ /**
926
+ * Stops every write to the local store, for an instance whose database is
927
+ * about to be dropped from under it: the store-writing background
928
+ * processes (heartbeat, GC, collection, mutation recovery) are aborted, a
929
+ * `persist()` already in flight is waited for, and every later `persist()`
930
+ * — scheduled or explicit — is a no-op. Mutations keep running against the in-memory
931
+ * dag until the app replaces the instance (see `onClientStateNotFound`).
932
+ *
933
+ * Use together with {@link stopRefresh} before dropping the database, so
934
+ * the drop's own footprint — `database is closed` from the next scheduled
935
+ * persist and the background processes — is not logged as errors against a
936
+ * store that was deleted on purpose.
937
+ */
938
+ async stopPersist() {
939
+ this.#persistAbortController.abort();
940
+ await this.#persistInFlight;
941
+ }
942
+ /**
943
+ * Stops every refresh from the local store, for an instance whose database
944
+ * is about to be dropped from under it: the store-reading background
945
+ * process (the new-client channel) is aborted, a `refresh()` already in
946
+ * flight is waited for, and every later `refresh()` / `runRefresh()` —
947
+ * scheduled or explicit — is a no-op. Queries keep running against the
948
+ * in-memory dag until the app replaces the instance (see
949
+ * `onClientStateNotFound`).
950
+ *
951
+ * Use together with {@link stopPersist} before dropping the database, so
952
+ * the run loop's refresh after a connect error does not run into the
953
+ * dropped store and log `database is closed` as an error.
954
+ */
955
+ async stopRefresh() {
956
+ this.#refreshAbortController.abort();
957
+ await this.#refreshInFlight;
958
+ }
882
959
  async disableClientGroup() {
883
960
  const clientGroupID = await this.#clientGroupIDPromise;
884
961
  assert(clientGroupID, "Expected clientGroupID to be defined");
@@ -890,7 +967,7 @@ var ReplicacheImpl = class {
890
967
  this.onUpdateNeeded?.(reason);
891
968
  }
892
969
  async #schedulePersist() {
893
- if (!this.#enableScheduledPersist || this.#storageFailure) return;
970
+ if (!this.#enableScheduledPersist || this.#storageFailure || this.#persistAbortController.signal.aborted) return;
894
971
  await this.#schedule("persist", this.#persistScheduler);
895
972
  }
896
973
  async #handlePersist(persistInfo) {
@@ -899,7 +976,7 @@ var ReplicacheImpl = class {
899
976
  if (persistInfo.clientGroupID === clientGroupID) this.#scheduleRefresh();
900
977
  }
901
978
  async #scheduleRefresh() {
902
- if (!this.#enableScheduledRefresh || this.#storageFailure) return;
979
+ if (!this.#enableScheduledRefresh || this.#storageFailure || this.#refreshAbortController.signal.aborted) return;
903
980
  await this.#schedule("refresh from storage", this.#refreshScheduler);
904
981
  }
905
982
  async #schedule(name, scheduler) {
@@ -1058,7 +1135,7 @@ var ReplicacheImpl = class {
1058
1135
  return ex;
1059
1136
  }
1060
1137
  recoverMutations() {
1061
- if (this.#storeProcessesAbortController.signal.aborted) return promiseFalse;
1138
+ if (this.#persistAbortController.signal.aborted) return promiseFalse;
1062
1139
  }
1063
1140
  /**
1064
1141
  * List of pending mutations. The order of this is from oldest to newest.