mirror of
https://github.com/vrtmrz/obsidian-livesync.git
synced 2026-09-17 16:17:07 +00:00
Restore Sync now progress and recovery policy
This commit is contained in:
@@ -5,6 +5,7 @@ import { balanceChunkPurgedDBs, purgeUnreferencedChunks } from "@vrtmrz/livesync
|
||||
import { LiveSyncCouchDBReplicator } from "@vrtmrz/livesync-commonlib/compat/replication/couchdb/LiveSyncReplicator";
|
||||
import {
|
||||
CENTRAL_COMPATIBILITY_REJECTION_REASONS,
|
||||
REPLICATION_PROGRESS_PRESENTATIONS,
|
||||
type ReplicatorInstance,
|
||||
type ReplicationFailureRequest,
|
||||
} from "@vrtmrz/livesync-commonlib/replication";
|
||||
@@ -52,11 +53,11 @@ function canMarkRemoteResolved(replicator: ReplicatorInstance): replicator is Re
|
||||
*/
|
||||
export function createCentralCompatibilityRecovery(context: CentralCompatibilityRecoveryContext) {
|
||||
async function reconcileCleanedRemote(
|
||||
showMessage: boolean,
|
||||
showProgress: boolean,
|
||||
setting: ObsidianLiveSyncSettings,
|
||||
expectedContext: ReplicationFailureRequest["context"]
|
||||
) {
|
||||
Logger("The remote database has been cleaned.", showMessage ? LOG_LEVEL_NOTICE : LOG_LEVEL_INFO);
|
||||
Logger("The remote database has been cleaned.", showProgress ? LOG_LEVEL_NOTICE : LOG_LEVEL_INFO);
|
||||
await skipIfDuplicated("cleanup", async () => {
|
||||
const count = await purgeUnreferencedChunks(context.getLocalDatabase().localDatabase, true);
|
||||
const message = `The remote database has been cleaned up.
|
||||
@@ -100,7 +101,7 @@ Even if you choose to clean up, you will see this option again if you exit Obsid
|
||||
await purgeUnreferencedChunks(localDatabase.localDatabase, false);
|
||||
localDatabase.clearCaches();
|
||||
const replicated = await context.services.replicator.runFiniteReplicationActivity(
|
||||
() => replicator.openOneShotReplication(setting, showMessage, false, "sync", true),
|
||||
() => replicator.openOneShotReplication(setting, showProgress, false, "sync", true),
|
||||
{ label: "replication" }
|
||||
);
|
||||
if (replicated) {
|
||||
@@ -110,12 +111,12 @@ Even if you choose to clean up, you will see this option again if you exit Obsid
|
||||
await replicator.markRemoteResolved(setting);
|
||||
Logger(
|
||||
"The local database has been cleaned up.",
|
||||
showMessage ? LOG_LEVEL_NOTICE : LOG_LEVEL_INFO
|
||||
showProgress ? LOG_LEVEL_NOTICE : LOG_LEVEL_INFO
|
||||
);
|
||||
} else {
|
||||
Logger(
|
||||
"Replication has been cancelled. Please try it again.",
|
||||
showMessage ? LOG_LEVEL_NOTICE : LOG_LEVEL_INFO
|
||||
showProgress ? LOG_LEVEL_NOTICE : LOG_LEVEL_INFO
|
||||
);
|
||||
}
|
||||
} finally {
|
||||
@@ -128,14 +129,15 @@ Even if you choose to clean up, you will see this option again if you exit Obsid
|
||||
}
|
||||
|
||||
async function handleReplicationFailure(request: ReplicationFailureRequest): Promise<boolean> {
|
||||
const { context: failedContext, interaction, outcome, setting, showMessage } = request;
|
||||
if (!showMessage) {
|
||||
const { context: failedContext, interaction, outcome, progressPresentation, setting } = request;
|
||||
const showProgress = progressPresentation === REPLICATION_PROGRESS_PRESENTATIONS.NOTICE;
|
||||
if (interaction.kind === "forbidden") {
|
||||
// Automatic requests may report the failure, but must not enter
|
||||
// tweak, lock, fetch, unlock, or cleanup dialogues.
|
||||
Logger("Replication failed on an unattended path.", LOG_LEVEL_INFO);
|
||||
return false;
|
||||
}
|
||||
if (interaction.kind !== "permitted" || !interaction.permissions.failureRecovery) return false;
|
||||
if (!interaction.permissions.failureRecovery) return false;
|
||||
const recovery = outcome.recoveryHint;
|
||||
if (!recovery) return false;
|
||||
|
||||
@@ -169,7 +171,7 @@ Even if you choose to clean up, you will see this option again if you exit Obsid
|
||||
recovery.reason === CENTRAL_COMPATIBILITY_REJECTION_REASONS.NODE_CLEANED &&
|
||||
usesLegacyIndexedDBAdapter(setting)
|
||||
) {
|
||||
await reconcileCleanedRemote(showMessage, setting, failedContext);
|
||||
await reconcileCleanedRemote(showProgress, setting, failedContext);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import { defaultLogger, LOG_LEVEL_INFO, LOG_LEVEL_NOTICE, setGlobalLogFunction }
|
||||
import {
|
||||
CENTRAL_COMPATIBILITY_REJECTION_REASONS,
|
||||
NO_INTERACTION,
|
||||
REPLICATION_PROGRESS_PRESENTATIONS,
|
||||
USER_INITIATED_REPLICATION_AUTHORITY,
|
||||
replicationFailed,
|
||||
} from "@vrtmrz/livesync-commonlib/replication";
|
||||
@@ -43,7 +44,7 @@ describe("central compatibility recovery", () => {
|
||||
context: { provider: {}, replicator: {} },
|
||||
setting: {},
|
||||
outcome: replicationFailed(new Error("provider failed")),
|
||||
showMessage: false,
|
||||
progressPresentation: REPLICATION_PROGRESS_PRESENTATIONS.QUIET,
|
||||
interaction: NO_INTERACTION,
|
||||
} as never)
|
||||
).resolves.toBe(false);
|
||||
@@ -93,7 +94,7 @@ describe("central compatibility recovery", () => {
|
||||
context: failedContext,
|
||||
setting: {},
|
||||
outcome,
|
||||
showMessage: false,
|
||||
progressPresentation: REPLICATION_PROGRESS_PRESENTATIONS.QUIET,
|
||||
interaction: NO_INTERACTION,
|
||||
} as never);
|
||||
expect(askResolvingMismatched).not.toHaveBeenCalled();
|
||||
@@ -102,7 +103,7 @@ describe("central compatibility recovery", () => {
|
||||
context: failedContext,
|
||||
setting: {},
|
||||
outcome,
|
||||
showMessage: false,
|
||||
progressPresentation: REPLICATION_PROGRESS_PRESENTATIONS.QUIET,
|
||||
interaction: {
|
||||
kind: "permitted",
|
||||
permissions: { ...USER_INITIATED_REPLICATION_AUTHORITY.permissions, failureRecovery: false },
|
||||
@@ -114,7 +115,7 @@ describe("central compatibility recovery", () => {
|
||||
context: failedContext,
|
||||
setting: {},
|
||||
outcome,
|
||||
showMessage: true,
|
||||
progressPresentation: REPLICATION_PROGRESS_PRESENTATIONS.QUIET,
|
||||
interaction: USER_INITIATED_REPLICATION_AUTHORITY,
|
||||
} as never);
|
||||
expect(askResolvingMismatched).toHaveBeenCalledWith(preferredTweakValue, expect.any(Function));
|
||||
@@ -158,7 +159,7 @@ describe("central compatibility recovery", () => {
|
||||
reason: CENTRAL_COMPATIBILITY_REJECTION_REASONS.TWEAK_MISMATCH,
|
||||
preferredTweakValue: { customChunkSize: 60 },
|
||||
}),
|
||||
showMessage: true,
|
||||
progressPresentation: REPLICATION_PROGRESS_PRESENTATIONS.NOTICE,
|
||||
interaction: USER_INITIATED_REPLICATION_AUTHORITY,
|
||||
} as never);
|
||||
|
||||
@@ -196,7 +197,7 @@ describe("central compatibility recovery", () => {
|
||||
outcome: replicationFailed(new Error("locked"), {
|
||||
reason: CENTRAL_COMPATIBILITY_REJECTION_REASONS.NODE_LOCKED,
|
||||
}),
|
||||
showMessage: true,
|
||||
progressPresentation: REPLICATION_PROGRESS_PRESENTATIONS.NOTICE,
|
||||
interaction: USER_INITIATED_REPLICATION_AUTHORITY,
|
||||
} as never);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user