fix(core): preserve data integrity and bound shared UI and response work
Module Package Release / publish-packages (push) Successful in 13s
Module Package Release / publish-packages (push) Successful in 13s
Release v0.1.46. Coordinated integrity review: GovOPlaN/govoplan-core#298.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { importModuleWithRetry } from "../src/platform/moduleLoading";
|
||||
import { createModuleRefresh } from "../src/platform/moduleRefresh";
|
||||
|
||||
function assert(condition: unknown, message: string): asserts condition {
|
||||
if (!condition) throw new Error(message);
|
||||
@@ -34,3 +35,48 @@ async function verifyModuleImportRetry() {
|
||||
}
|
||||
|
||||
void verifyModuleImportRetry().catch((error) => { throw error; });
|
||||
|
||||
async function verifyModuleRefresh() {
|
||||
const requests: Array<{ resolve: (value: number) => void; reject: (error: unknown) => void }> = [];
|
||||
const accepted: number[] = [];
|
||||
const errors: unknown[] = [];
|
||||
let time = 0;
|
||||
const refresh = createModuleRefresh({
|
||||
load: () => new Promise<number>((resolve, reject) => requests.push({ resolve, reject })),
|
||||
accept: (value) => accepted.push(value), reject: (error) => errors.push(error), now: () => time
|
||||
});
|
||||
const settle = async () => { await Promise.resolve(); await Promise.resolve(); };
|
||||
refresh.invalidate();
|
||||
refresh.invalidate();
|
||||
refresh.invalidate();
|
||||
assert(requests.length === 1, "mutation bursts cannot start overlapping requests");
|
||||
requests[0].resolve(0);
|
||||
await settle();
|
||||
assert(accepted.length === 0 && Number(requests.length) === 2, "obsolete success is ignored and invalidation gets one trailing read");
|
||||
refresh.invalidate();
|
||||
requests[1].reject(new Error("obsolete"));
|
||||
await settle();
|
||||
assert(errors.length === 0 && Number(requests.length) === 3, "obsolete error cannot clear the current catalogue or drop invalidation");
|
||||
requests[2].resolve(2);
|
||||
await settle();
|
||||
assert(accepted.join() === "2", "only the current generation publishes");
|
||||
refresh.refreshVisible(true);
|
||||
time = 6_000;
|
||||
refresh.refreshVisible(false);
|
||||
assert(Number(requests.length) === 3, "focus throttle and hidden-document checks remain");
|
||||
refresh.refreshVisible(true);
|
||||
assert(Number(requests.length) === 4, "visible focus refresh remains available after the throttle");
|
||||
requests[3].reject("current failure");
|
||||
await settle();
|
||||
assert(errors.join() === "current failure", "current errors retain fail-closed handling without automatic retries");
|
||||
refresh.invalidate();
|
||||
refresh.invalidate();
|
||||
refresh.dispose();
|
||||
requests[4].resolve(4);
|
||||
await settle();
|
||||
refresh.invalidate();
|
||||
assert(Number(requests.length) === 5 && accepted.join() === "2", "authority change/unmount discards both old response and queued work");
|
||||
console.log("Module refresh coalescing and generation tests passed.");
|
||||
}
|
||||
|
||||
void verifyModuleRefresh().catch((error) => { throw error; });
|
||||
|
||||
Reference in New Issue
Block a user