@rljson/fs-agent 0.0.57 → 0.0.58

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.
@@ -276,6 +276,14 @@ export declare class FsAgent {
276
276
  /** Files written vs left alone by the current {@link restore}. */
277
277
  private _restoreWritten;
278
278
  private _restoreSkipped;
279
+ /**
280
+ * Absolute paths of the files this agent has actually TOLD anyone about.
281
+ *
282
+ * A prune may only remove a file that peers could know exists. Anything
283
+ * written since the last announcement is invisible to every sender, so a
284
+ * tree that lacks it is not deleting it — it simply predates it.
285
+ */
286
+ private readonly _announcedFiles;
279
287
  /**
280
288
  * Files this restore DELETED.
281
289
  *
@@ -724,6 +732,14 @@ export declare class FsAgent {
724
732
  * @returns `apply`, or the reason it is not news.
725
733
  */
726
734
  private _inboundRefVerdict;
735
+ /**
736
+ * Records the files an announcement carried.
737
+ *
738
+ * Called wherever this agent commits to a state as "what peers know" —
739
+ * its own pushes, and the states it adopts from theirs.
740
+ * @param tree - The tree that just went out, or was adopted as ours.
741
+ */
742
+ private _rememberAnnounced;
727
743
  private _adoptAppliedRef;
728
744
  /**
729
745
  * Derives a deterministic content key from an FsTree.
package/dist/fs-agent.js CHANGED
@@ -1152,6 +1152,14 @@ class FsAgent {
1152
1152
  /** Files written vs left alone by the current {@link restore}. */
1153
1153
  _restoreWritten = 0;
1154
1154
  _restoreSkipped = 0;
1155
+ /**
1156
+ * Absolute paths of the files this agent has actually TOLD anyone about.
1157
+ *
1158
+ * A prune may only remove a file that peers could know exists. Anything
1159
+ * written since the last announcement is invisible to every sender, so a
1160
+ * tree that lacks it is not deleting it — it simply predates it.
1161
+ */
1162
+ _announcedFiles = /* @__PURE__ */ new Set();
1155
1163
  /**
1156
1164
  * Files this restore DELETED.
1157
1165
  *
@@ -1939,6 +1947,9 @@ ${err.stack}` : String(err);
1939
1947
  }
1940
1948
  }
1941
1949
  } else if (!expectedFiles.has(fullPath) && preRestore.has(fullPath)) {
1950
+ if (this._announcedFiles.size > 0 && !this._announcedFiles.has(fullPath)) {
1951
+ continue;
1952
+ }
1942
1953
  await rm(fullPath, { force: true });
1943
1954
  this._restorePruned++;
1944
1955
  }
@@ -1988,12 +1999,14 @@ ${err.stack}` : String(err);
1988
1999
  this._currentRef = initialRef;
1989
2000
  this._persistCurrentRef(initialRef);
1990
2001
  this._lastSentContentKey = this._contentKeyFromTree(initialTree);
2002
+ this._rememberAnnounced(initialTree);
1991
2003
  }
1992
2004
  if (initialRef && !isSilentJoiner) {
1993
2005
  this._lastSentRef = initialRef;
1994
2006
  this._currentRef = initialRef;
1995
2007
  this._persistCurrentRef(initialRef);
1996
2008
  this._lastSentContentKey = this._contentKeyFromTree(initialTree);
2009
+ this._rememberAnnounced(initialTree);
1997
2010
  await this._sendRef(
1998
2011
  connector,
1999
2012
  initialRef,
@@ -2073,6 +2086,7 @@ ${err.stack}` : String(err);
2073
2086
  }
2074
2087
  this._lastSentRef = ref;
2075
2088
  this._lastSentContentKey = contentKey;
2089
+ this._rememberAnnounced(tree);
2076
2090
  if (parentRef && parentRef !== ref) {
2077
2091
  connector.invalidateReceived(parentRef);
2078
2092
  }
@@ -2339,6 +2353,19 @@ ${err.stack}` : String(err);
2339
2353
  if (!isNewestFromSender) return "stale";
2340
2354
  return "apply";
2341
2355
  }
2356
+ /**
2357
+ * Records the files an announcement carried.
2358
+ *
2359
+ * Called wherever this agent commits to a state as "what peers know" —
2360
+ * its own pushes, and the states it adopts from theirs.
2361
+ * @param tree - The tree that just went out, or was adopted as ours.
2362
+ */
2363
+ _rememberAnnounced(tree) {
2364
+ this._announcedFiles.clear();
2365
+ for (const path of this._getFileContentMap(tree).keys()) {
2366
+ this._announcedFiles.add(join(this._rootPath, path));
2367
+ }
2368
+ }
2342
2369
  _adoptAppliedRef(connector, treeRef) {
2343
2370
  if (this._lastAppliedRef && this._lastAppliedRef !== treeRef) {
2344
2371
  connector.invalidateSent?.(this._lastAppliedRef);
@@ -2408,6 +2435,7 @@ ${err.stack}` : String(err);
2408
2435
  const ref = await dbAdapter.storeFsTree(tree, { previous });
2409
2436
  this._lastSentRef = ref;
2410
2437
  this._lastSentContentKey = this._contentKeyFromTree(tree);
2438
+ this._rememberAnnounced(tree);
2411
2439
  this._currentRef = ref;
2412
2440
  return ref;
2413
2441
  }
@@ -2471,6 +2499,7 @@ ${err.stack}` : String(err);
2471
2499
  this._currentRef = treeRef;
2472
2500
  this._persistCurrentRef(treeRef);
2473
2501
  this._lastSentContentKey = this._contentKeyFromTree(currentTree);
2502
+ this._rememberAnnounced(currentTree);
2474
2503
  return;
2475
2504
  }
2476
2505
  if (this._resolveConflicts && this._currentRef && predecessorRefs && predecessorRefs.length > 0) {
@@ -2545,6 +2574,7 @@ ${err.stack}` : String(err);
2545
2574
  if (!hasNewsOfOurOwn) {
2546
2575
  this._lastSentRef = postRestoreRef;
2547
2576
  this._lastSentContentKey = this._contentKeyFromTree(postRestoreTree);
2577
+ this._rememberAnnounced(postRestoreTree);
2548
2578
  if (postRestoreFiles.size < incomingFiles.size) {
2549
2579
  console.log(
2550
2580
  `[FsAgent] ref=${treeRef.slice(0, 8)}… left this node behind (${postRestoreFiles.size} of ${incomingFiles.size} files) — not announcing a state that is catching up.`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rljson/fs-agent",
3
- "version": "0.0.57",
3
+ "version": "0.0.58",
4
4
  "description": "Rljson fs-agent description",
5
5
  "homepage": "https://github.com/rljson/fs-agent",
6
6
  "bugs": "https://github.com/rljson/fs-agent/issues",