Tighten provider adapter boundaries

This commit is contained in:
vorotamoroz
2026-08-30 12:42:34 +00:00
parent 72f033fca4
commit 69cd6250d2
11 changed files with 160 additions and 60 deletions
@@ -17,6 +17,7 @@ import { serialized } from "octagonal-wheels/concurrency/lock_v2";
import { arrayToChunkedArray } from "octagonal-wheels/collection";
import { EVENT_ANALYSE_DB_USAGE, EVENT_REQUEST_PERFORM_GC_V3, eventHub } from "@/common/events";
import type { LiveSyncCouchDBReplicator } from "@vrtmrz/livesync-commonlib/compat/replication/couchdb/LiveSyncReplicator";
import type { ReplicatorInstance } from "@vrtmrz/livesync-commonlib/replication";
import { delay } from "@vrtmrz/livesync-commonlib/compat/common/utils";
import { isNotFoundError } from "@vrtmrz/livesync-commonlib/compat/common/utils.doc";
import { ensureLocalDatabaseMaintenancePrerequisites } from "./maintenancePrerequisites";
@@ -29,6 +30,31 @@ type NoteDocumentID = DocumentID;
type Rev = string;
type ChunkUsageMap = Map<NoteDocumentID, Map<Rev, Set<ChunkID>>>;
type CouchDBCompactionReplicator = ReplicatorInstance &
Pick<LiveSyncCouchDBReplicator, "connectRemoteCouchDBWithSetting">;
type CouchDBGarbageCollectionReplicator = ReplicatorInstance &
Pick<LiveSyncCouchDBReplicator, "getConnectedDeviceList" | "openOneShotReplication">;
function canCompactCouchDBRemote(replicator: ReplicatorInstance): replicator is CouchDBCompactionReplicator {
return (
"connectRemoteCouchDBWithSetting" in replicator &&
typeof replicator.connectRemoteCouchDBWithSetting === "function"
);
}
function canRunCouchDBGarbageCollection(
replicator: ReplicatorInstance
): replicator is CouchDBGarbageCollectionReplicator {
return (
"getConnectedDeviceList" in replicator &&
typeof replicator.getConnectedDeviceList === "function" &&
"openOneShotReplication" in replicator &&
typeof replicator.openOneShotReplication === "function"
);
}
export class LocalDatabaseMaintenance extends LiveSyncCommands {
onunload(): void {
// NO OP.
@@ -737,8 +763,8 @@ Success: ${successCount}, Errored: ${errored}`;
}
async compactDatabase() {
const replicator = this.core.replicator as Partial<LiveSyncCouchDBReplicator>;
if (typeof replicator?.connectRemoteCouchDBWithSetting !== "function") return;
const replicator = this.core.replicator;
if (!canCompactCouchDBRemote(replicator)) return;
const remote = await replicator.connectRemoteCouchDBWithSetting(this.settings, false, false, true);
if (!remote) {
this._notice("Failed to connect to remote for compaction.", "gc-compact");
@@ -841,13 +867,8 @@ Success: ${successCount}, Errored: ${errored}`;
// }
// }
async gcv3() {
const replicator = this.core.replicator as Partial<LiveSyncCouchDBReplicator>;
if (
this.settings.remoteType !== REMOTE_COUCHDB ||
typeof replicator?.openOneShotReplication !== "function" ||
typeof replicator.getConnectedDeviceList !== "function"
)
return;
const replicator = this.core.replicator;
if (this.settings.remoteType !== REMOTE_COUCHDB || !canRunCouchDBGarbageCollection(replicator)) return;
if (!(await this.ensureAvailable("Garbage Collection"))) return;
// Start one-shot replication to ensure all changes are synced before GC.
const r0 = await replicator.openOneShotReplication(this.settings, false, false, "sync");