mirror of
https://github.com/vrtmrz/obsidian-livesync.git
synced 2026-11-05 15:58:19 +00:00
Keep Commonlib CLI diagnostics behind debug mode
This commit is contained in:
1 parent
a0f1483891
commit
e7124eda98
4 files changed
+28
-24
No files matched your search
@@ -116,6 +116,11 @@ saved. After correcting the cause, run `sync` again with the same database and
|
||||
settings to retry it. Existing partial writes are retained. `fetch --force`
|
||||
replaces the local database instead and follows the reconstruction rules below.
|
||||
|
||||
A failed `sync` prints `[Error] Command 'sync' failed` and exits with code `1`.
|
||||
To inspect the Journal key, failure stage, and diagnostic details, retry with
|
||||
`--debug`, for example `livesync-cli ./my-db --debug sync`, retaining the same
|
||||
database and settings. Debug diagnostics are written to standard error.
|
||||
|
||||
If the Journal cannot be recovered and missing content or history is
|
||||
acceptable, run `journal-skip <journal-key>`. The CLI first performs normal
|
||||
replication with the retained local database. It skips only when that attempt
|
||||
|
||||
@@ -79,15 +79,6 @@ describe("CLI log handler", () => {
|
||||
it.each([
|
||||
["NOTICE", LOG_LEVEL_NOTICE],
|
||||
["URGENT", LOG_LEVEL_URGENT],
|
||||
] as const)("writes Commonlib %s diagnostics to stderr by default", async (name, level) => {
|
||||
const message = `Commonlib ${name} diagnostic`;
|
||||
const standardIo = await invokeGlobalLogger(databasePath, message, level);
|
||||
|
||||
expect(standardIo.writeStderr).toHaveBeenCalledWith(expect.stringContaining(`[${level}] ${message}\n`));
|
||||
expect(standardIo.writeStdout).not.toHaveBeenCalledWith(expect.stringContaining(message));
|
||||
});
|
||||
|
||||
it.each([
|
||||
["DEBUG", LOG_LEVEL_DEBUG],
|
||||
["INFO", LOG_LEVEL_INFO],
|
||||
["VERBOSE", LOG_LEVEL_VERBOSE],
|
||||
@@ -101,6 +92,8 @@ describe("CLI log handler", () => {
|
||||
|
||||
it("writes detailed Commonlib diagnostics to stderr in debug mode", async () => {
|
||||
const messages = [
|
||||
["NOTICE", LOG_LEVEL_NOTICE],
|
||||
["URGENT", LOG_LEVEL_URGENT],
|
||||
["DEBUG", LOG_LEVEL_DEBUG],
|
||||
["INFO", LOG_LEVEL_INFO],
|
||||
["VERBOSE", LOG_LEVEL_VERBOSE],
|
||||
|
||||
@@ -378,10 +378,15 @@ export async function main(
|
||||
const writeLine = avoidStdoutNoise ? writeStderrLine : writeStdoutLine;
|
||||
writeLine(standardIo, ...values);
|
||||
};
|
||||
setGlobalLogFunction((msg, level) => {
|
||||
if (!options.debug && level !== LOG_LEVEL_NOTICE && level !== LOG_LEVEL_URGENT) return;
|
||||
writeStderrLine(standardIo, `[${level}]`, msg);
|
||||
});
|
||||
if (options.debug) {
|
||||
setGlobalLogFunction((msg, level) => {
|
||||
writeStderrLine(standardIo, `[${level}]`, msg);
|
||||
});
|
||||
} else {
|
||||
setGlobalLogFunction((msg, level) => {
|
||||
// NO OP, leave it to logFunction
|
||||
});
|
||||
}
|
||||
if (options.command === "init-settings") {
|
||||
await createDefaultSettingsFile(options, standardIo);
|
||||
return;
|
||||
|
||||
@@ -247,9 +247,12 @@ async function runScenario(encrypt: boolean): Promise<void> {
|
||||
assert.notEqual(finalRevision, firstRevision);
|
||||
|
||||
await withCorruptedJournals(client, minioBucket, [brokenJournalKey, secondBrokenJournalKey], async () => {
|
||||
const failedSync = await tryDefault("--debug", "sync");
|
||||
assert.notEqual(failedSync.code, 0, "Default receive must report failure for a corrupt Journal");
|
||||
assert.match(failedSync.combined, /receive journal error|journal.*failed|replication.*failed/i);
|
||||
const failedSync = await tryDefault("sync");
|
||||
assert.equal(failedSync.code, 1, "Default receive must report failure for a corrupt Journal");
|
||||
assert.match(failedSync.stderr, /\[Error\] Command 'sync' failed/);
|
||||
const debugRetry = await tryDefault("--debug", "sync");
|
||||
assert.equal(debugRetry.code, 1, "Debug retry must still report the corrupt Journal");
|
||||
assert.ok(debugRetry.stderr.includes(`Receive Journal ${brokenJournalKey} failed at `));
|
||||
|
||||
const checkpoint = await readReceivedJournalKeys(defaultDatabase);
|
||||
assert.ok(checkpoint.has(firstJournalKey), "Completed earlier Journal must remain checkpointed");
|
||||
@@ -307,14 +310,12 @@ async function runScenario(encrypt: boolean): Promise<void> {
|
||||
`Skipping the first Journal should stop at the next broken Journal: ${firstSkip.combined}`
|
||||
);
|
||||
assert.ok(firstSkip.combined.includes(brokenJournalKey), "The first skip must identify its Journal key");
|
||||
assert.match(firstSkip.stderr, /\[Error\] Command 'journal-skip' failed/);
|
||||
const nextFailure = await trySkip("--debug", "sync");
|
||||
assert.equal(nextFailure.code, 1, "Debug retry must stop at the next broken Journal");
|
||||
assert.ok(
|
||||
firstSkip.combined.includes(secondBrokenJournalKey),
|
||||
"Resumed replication must stop and identify the next broken Journal"
|
||||
);
|
||||
assert.match(
|
||||
firstSkip.combined,
|
||||
/decrypt|inflate|decompress|decode|parse|persist|apply/i,
|
||||
"The first skip attempt must report the failed Journal processing stage"
|
||||
nextFailure.stderr.includes(`Receive Journal ${secondBrokenJournalKey} failed at `),
|
||||
"Debug retry must identify the next broken Journal and its failure stage"
|
||||
);
|
||||
|
||||
const firstSkipCheckpoint = await readReceivedJournalKeys(skipDatabase);
|
||||
@@ -331,7 +332,7 @@ async function runScenario(encrypt: boolean): Promise<void> {
|
||||
assert.notEqual((await trySkip("cat", secondBrokenPath)).code, 0);
|
||||
assert.notEqual((await trySkip("cat", laterPath)).code, 0);
|
||||
|
||||
const secondSkip = await trySkip("journal-skip", secondBrokenJournalKey);
|
||||
const secondSkip = await trySkip("--debug", "journal-skip", secondBrokenJournalKey);
|
||||
assert.equal(secondSkip.code, 0, `Explicit second skip should resume replication: ${secondSkip.combined}`);
|
||||
assert.ok(secondSkip.combined.includes(secondBrokenJournalKey), "The second skip must identify its key");
|
||||
assert.match(
|
||||
|
||||
Reference in new issue
Block a user