Offline: Fotos bei abgelaufener Testphase nicht mehr verwerfen
Upload-Antwort 422 trial_expired gilt als vorübergehend: Datei bleibt auf dem Gerät, wartende Op bleibt in der Warteschlange, der Sync-Durchlauf stoppt mit Backoff. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -43,7 +43,7 @@ const at = (ms: number) => new Date(T0.getTime() + ms);
|
||||
const fixedRandom = () => 1; // backoff = full step
|
||||
|
||||
/** Fake server: records every batch, answers per op via `decide`. */
|
||||
function fakeTransport(decide: (op: SyncOperationInput) => SyncOpResult, opts: { failBatches?: number; uploadError?: "network" | "invalid" } = {}) {
|
||||
function fakeTransport(decide: (op: SyncOperationInput) => SyncOpResult, opts: { failBatches?: number; uploadError?: "network" | "invalid" | "suspended" } = {}) {
|
||||
const batches: SyncOperationInput[][] = [];
|
||||
const uploads: string[] = [];
|
||||
const log: string[] = [];
|
||||
@@ -230,6 +230,17 @@ async function main() {
|
||||
const p = await runSyncPass({ store: store3, ctx: A, transport: offline.transport, deviceId: "d", now: () => at(10), random: fixedRandom });
|
||||
const blob3 = await store3.getBlob(c3);
|
||||
ok(p.stopped === "network" && blob3?.status === "failed" && blob3.nextAttemptAt === at(2010).toISOString() && offline.batches.length === 0, "Upload ohne Netz → Backoff, Op wartet");
|
||||
|
||||
// L15: expired trial (read-only tenant) must not discard photos
|
||||
const store5 = createMemoryStore();
|
||||
const c5 = randomUUID();
|
||||
const op5 = await enqueueOp(store5, A, { opType: "photo.attach", payload: { workOrderId: "wo-1", documentId: await enqueueBlob(store5, A, { clientId: c5, workOrderId: "wo-1", kind: "photo", blob: new Blob(["x"]), fileName: "f" }, at(0)) } }, randomUUID(), at(1));
|
||||
const suspended = fakeTransport((o) => applied(o), { uploadError: "suspended" });
|
||||
const p5 = await runSyncPass({ store: store5, ctx: A, transport: suspended.transport, deviceId: "d", now: () => at(10), random: fixedRandom });
|
||||
const blob5 = await store5.getBlob(c5);
|
||||
const op5After = (await store5.listOps(ctxKeyOf(A))).find((o) => o.clientOpId === op5.clientOpId);
|
||||
ok(p5.stopped === "suspended" && p5.rejected === 0 && suspended.batches.length === 0, "Testphase abgelaufen → Pass stoppt, nichts verworfen");
|
||||
ok(!!blob5 && blob5.nextAttemptAt !== null && blob5.lastError?.message === "trial_expired" && op5After?.status === "queued", "Foto bleibt auf dem Gerät, Op wartet (Backoff)");
|
||||
}
|
||||
|
||||
console.log("\n— idMap / verkettete baseVersion —");
|
||||
|
||||
Reference in New Issue
Block a user