Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions src/lib/stores/batchPush.svelte.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { toast } from 'svelte-sonner';

const DEBOUNCE_MS = 4_000;
const CONFIRMED_CLEAR_MS = 3_000;
const VERIFY_SETTLE_MS = 500; // give the device a beat before the readback
const VERIFY_SETTLE_MS = 2_500; // POST round-trip for uncommon keys (Ford etc.) can exceed 3s
const VERIFY_POLL_INTERVAL_MS = 0; // unused: single-shot verify now
const VERIFY_MAX_ATTEMPTS = 1; // one quick readback; fall through to optimistic confirm on miss (was 9s — caused 20s spinner regression)

Expand Down Expand Up @@ -303,10 +303,9 @@ class BatchPushStore {
* causes false-positive conflicts when compared against the boolean
* desiredValue.
*
* Timing budget is tight (user perceives anything past ~4s as a regression):
* one short settle, single read. If we can't confirm, fall back to
* optimistic confirm — periodic drift detection will surface any mismatch
* later. Previous 6-attempt loop added ~9s to every push. */
* Settle (2.5s) accounts for slow POST round-trips (Ford/uncommon keys
* observed at 1.2–3.5s). confirmKeys fires optimistically before this
* runs, so the settle window has no UX cost. */
private async verifyWrite(
deviceId: string,
keys: string[],
Expand Down Expand Up @@ -346,6 +345,10 @@ class BatchPushStore {
// means the device changed it independently → conflict.
// Equal to baseline → write pending, not a conflict.
const baselineVal = baselineAtPushTime[item.key];
if (!Object.prototype.hasOwnProperty.call(baselineAtPushTime, item.key)) {
allMatch = false;
continue;
}
if (!this.valuesEqual(deviceValue, baselineVal)) {
conflicts.push({ key: item.key, deviceValue });
}
Expand Down
13 changes: 13 additions & 0 deletions src/routes/dashboard/settings/+layout.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,19 @@
const resolvedKeys = Object.keys(freshValues).filter((k) => !driftedKeys.has(k));
if (resolvedKeys.length > 0) driftStore.resolveKeys(did, resolvedKeys);
}

{
const currentBaseline = driftStore.getBaseline(did);
const additions: Record<string, unknown> = {};
for (const [key, val] of Object.entries(freshValues)) {
if (!Object.prototype.hasOwnProperty.call(currentBaseline, key)) {
additions[key] = val;
}
}
if (Object.keys(additions).length > 0) {
driftStore.updateBaseline(did, { ...currentBaseline, ...additions });
}
}
} catch {
// Errors are non-fatal — flags still cleared in finally so the UI
// recovers from spinner-stuck state even on partial failure.
Expand Down
Loading