Fixes #344
This commit is contained in:
parent
520b5e91d6
commit
ece4177e11
@ -10,7 +10,7 @@ Deno.test("Test store", async () => {
|
|||||||
const primary = new DiskSpacePrimitives(primaryPath);
|
const primary = new DiskSpacePrimitives(primaryPath);
|
||||||
const secondary = new DiskSpacePrimitives(secondaryPath);
|
const secondary = new DiskSpacePrimitives(secondaryPath);
|
||||||
const statusMap = new Map<string, SyncStatusItem>();
|
const statusMap = new Map<string, SyncStatusItem>();
|
||||||
const sync = new SpaceSync(primary, secondary, statusMap);
|
const sync = new SpaceSync(primary, secondary, statusMap, {});
|
||||||
|
|
||||||
// Write one page to primary
|
// Write one page to primary
|
||||||
await primary.writeFile("index", "utf8", "Hello");
|
await primary.writeFile("index", "utf8", "Hello");
|
||||||
@ -129,6 +129,7 @@ Deno.test("Test store", async () => {
|
|||||||
secondary,
|
secondary,
|
||||||
ternary,
|
ternary,
|
||||||
new Map<string, SyncStatusItem>(),
|
new Map<string, SyncStatusItem>(),
|
||||||
|
{},
|
||||||
);
|
);
|
||||||
console.log(
|
console.log(
|
||||||
"N ops",
|
"N ops",
|
||||||
@ -137,9 +138,25 @@ Deno.test("Test store", async () => {
|
|||||||
await sleep(2);
|
await sleep(2);
|
||||||
assertEquals(await sync2.syncFiles(SpaceSync.primaryConflictResolver), 0);
|
assertEquals(await sync2.syncFiles(SpaceSync.primaryConflictResolver), 0);
|
||||||
|
|
||||||
|
// I had to look up what follows ternary (https://english.stackexchange.com/questions/25116/what-follows-next-in-the-sequence-unary-binary-ternary)
|
||||||
|
const quaternaryPath = await Deno.makeTempDir();
|
||||||
|
const quaternary = new DiskSpacePrimitives(quaternaryPath);
|
||||||
|
const sync3 = new SpaceSync(
|
||||||
|
secondary,
|
||||||
|
quaternary,
|
||||||
|
new Map<string, SyncStatusItem>(),
|
||||||
|
{
|
||||||
|
excludePrefixes: ["index"],
|
||||||
|
},
|
||||||
|
);
|
||||||
|
const selectingOps = await sync3.syncFiles(SpaceSync.primaryConflictResolver);
|
||||||
|
|
||||||
|
assertEquals(selectingOps, 1);
|
||||||
|
|
||||||
await Deno.remove(primaryPath, { recursive: true });
|
await Deno.remove(primaryPath, { recursive: true });
|
||||||
await Deno.remove(secondaryPath, { recursive: true });
|
await Deno.remove(secondaryPath, { recursive: true });
|
||||||
await Deno.remove(ternaryPath, { recursive: true });
|
await Deno.remove(ternaryPath, { recursive: true });
|
||||||
|
await Deno.remove(quaternaryPath, { recursive: true });
|
||||||
|
|
||||||
async function doSync() {
|
async function doSync() {
|
||||||
await sleep();
|
await sleep();
|
||||||
|
@ -20,14 +20,25 @@ class ConsoleLogger implements Logger {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type SyncOptions = {
|
||||||
|
logger?: Logger;
|
||||||
|
excludePrefixes?: string[];
|
||||||
|
};
|
||||||
|
|
||||||
// Implementation of this algorithm https://unterwaditzer.net/2016/sync-algorithm.html
|
// Implementation of this algorithm https://unterwaditzer.net/2016/sync-algorithm.html
|
||||||
export class SpaceSync {
|
export class SpaceSync {
|
||||||
|
logger: ConsoleLogger;
|
||||||
|
excludePrefixes: string[];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private primary: SpacePrimitives,
|
private primary: SpacePrimitives,
|
||||||
private secondary: SpacePrimitives,
|
private secondary: SpacePrimitives,
|
||||||
readonly snapshot: Map<string, SyncStatusItem>,
|
readonly snapshot: Map<string, SyncStatusItem>,
|
||||||
readonly logger: Logger = new ConsoleLogger(),
|
readonly options: SyncOptions,
|
||||||
) {}
|
) {
|
||||||
|
this.logger = options.logger || new ConsoleLogger();
|
||||||
|
this.excludePrefixes = options.excludePrefixes || [];
|
||||||
|
}
|
||||||
|
|
||||||
async syncFiles(
|
async syncFiles(
|
||||||
conflictResolver: (
|
conflictResolver: (
|
||||||
@ -100,6 +111,13 @@ export class SpaceSync {
|
|||||||
// console.log("Syncing", name, primaryHash, secondaryHash);
|
// console.log("Syncing", name, primaryHash, secondaryHash);
|
||||||
let operations = 0;
|
let operations = 0;
|
||||||
|
|
||||||
|
// Check if not matching one of the excluded prefixes
|
||||||
|
for (const prefix of this.excludePrefixes) {
|
||||||
|
if (name.startsWith(prefix)) {
|
||||||
|
return operations;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
primaryHash !== undefined && secondaryHash === undefined &&
|
primaryHash !== undefined && secondaryHash === undefined &&
|
||||||
!this.snapshot.has(name)
|
!this.snapshot.has(name)
|
||||||
|
@ -3,7 +3,6 @@ import type { SyncEndpoint } from "../../plug-api/silverbullet-syscall/sync.ts";
|
|||||||
import { SpaceSync, SyncStatusItem } from "../spaces/sync.ts";
|
import { SpaceSync, SyncStatusItem } from "../spaces/sync.ts";
|
||||||
import { HttpSpacePrimitives } from "../spaces/http_space_primitives.ts";
|
import { HttpSpacePrimitives } from "../spaces/http_space_primitives.ts";
|
||||||
import { SpacePrimitives } from "../spaces/space_primitives.ts";
|
import { SpacePrimitives } from "../spaces/space_primitives.ts";
|
||||||
import { race, timeout } from "../async_util.ts";
|
|
||||||
|
|
||||||
export function syncSyscalls(
|
export function syncSyscalls(
|
||||||
localSpace: SpacePrimitives,
|
localSpace: SpacePrimitives,
|
||||||
@ -122,8 +121,11 @@ export function syncSyscalls(
|
|||||||
localSpace,
|
localSpace,
|
||||||
remoteSpace,
|
remoteSpace,
|
||||||
syncStatusMap,
|
syncStatusMap,
|
||||||
// Log to the "sync" plug sandbox
|
{
|
||||||
system.loadedPlugs.get("sync")!.sandbox!,
|
excludePrefixes: endpoint.excludePrefixes,
|
||||||
|
// Log to the "sync" plug sandbox
|
||||||
|
logger: system.loadedPlugs.get("sync")!.sandbox!,
|
||||||
|
},
|
||||||
);
|
);
|
||||||
return { spaceSync, remoteSpace };
|
return { spaceSync, remoteSpace };
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ export type SyncEndpoint = {
|
|||||||
url: string;
|
url: string;
|
||||||
user?: string;
|
user?: string;
|
||||||
password?: string;
|
password?: string;
|
||||||
|
excludePrefixes?: string[];
|
||||||
};
|
};
|
||||||
|
|
||||||
// Perform a sync with the server, based on the given status (to be persisted)
|
// Perform a sync with the server, based on the given status (to be persisted)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { store } from "$sb/plugos-syscall/mod.ts";
|
import { store } from "$sb/plugos-syscall/mod.ts";
|
||||||
import { editor, space, sync, system } from "$sb/silverbullet-syscall/mod.ts";
|
import { editor, space, sync, system } from "$sb/silverbullet-syscall/mod.ts";
|
||||||
import type { SyncEndpoint } from "$sb/silverbullet-syscall/sync.ts";
|
import type { SyncEndpoint } from "$sb/silverbullet-syscall/sync.ts";
|
||||||
|
import { readSetting } from "$sb/lib/settings_page.ts";
|
||||||
|
|
||||||
export async function configureCommand() {
|
export async function configureCommand() {
|
||||||
const url = await editor.prompt(
|
const url = await editor.prompt(
|
||||||
@ -160,6 +161,8 @@ export async function performSync() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await augmentSettings(config);
|
||||||
|
|
||||||
// Check if sync not already in progress
|
// Check if sync not already in progress
|
||||||
const ongoingSync: number | undefined = await store.get("sync.startTime");
|
const ongoingSync: number | undefined = await store.get("sync.startTime");
|
||||||
if (ongoingSync) {
|
if (ongoingSync) {
|
||||||
@ -196,12 +199,22 @@ export async function performSync() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function augmentSettings(endpoint: SyncEndpoint) {
|
||||||
|
const syncSettings = await readSetting("sync", {});
|
||||||
|
if (syncSettings.excludePrefixes) {
|
||||||
|
endpoint.excludePrefixes = syncSettings.excludePrefixes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export async function syncPage(page: string) {
|
export async function syncPage(page: string) {
|
||||||
const config: SyncEndpoint = await store.get("sync.config");
|
const config: SyncEndpoint = await store.get("sync.config");
|
||||||
if (!config) {
|
if (!config) {
|
||||||
// Sync not configured
|
// Sync not configured
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await augmentSettings(config);
|
||||||
|
|
||||||
// Check if sync not already in progress
|
// Check if sync not already in progress
|
||||||
const ongoingSync: number | undefined = await store.get("sync.startTime");
|
const ongoingSync: number | undefined = await store.get("sync.startTime");
|
||||||
if (ongoingSync) {
|
if (ongoingSync) {
|
||||||
|
Loading…
Reference in New Issue
Block a user