@tinycloud/cli 1.5.0-beta.11 → 1.5.0-beta.12

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.
@@ -5259,6 +5259,9 @@ function assertReadable(authority, now) {
5259
5259
  function contentHash(bytes) {
5260
5260
  return bytesToHex(blake3(bytes));
5261
5261
  }
5262
+ function repairId(entry) {
5263
+ return `${entry.hash}\0${entry.key}`;
5264
+ }
5262
5265
  function sameEtag(a, b) {
5263
5266
  return a.replace(/^"|"$/g, "") === b.replace(/^"|"$/g, "");
5264
5267
  }
@@ -5628,7 +5631,7 @@ function kvSyncTransport(kv, options = {}) {
5628
5631
  }
5629
5632
  };
5630
5633
  }
5631
- var ReplicaErrorCode, REPLICA_ERROR, ReplicaError, RFC3339, DEFAULT_PAGE_LIMIT, DEFAULT_LEASE_TTL_MS, FETCH_CHUNK, REPAIR_BATCH, RETENTION_REVOKED, PENDING_REFUSALS, Replica, BASE58, BASE32, featureCache, REVOKED_CODES, REVOKED_BODY, encoder;
5634
+ var ReplicaErrorCode, REPLICA_ERROR, ReplicaError, RFC3339, DEFAULT_PAGE_LIMIT, DEFAULT_LEASE_TTL_MS, FETCH_CHUNK, REPAIR_BATCH, REPAIR_MAX_TRIES, REPAIR_BACKOFF_BASE_MS, RETENTION_REVOKED, PENDING_REFUSALS, Replica, BASE58, BASE32, featureCache, REVOKED_CODES, REVOKED_BODY, encoder;
5632
5635
  var init_dist = __esm({
5633
5636
  "../replica/dist/index.js"() {
5634
5637
  "use strict";
@@ -5716,6 +5719,8 @@ var init_dist = __esm({
5716
5719
  DEFAULT_LEASE_TTL_MS = 12e4;
5717
5720
  FETCH_CHUNK = 100;
5718
5721
  REPAIR_BATCH = 100;
5722
+ REPAIR_MAX_TRIES = 5;
5723
+ REPAIR_BACKOFF_BASE_MS = 6e4;
5719
5724
  RETENTION_REVOKED = /* @__PURE__ */ new Set(["retention-grant-revoked", "retention-grant-ancestor-revoked"]);
5720
5725
  PENDING_REFUSALS = /* @__PURE__ */ new Set([
5721
5726
  ReplicaErrorCode.GRANT_UNAUTHORIZED,
@@ -5728,6 +5733,8 @@ var init_dist = __esm({
5728
5733
  #now;
5729
5734
  #leaseTtlMs;
5730
5735
  #onCommit;
5736
+ /** Failed repair fetches of this session, by key and ETag hash. Never persisted: a new `Replica` retries afresh. */
5737
+ #repairTries = /* @__PURE__ */ new Map();
5731
5738
  constructor(options) {
5732
5739
  this.#store = options.store;
5733
5740
  const transport = options.transport;
@@ -6082,7 +6089,14 @@ var init_dist = __esm({
6082
6089
  return { changes, blobs, fetched: fetched2 };
6083
6090
  }
6084
6091
  async #repair(attempt, cursor, nodeDid, coverage, retentionGrantCid) {
6085
- const pending = await this.#store.pendingRepairs(Number.MAX_SAFE_INTEGER);
6092
+ const all = await this.#store.pendingRepairs(Number.MAX_SAFE_INTEGER);
6093
+ const now = this.#now();
6094
+ const pendingIds = new Set(all.map((entry) => repairId(entry)));
6095
+ for (const id of this.#repairTries.keys()) if (!pendingIds.has(id)) this.#repairTries.delete(id);
6096
+ const pending = all.filter((entry) => {
6097
+ const state2 = this.#repairTries.get(repairId(entry));
6098
+ return state2 === void 0 || state2.tries < REPAIR_MAX_TRIES && now >= state2.nextAttemptAt;
6099
+ });
6086
6100
  let repaired = 0;
6087
6101
  for (let start = 0; start < pending.length; start += REPAIR_BATCH) {
6088
6102
  const chunk = pending.slice(start, start + REPAIR_BATCH);
@@ -6094,7 +6108,14 @@ var init_dist = __esm({
6094
6108
  const changes = [];
6095
6109
  for (const entry of chunk) {
6096
6110
  const bytes = acceptContent(entry, contents.get(entry.key));
6097
- if (bytes === void 0) continue;
6111
+ const id = repairId(entry);
6112
+ if (bytes === void 0) {
6113
+ const tries = (this.#repairTries.get(id)?.tries ?? 0) + 1;
6114
+ const wait = tries === 1 ? 0 : REPAIR_BACKOFF_BASE_MS * 2 ** (tries - 2);
6115
+ this.#repairTries.set(id, { tries, nextAttemptAt: this.#now() + wait });
6116
+ continue;
6117
+ }
6118
+ this.#repairTries.delete(id);
6098
6119
  blobs.set(entry.hash, bytes);
6099
6120
  changes.push({ ...entry, content: true });
6100
6121
  }