@rljson/fs-agent 0.0.50 → 0.0.52
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/fs-agent.d.ts +18 -0
- package/dist/fs-agent.js +45 -2
- package/package.json +1 -1
package/dist/fs-agent.d.ts
CHANGED
|
@@ -276,6 +276,24 @@ 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
|
+
* The file set of the newest tree any peer has told this node about.
|
|
281
|
+
*
|
|
282
|
+
* Kept so the send path can answer the one question a receiver never can:
|
|
283
|
+
* am I about to announce my progress through someone else's state?
|
|
284
|
+
*/
|
|
285
|
+
private _lastKnownRemoteFiles?;
|
|
286
|
+
/**
|
|
287
|
+
* Whether a LOCAL deletion has been seen since the last apply.
|
|
288
|
+
*
|
|
289
|
+
* The discriminator 0.0.49 lacked. A folder smaller than the newest tree
|
|
290
|
+
* this node knows about is either a node still catching up or a node someone
|
|
291
|
+
* deleted files from, and those need opposite treatment — the first must stay
|
|
292
|
+
* quiet, the second must be heard. The shapes are identical; the CAUSE is
|
|
293
|
+
* not, and only this node can see it: a deletion arrives as a watcher event,
|
|
294
|
+
* catching up does not.
|
|
295
|
+
*/
|
|
296
|
+
private _localDeleteSinceApply;
|
|
279
297
|
/**
|
|
280
298
|
* Files this restore DELETED.
|
|
281
299
|
*
|
package/dist/fs-agent.js
CHANGED
|
@@ -1152,6 +1152,24 @@ class FsAgent {
|
|
|
1152
1152
|
/** Files written vs left alone by the current {@link restore}. */
|
|
1153
1153
|
_restoreWritten = 0;
|
|
1154
1154
|
_restoreSkipped = 0;
|
|
1155
|
+
/**
|
|
1156
|
+
* The file set of the newest tree any peer has told this node about.
|
|
1157
|
+
*
|
|
1158
|
+
* Kept so the send path can answer the one question a receiver never can:
|
|
1159
|
+
* am I about to announce my progress through someone else's state?
|
|
1160
|
+
*/
|
|
1161
|
+
_lastKnownRemoteFiles;
|
|
1162
|
+
/**
|
|
1163
|
+
* Whether a LOCAL deletion has been seen since the last apply.
|
|
1164
|
+
*
|
|
1165
|
+
* The discriminator 0.0.49 lacked. A folder smaller than the newest tree
|
|
1166
|
+
* this node knows about is either a node still catching up or a node someone
|
|
1167
|
+
* deleted files from, and those need opposite treatment — the first must stay
|
|
1168
|
+
* quiet, the second must be heard. The shapes are identical; the CAUSE is
|
|
1169
|
+
* not, and only this node can see it: a deletion arrives as a watcher event,
|
|
1170
|
+
* catching up does not.
|
|
1171
|
+
*/
|
|
1172
|
+
_localDeleteSinceApply = false;
|
|
1155
1173
|
/**
|
|
1156
1174
|
* Files this restore DELETED.
|
|
1157
1175
|
*
|
|
@@ -2007,6 +2025,7 @@ ${err.stack}` : String(err);
|
|
|
2007
2025
|
debouncedSync({ type: "safety-rescan" });
|
|
2008
2026
|
};
|
|
2009
2027
|
const debouncedSync = (change) => {
|
|
2028
|
+
if (change?.type === "deleted") this._localDeleteSinceApply = true;
|
|
2010
2029
|
if (change?.type === "safety-rescan" && this._remoteApplyInFlight) {
|
|
2011
2030
|
this._rescanDeferred = true;
|
|
2012
2031
|
return;
|
|
@@ -2021,6 +2040,25 @@ ${err.stack}` : String(err);
|
|
|
2021
2040
|
if (contentKey === this._lastSentContentKey) {
|
|
2022
2041
|
return;
|
|
2023
2042
|
}
|
|
2043
|
+
const known = this._lastKnownRemoteFiles;
|
|
2044
|
+
if (known && !this._localDeleteSinceApply && tree.trees.size > 0) {
|
|
2045
|
+
const mine = this._getFileContentMap(tree);
|
|
2046
|
+
if (mine.size < known.size) {
|
|
2047
|
+
let hasOwn = false;
|
|
2048
|
+
for (const path of mine.keys()) {
|
|
2049
|
+
if (!known.has(path)) {
|
|
2050
|
+
hasOwn = true;
|
|
2051
|
+
break;
|
|
2052
|
+
}
|
|
2053
|
+
}
|
|
2054
|
+
if (!hasOwn) {
|
|
2055
|
+
console.log(
|
|
2056
|
+
`[FsAgent] not announcing ${mine.size} of ${known.size} files — nothing here was deleted locally, so this is a gap rather than news.`
|
|
2057
|
+
);
|
|
2058
|
+
return;
|
|
2059
|
+
}
|
|
2060
|
+
}
|
|
2061
|
+
}
|
|
2024
2062
|
const dbAdapter = new FsDbAdapter(db, treeKey);
|
|
2025
2063
|
const parentRef = this._currentRef;
|
|
2026
2064
|
const previous = await this._ancestryPrevious(
|
|
@@ -2466,10 +2504,13 @@ ${err.stack}` : String(err);
|
|
|
2466
2504
|
}
|
|
2467
2505
|
const ancestryExpected = this._resolveConflicts;
|
|
2468
2506
|
const declaresAncestry = (predecessorRefs?.length ?? 0) > 0;
|
|
2469
|
-
const
|
|
2507
|
+
const ancestryIsCarried = connector.syncConfig?.causalOrdering === true;
|
|
2508
|
+
const senderSawMyState = !ancestryIsCarried || this._currentRef !== void 0 && (predecessorRefs?.includes(this._currentRef) ?? false);
|
|
2509
|
+
const withholdPrune = restoreOptions?.cleanTarget && (ancestryExpected && !declaresAncestry || !senderSawMyState);
|
|
2510
|
+
const applyOptions = withholdPrune ? { ...restoreOptions, cleanTarget: false } : restoreOptions;
|
|
2470
2511
|
if (applyOptions !== restoreOptions) {
|
|
2471
2512
|
console.warn(
|
|
2472
|
-
`[FsAgent] ref=${treeRef.slice(0, 8)}… declares no ancestry — applying additively, not pruning.`
|
|
2513
|
+
`[FsAgent] ref=${treeRef.slice(0, 8)}… ` + (declaresAncestry ? `descends from ${predecessorRefs?.map((r) => r.slice(0, 8)).join(", ")}, not from the state this node is in (${this._currentRef?.slice(0, 8) ?? "none"})` : "declares no ancestry") + ` — applying additively, not pruning.`
|
|
2473
2514
|
);
|
|
2474
2515
|
}
|
|
2475
2516
|
if (restoreOptions?.cleanTarget) {
|
|
@@ -2498,6 +2539,8 @@ ${err.stack}` : String(err);
|
|
|
2498
2539
|
this._persistCurrentRef(postRestoreRef);
|
|
2499
2540
|
const postRestoreFiles = this._getFileContentMap(postRestoreTree);
|
|
2500
2541
|
const incomingFiles = this._getFileContentMap(incomingTree);
|
|
2542
|
+
this._lastKnownRemoteFiles = incomingFiles;
|
|
2543
|
+
this._localDeleteSinceApply = false;
|
|
2501
2544
|
let hasNewsOfOurOwn = false;
|
|
2502
2545
|
for (const path of postRestoreFiles.keys()) {
|
|
2503
2546
|
if (!incomingFiles.has(path)) {
|