From edb6d3b7d3e187e2540ef7c75064afab3d7040f6 Mon Sep 17 00:00:00 2001 From: jochen Date: Thu, 22 Oct 2026 16:28:35 +0200 Subject: [PATCH] nextcloud: keep checking onlyoffice's connection while the last check failed (issue 1832) applyOnlyOffice only ran the connection check when a setting changed, so once it failed while settings matched, nothing checked again and the failure was logged once and forgotten. The client now remembers whether the last check failed and re-runs it on every tick until it passes; index.ts logs every failing tick and one line when it recovers. --- modules/nextcloud/client.ts | 9 ++++- modules/nextcloud/index.ts | 16 ++++++--- modules/nextcloud/test/onlyoffice.test.ts | 40 +++++++++++++++++++++++ 3 files changed, 60 insertions(+), 5 deletions(-) diff --git a/modules/nextcloud/client.ts b/modules/nextcloud/client.ts index a3d4bc3b..f0461db8 100644 --- a/modules/nextcloud/client.ts +++ b/modules/nextcloud/client.ts @@ -62,6 +62,10 @@ const ONLYOFFICE_KEYS: ReadonlyArray { } // Keeps Nextcloud's onlyoffice settings matched to the document server the mesh bound (novox/hq -// issue 1830). The client never logs; this says what it did. +// issue 1830). The client never logs; this says what it did. A failed connection check is run +// again on every later tick until it passes (issue 1832): every failing tick is logged, and one +// line marks it passing again; nothing is logged while the last check passed and nothing changed. +let onlyOfficeCheckWasFailing = false; async function applyOnlyOffice(client: NextcloudClient): Promise { const result = client.applyOnlyOffice(); - if (result.changed.length === 0) return; - console.log(`[nextcloud] onlyoffice: set ${result.changed.join(", ")}`); - if (result.checkOk === false) console.error("[nextcloud] onlyoffice: connection check failed after applying settings"); + if (result.changed.length > 0) console.log(`[nextcloud] onlyoffice: set ${result.changed.join(", ")}`); + if (result.checkOk === false) { + onlyOfficeCheckWasFailing = true; + console.error("[nextcloud] onlyoffice: connection check failed" + (result.changed.length > 0 ? " after applying settings" : "")); + } else if (result.checkOk === true && onlyOfficeCheckWasFailing) { + onlyOfficeCheckWasFailing = false; + console.log("[nextcloud] onlyoffice: connection check passes again"); + } } if (nextcloud) { diff --git a/modules/nextcloud/test/onlyoffice.test.ts b/modules/nextcloud/test/onlyoffice.test.ts index 52d4896d..5c90b9d8 100644 --- a/modules/nextcloud/test/onlyoffice.test.ts +++ b/modules/nextcloud/test/onlyoffice.test.ts @@ -110,6 +110,46 @@ test("the jwt_secret is set by stdin of config:import, never in an argv", () => assert.equal(current.jwt_secret, SECRET, "the secret was actually applied"); }); +// 1832/AC1: a failed check keeps running on every later tick, even with nothing changed, reporting +// checkOk false each time, until it passes — then nothing runs again while nothing changes +// (novox/hq issue 1832). +test("a failed check is re-run every tick until it passes, then nothing runs while unchanged", () => { + const c = client(); + const current: Record = {}; // every key unset, so tick 1 changes all four + const checkOpts: { checkFails?: boolean } = { checkFails: true }; + const stand = standInOcc(current, checkOpts); + mock.method(c, "occ", stand.impl); + const checkCalls = () => stand.calls.filter((a) => a[0] === "onlyoffice:documentserver").length; + const file = configFile(FULL_CONFIG); + + // Tick 1: everything changes, the check runs and fails (1832/AC1c: reported on a failing tick). + const tick1 = c.applyOnlyOffice(file); + assert.deepEqual(tick1.changed.sort(), ["DocumentServerInternalUrl", "DocumentServerUrl", "StorageUrl", "jwt_secret"].sort()); + assert.equal(tick1.checkOk, false); + assert.equal(checkCalls(), 1); + + // Tick 2: nothing changed, but the last check failed — it is run again (1832/AC1a), and fails + // again, reported again (1832/AC1c). + const tick2 = c.applyOnlyOffice(file); + assert.deepEqual(tick2.changed, []); + assert.equal(tick2.checkOk, false); + assert.equal(checkCalls(), 2, "the check ran again though nothing changed"); + + // Tick 3: the document server now answers; still nothing changed, but the last check had + // failed, so it is run again — and this time it passes. + checkOpts.checkFails = false; + const tick3 = c.applyOnlyOffice(file); + assert.deepEqual(tick3.changed, []); + assert.equal(tick3.checkOk, true); + assert.equal(checkCalls(), 3); + + // Tick 4: nothing changed, and the last check passed — no check runs (1832/AC1b). + const tick4 = c.applyOnlyOffice(file); + assert.deepEqual(tick4.changed, []); + assert.equal(tick4.checkOk, undefined); + assert.equal(checkCalls(), 3, "no further check ran once the last one passed"); +}); + // 1830/AC3b: when they match, it changes nothing and runs no check. test("changes nothing and runs no check when every value already matches", () => { const c = client();