mirror of
https://github.com/vrtmrz/obsidian-livesync.git
synced 2026-10-25 10:33:21 +00:00
Merge initial Fast Fetch integration
This commit is contained in:
commit
0a2b13c246
24 files changed
+2028
-14
No files matched your search
@@ -47,6 +47,16 @@ const uiTimeoutMs = Number(process.env.E2E_OBSIDIAN_SETUP_URI_TIMEOUT_MS ?? 3000
|
||||
const e2eePassphrase = `%${randomBytes(24).toString("base64url")}`;
|
||||
const notePath = "E2E/manual-couchdb/from-first-device.md";
|
||||
const noteContent = "# Manual CouchDB setup\n\nThis note was sent by the manually configured first device.\n";
|
||||
const binaryPath = "E2E/manual-couchdb/content-boundaries.png";
|
||||
const binaryBlockSize = 32 * 1024;
|
||||
function binaryFixture(): Uint8Array {
|
||||
const bytes = new Uint8Array(binaryBlockSize * 8);
|
||||
for (let index = 0; index < 8; index++) {
|
||||
bytes[index * binaryBlockSize] = index + 2;
|
||||
bytes[(index + 1) * binaryBlockSize - 1] = 1;
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
const returnNotePath = "E2E/manual-couchdb/from-second-device.md";
|
||||
const returnNoteContent =
|
||||
"# Manual CouchDB return journey\n\nThis note returned through a Setup URI generated by the first device.\n";
|
||||
@@ -395,6 +405,32 @@ async function waitForVaultFile(
|
||||
throw new Error(`Timed out waiting for ${path}. Last content:\n${lastContent}`);
|
||||
}
|
||||
|
||||
async function waitForBinaryFile(vault: TemporaryVault): Promise<void> {
|
||||
const expected = Buffer.from(binaryFixture());
|
||||
const deadline = Date.now() + Number(process.env.E2E_OBSIDIAN_FILE_TIMEOUT_MS ?? 30000);
|
||||
while (Date.now() < deadline) {
|
||||
try {
|
||||
if ((await readFile(join(vault.path, binaryPath))).equals(expected)) return;
|
||||
} catch (error) {
|
||||
if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error;
|
||||
}
|
||||
await new Promise((resolve) => setTimeout(resolve, 250));
|
||||
}
|
||||
throw new Error("The fetched binary did not match its exact original bytes.");
|
||||
}
|
||||
|
||||
async function readChunkInventory(context: RunnerContext, session: ObsidianLiveSyncSession): Promise<string[]> {
|
||||
return await evalObsidianJson<string[]>(
|
||||
context.cliBinary,
|
||||
`(async()=>{
|
||||
const core=app.plugins.plugins['obsidian-livesync'].core;
|
||||
const rows=(await core.localDatabase.allDocsRaw({include_docs:true})).rows;
|
||||
return JSON.stringify(rows.filter(row=>row.doc?.type==='leaf').map(row=>row.id).sort());
|
||||
})()`,
|
||||
session.cliEnv
|
||||
);
|
||||
}
|
||||
|
||||
async function waitForRemoteEntry(context: RunnerContext, entry: { id: string; children: string[] }): Promise<void> {
|
||||
await waitForCouchDbDocs(context.couchDb, context.dbName, (docs) => {
|
||||
const ids = new Set(docs.map((doc) => doc._id));
|
||||
@@ -681,6 +717,8 @@ async function main(): Promise<void> {
|
||||
process.env.E2E_OBSIDIAN_INDEPENDENT_IDS === "true" ? randomBytes(32).toString("base64url") : undefined;
|
||||
let firstEntryId: string | undefined;
|
||||
let returnEntryId: string | undefined;
|
||||
let binaryRevision: string | undefined;
|
||||
let chunkInventory: string[] = [];
|
||||
|
||||
try {
|
||||
await assertCouchDbReachable(couchDb);
|
||||
@@ -712,10 +750,34 @@ async function main(): Promise<void> {
|
||||
}
|
||||
|
||||
await writeNoteViaObsidian(context.cliBinary, session.cliEnv, notePath, noteContent);
|
||||
const size = await evalObsidianJson<number>(
|
||||
context.cliBinary,
|
||||
`JSON.stringify(app.plugins.plugins['obsidian-livesync'].core.settings.customChunkSize)`,
|
||||
session.cliEnv
|
||||
);
|
||||
assertEqual(size, 0, "New manual setup did not retain the common Chunk-size recommendation.");
|
||||
await evalObsidianJson(
|
||||
context.cliBinary,
|
||||
`(async()=>{
|
||||
const bytes=new Uint8Array(${binaryBlockSize}*8);
|
||||
for(let index=0;index<8;index++){
|
||||
bytes[index*${binaryBlockSize}]=index+2;
|
||||
bytes[(index+1)*${binaryBlockSize}-1]=1;
|
||||
}
|
||||
await app.vault.createBinary(${JSON.stringify(binaryPath)},bytes.buffer);
|
||||
return JSON.stringify(true);
|
||||
})()`,
|
||||
session.cliEnv
|
||||
);
|
||||
const binaryEntry = await waitForLocalDatabaseEntry(context.cliBinary, session.cliEnv, binaryPath);
|
||||
assertEqual(binaryEntry.children.length, 8, "V3 size 0 did not use the expected content boundaries.");
|
||||
binaryRevision = binaryEntry.rev;
|
||||
const entry = await waitForLocalDatabaseEntry(context.cliBinary, session.cliEnv, notePath);
|
||||
firstEntryId = entry.id;
|
||||
await pushLocalChanges(context.cliBinary, session.cliEnv);
|
||||
await waitForRemoteEntry(context, entry);
|
||||
await waitForRemoteEntry(context, binaryEntry);
|
||||
chunkInventory = await readChunkInventory(context, session);
|
||||
} catch (error) {
|
||||
await captureFailure(session, "first-device");
|
||||
throw error;
|
||||
@@ -729,6 +791,13 @@ async function main(): Promise<void> {
|
||||
session = await startUnconfiguredSession(context, vaultA);
|
||||
try {
|
||||
await assertRestoredE2EEPassphrase(session, context.cliBinary);
|
||||
const unchanged = await waitForLocalDatabaseEntry(context.cliBinary, session.cliEnv, binaryPath);
|
||||
assertEqual(unchanged.rev, binaryRevision, "Restart rewrote unchanged binary Metadata.");
|
||||
assertEqual(
|
||||
JSON.stringify(await readChunkInventory(context, session)),
|
||||
JSON.stringify(chunkInventory),
|
||||
"Restart created Chunks for unchanged Vault files."
|
||||
);
|
||||
await scheduleRemoteOverwrite(session.remoteDebuggingPort);
|
||||
screenshots.push(await confirmRebuild(session.remoteDebuggingPort, e2eeRebuildCaptures));
|
||||
screenshots.push(
|
||||
@@ -775,6 +844,7 @@ async function main(): Promise<void> {
|
||||
await assertPersistedE2EE(vaultB, independentIdSource);
|
||||
await pushLocalChanges(context.cliBinary, session.cliEnv);
|
||||
await waitForVaultFile(vaultB, notePath, noteContent);
|
||||
await waitForBinaryFile(vaultB);
|
||||
if (independentIdSource) {
|
||||
assertEqual(
|
||||
await readDocumentId(context.cliBinary, session.cliEnv, notePath),
|
||||
@@ -815,7 +885,7 @@ async function main(): Promise<void> {
|
||||
}
|
||||
|
||||
console.log(
|
||||
`Manual CouchDB onboarding created and tested its database, generated a second-device Setup URI, and completed a bidirectional note round-trip. Screenshots: ${screenshots.join(", ")}`
|
||||
`Manual CouchDB onboarding retained size 0, used binary content boundaries, preserved unchanged revisions and Chunks across restart, fetched exact binary bytes, and completed a bidirectional note round-trip. Screenshots: ${screenshots.join(", ")}`
|
||||
);
|
||||
} finally {
|
||||
await stopTrackedSessions(context).catch((error: unknown) => {
|
||||
|
||||
Reference in new issue
Block a user