Reuse scoped content and progress operations

This commit is contained in:
vorotamoroz committed 2026-10-29 14:56:56 +00:00
1 parent 28bc6e87a1
commit cfdc698775
16 files changed
+1596 -132

No files matched your search

@@ -35,7 +35,6 @@ import {
getLogLevel,
autosaveCache,
type MapLike,
onlyInNTimes,
BASE_IS_NEW,
EVEN,
displayRev,
@@ -45,6 +44,7 @@ import { serialized, skipIfDuplicated } from "octagonal-wheels/concurrency/lock"
import { JsonResolveModal } from "@/features/HiddenFileCommon/JsonResolveModal.ts";
import { LiveSyncCommands } from "@/features/LiveSyncCommands.ts";
import { addPrefix, stripAllPrefixes } from "@vrtmrz/livesync-commonlib/compat/string_and_binary/path";
import { createCoalescingNotifier } from "octagonal-wheels/concurrency/coalescingNotifier";
import { QueueProcessor } from "octagonal-wheels/concurrency/processor";
import {
hiddenFilesEventCount,
@@ -57,6 +57,7 @@ import { tryGetFilePath } from "@vrtmrz/livesync-commonlib/compat/common/utils.d
import type { HandlerOutcome } from "@vrtmrz/livesync-commonlib/compat/services/lib/HandlerUtils";
import type { OptionalFileEventOptions } from "@vrtmrz/livesync-commonlib/compat/services/base/IService";
import { configureHiddenFileSyncMode, type ConfigureHiddenFileSyncResult } from "./configureHiddenFileSyncMode.ts";
import { performBatchWithProgress } from "./performBatchWithProgress.ts";
import type { OptionalSyncFeatureMode } from "@/features/optionalSyncFeatures.ts";
import { getObsidianCommunityPluginManager } from "@/common/obsidianCommunityPlugins.ts";
import { $msg } from "@/common/translation";
@@ -571,18 +572,15 @@ export class HiddenFileSync extends LiveSyncCommands {
) {
const logLevel = getLogLevel(showNotice);
const p = this._progress(`[⚙ Storage -> DB ]\n`, logLevel);
const notifyProgress = onlyInNTimes(100, (progress) => p.log(`${progress}/${processFiles.length}`));
const processes = processFiles.map(async (file, i) => {
try {
await this.trackStorageFileModification(file, onlyNew, forceWriteAll, includeDeleted);
notifyProgress();
} catch (ex) {
await performBatchWithProgress(processFiles, 100, {
processItem: (file) => this.trackStorageFileModification(file, onlyNew, forceWriteAll, includeDeleted),
onProgress: (progress) => p.log(`${progress}/${processFiles.length}`),
onItemError: (ex, file) => {
p.once(`Failed to process storage change file:${file}`);
this._log(ex, LOG_LEVEL_VERBOSE);
}
},
onDone: () => p.done(),
});
await Promise.all(processes);
p.done();
}
async scanAllStorageChanges(
showNotice: boolean = false,
@@ -1134,9 +1132,8 @@ Offline Changed files: ${processFiles.length}`;
) {
const logLevel = getLogLevel(showNotice);
const p = this._progress(`[⚙ DB -> Storage ]\n`, logLevel);
const notifyProgress = onlyInNTimes(100, (progress) => p.log(`${progress}/${processFiles.length}`));
const processes = processFiles.map(async (file) => {
try {
await performBatchWithProgress(processFiles, 100, {
processItem: async (file) => {
const path = stripAllPrefixes(this.getPath(file));
if (!(await this.isTargetFile(path))) {
this._log(
@@ -1153,14 +1150,14 @@ Offline Changed files: ${processFiles.length}`;
includeDeletion
);
}
notifyProgress();
} catch (ex) {
},
onProgress: (progress) => p.log(`${progress}/${processFiles.length}`),
onItemError: (ex, file) => {
this._log(`Failed to process storage change file:${tryGetFilePath(file)}`, logLevel);
this._log(ex, LOG_LEVEL_VERBOSE);
}
},
onDone: () => p.done(),
});
await Promise.all(processes);
p.done();
}
async applyOfflineChanges(showNotice: boolean) {
@@ -1188,9 +1185,14 @@ Untracked database files: ${untrackedDatabase.length}
Common untracked files: ${bothUntracked.length}`;
p.once(stat);
const semaphores = Semaphore(10);
const notifyProgress = onlyInNTimes(25, (progress) => p.log(`${progress}/${bothUntracked.length}`));
const notifyProgress = createCoalescingNotifier<number>({
everyCount: 25,
leading: true,
onNotify: (progress) => p.log(`${progress}/${bothUntracked.length}`),
});
let attempted = 0;
const allProcesses = bothUntracked.map(async (file) => {
notifyProgress();
notifyProgress.update(++attempted);
const rel = await semaphores.acquire();
try {
const fileStat = await this.core.storageAccess.statHidden(file);
@@ -1260,20 +1262,18 @@ Offline Changed files: ${files.length}`;
const logLevel = getLogLevel(showNotice);
const p = this._progress(`[⚙ Scanning DB -> Storage ]\n`, logLevel);
p.log("Scanning database files...");
const notifyProgress = onlyInNTimes(25, (progress) => p.log(`${progress}/${files.length}`));
const processFiles = files.map(async (file) => {
try {
await performBatchWithProgress(files, 25, {
processItem: async (file) => {
const path = stripAllPrefixes(this.getPath(file));
await this.trackDatabaseFileModification(path, "[Scanning]", true, onlyNew, file);
notifyProgress();
} catch (ex) {
},
onProgress: (progress) => p.log(`${progress}/${files.length}`),
onItemError: (ex, file) => {
this._log(`Failed to process database changes:${tryGetFilePath(file)}`);
this._log(ex, LOG_LEVEL_VERBOSE);
}
return;
},
onDone: () => p.done(),
});
await Promise.all(processFiles);
p.done();
return true;
}
@@ -1435,9 +1435,14 @@ Offline Changed files: ${files.length}`;
const storageToDatabase = [] as FilePath[];
const databaseToStorage = [] as MetaEntry[];
const eachProgress = onlyInNTimes(100, (progress) => p.log(`Checking ${progress}/${allFileNames.size}`));
const eachProgress = createCoalescingNotifier<number>({
everyCount: 100,
leading: true,
onNotify: (progress) => p.log(`Checking ${progress}/${allFileNames.size}`),
});
let attempted = 0;
for (const file of allFileNames) {
eachProgress();
eachProgress.update(++attempted);
const storageMTime = await this.core.storageAccess.statHidden(file);
const mtimeStorage = getComparingMTime(storageMTime);
const dbEntry = allDatabaseMap.get(file)!;