Sync all offline changes to the remote server
This commit is contained in:
parent
eb87de8e68
commit
742e0fd7e5
3 changed files with 140 additions and 7 deletions
131
plugin/src/sync-operations/apply-local-changes-remotely.ts
Normal file
131
plugin/src/sync-operations/apply-local-changes-remotely.ts
Normal file
|
|
@ -0,0 +1,131 @@
|
||||||
|
import { Database } from "../database/database";
|
||||||
|
import { SyncService } from "../services/sync_service";
|
||||||
|
import { Logger } from "../logger";
|
||||||
|
import { FileOperations } from "../file-operations/file-operations";
|
||||||
|
import { syncLocallyCreatedFile } from "./sync-locally-created-file";
|
||||||
|
import { EMPTY_HASH, hash } from "src/utils/hash";
|
||||||
|
import { syncLocallyUpdatedFile } from "./sync-locally-updated-file";
|
||||||
|
import { syncLocallyDeletedFile } from "./sync-locally-deleted-file";
|
||||||
|
import { Notice } from "obsidian";
|
||||||
|
import PQueue from "p-queue";
|
||||||
|
|
||||||
|
let isRunning = false;
|
||||||
|
|
||||||
|
export interface Progress {
|
||||||
|
processedFiles: number;
|
||||||
|
totalFiles: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function applyLocalChangesRemotely(
|
||||||
|
database: Database,
|
||||||
|
syncServer: SyncService,
|
||||||
|
operations: FileOperations
|
||||||
|
) {
|
||||||
|
console.log("applyLocalChangesRemotely");
|
||||||
|
if (isRunning) {
|
||||||
|
Logger.getInstance().info("Push sync already in progress, skipping");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let tasks: Promise<void>[] = [];
|
||||||
|
|
||||||
|
const allLocalFiles = await operations.listAllFiles();
|
||||||
|
console.log(allLocalFiles);
|
||||||
|
const deletedFiles = [...database.getDocuments().entries()].filter(
|
||||||
|
([path, _]) => !allLocalFiles.includes(path)
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log(deletedFiles);
|
||||||
|
|
||||||
|
const promiseQueue = new PQueue({
|
||||||
|
concurrency: 1,
|
||||||
|
});
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
allLocalFiles.map((path) =>
|
||||||
|
promiseQueue.add(async () => {
|
||||||
|
const syncedState = database.getDocument(path);
|
||||||
|
if (!syncedState) {
|
||||||
|
Logger.getInstance().info(
|
||||||
|
`Document ${path} not found in database`
|
||||||
|
);
|
||||||
|
const contentHash = hash(await operations.read(path));
|
||||||
|
if (contentHash != EMPTY_HASH) {
|
||||||
|
const match = deletedFiles.find(
|
||||||
|
([path, doc]) => doc.hash === contentHash
|
||||||
|
);
|
||||||
|
if (match) {
|
||||||
|
const oldPath = match[0];
|
||||||
|
Logger.getInstance().info(
|
||||||
|
`Document ${path} found remotely under a different path (${oldPath}), moving`
|
||||||
|
);
|
||||||
|
tasks.push(
|
||||||
|
syncLocallyUpdatedFile({
|
||||||
|
database,
|
||||||
|
syncServer,
|
||||||
|
operations,
|
||||||
|
oldPath,
|
||||||
|
filePath: path,
|
||||||
|
updateTime:
|
||||||
|
await operations.getModificationTime(
|
||||||
|
path
|
||||||
|
),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
deletedFiles.remove(match);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tasks.push(
|
||||||
|
syncLocallyCreatedFile({
|
||||||
|
database,
|
||||||
|
syncServer,
|
||||||
|
operations,
|
||||||
|
updateTime: await operations.getModificationTime(
|
||||||
|
path
|
||||||
|
),
|
||||||
|
filePath: path,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const content = await operations.read(path);
|
||||||
|
if (syncedState.hash !== hash(content)) {
|
||||||
|
Logger.getInstance().info(
|
||||||
|
`Document ${path} has local changes, updating`
|
||||||
|
);
|
||||||
|
tasks.push(
|
||||||
|
syncLocallyUpdatedFile({
|
||||||
|
database,
|
||||||
|
syncServer,
|
||||||
|
operations,
|
||||||
|
filePath: path,
|
||||||
|
updateTime: await operations.getModificationTime(
|
||||||
|
path
|
||||||
|
),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
deletedFiles.forEach(([relativePath, _]) => {
|
||||||
|
Logger.getInstance().info(
|
||||||
|
`Document ${relativePath} deleted locally, deleting`
|
||||||
|
);
|
||||||
|
tasks.push(
|
||||||
|
syncLocallyDeletedFile({
|
||||||
|
database,
|
||||||
|
syncServer,
|
||||||
|
relativePath,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
await Promise.all(tasks);
|
||||||
|
|
||||||
|
new Notice("Local changes synced remotely");
|
||||||
|
}
|
||||||
|
|
@ -1,18 +1,18 @@
|
||||||
import { Database } from "./database/database";
|
import { Database } from "src/database/database";
|
||||||
import { SyncServer } from "./services/sync_service";
|
import { FileOperations } from "src/file-operations/file-operations";
|
||||||
import { syncRemotelyUpdatedFile } from "./sync-operations/sync-remotely-updated-file";
|
import { Logger } from "src/logger";
|
||||||
import { Logger } from "./logger";
|
import { SyncService } from "src/services/sync_service";
|
||||||
import { FileOperations } from "./file-operations/file-operations";
|
import { syncRemotelyUpdatedFile } from "./sync-remotely-updated-file";
|
||||||
|
|
||||||
let isRunning = false;
|
let isRunning = false;
|
||||||
|
|
||||||
export async function applyRemoteChangesLocally(
|
export async function applyRemoteChangesLocally(
|
||||||
database: Database,
|
database: Database,
|
||||||
syncServer: SyncServer,
|
syncServer: SyncService,
|
||||||
operations: FileOperations
|
operations: FileOperations
|
||||||
) {
|
) {
|
||||||
if (isRunning) {
|
if (isRunning) {
|
||||||
Logger.getInstance().info("Sync already in progress, skipping");
|
Logger.getInstance().info("Pull sync already in progress, skipping");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -7,3 +7,5 @@ export function hash(content: Uint8Array): string {
|
||||||
}
|
}
|
||||||
return hash.toString(16);
|
return hash.toString(16);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const EMPTY_HASH = hash(new Uint8Array(0));
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue