fix: resume interrupted translations without losing saved progress

This commit is contained in:
mrleo1nid committed 2026-10-27 04:41:17 +03:00
1 parent a8902deaf7
commit e14184435c
6 files changed
+321 -44

No files matched your search

+32 -2
View File
@@ -160,7 +160,7 @@ test("a run that was interrupted picks up the page the translator finished meanw
test("a job the translator no longer knows is skipped and its lines come back with the list", async () => {
const server = fakeServer(["a", "b", "c"]);
const translator = { ...fakeTranslator(), async job() { throw new Error("404"); } };
const translator = { ...fakeTranslator(), async job() { throw Object.assign(new Error("404"), { status: 404 }); } };
// `job` is also used while waiting, but the resumed job fails at once, so nothing waits
const created = [];
const client = { ...translator, async createJob(...args) { const j = await fakeTranslator().createJob(...args); created.push(j); return j; } };
@@ -172,7 +172,37 @@ test("a job the translator no longer knows is skipped and its lines come back wi
test("checkpoints say which page is out and when it is handled", async () => {
const marks = [];
await run(fakeTranslator(), fakeServer(["a", "b", "c"]), { pageSize: 2, onCheckpoint: (c) => marks.push([c.jobId ? "sent" : "done", c.keys.length, c.skip]) });
assert.deepEqual(marks, [["sent", 2, 0], ["done", 0, 0], ["sent", 1, 0], ["done", 0, 0]]);
assert.deepEqual(marks, [["sent", 2, 0], ["sent", 2, 0], ["done", 0, 0], ["sent", 1, 0], ["sent", 1, 0], ["done", 0, 0]]);
});
test("a failed save keeps its results available for resuming instead of silently skipping them", async () => {
const translator = fakeTranslator();
let checkpoint;
const server = fakeServer(["a", "b"]);
await assert.rejects(run(translator, server, {
save: async () => { throw new Error("save offline"); },
onCheckpoint: (cp) => { checkpoint = cp; },
}), /save offline/);
assert.equal(checkpoint.jobId, "j0");
assert.equal(checkpoint.done, 0);
await run(translator, server, { initial: checkpoint, resume: checkpoint });
assert.deepEqual(server.saved, { k0: "RU a", k1: "RU b" });
assert.equal(translator.created.length, 1);
});
test("resuming a partially saved job does not overwrite its committed rows or count them twice", async () => {
const translator = fakeTranslator();
const server = fakeServer(["a", "b"]);
const job = await translator.createJob("p", [{ id: "0", text: "a" }, { id: "1", text: "b" }]);
server.saved.k0 = "Human edit";
const seen = [];
await run(translator, server, {
initial: { total: 2, done: 1, failed: 0, skip: 0 },
resume: { jobId: job.id, keys: ["k0", "k1"], savedKeys: ["k0"] },
onProgress: (p) => seen.push(p),
});
assert.deepEqual(server.saved, { k0: "Human edit", k1: "RU b" });
assert.equal(seen.at(-1).done, 2);
});
test("a slow page is saved line by line while it is still running", async () => {