e5acc75f9efa
end the bundle with 'end 0' so a cut connection is caught; tests pinned to koh 3.4.1 (v3.0.212)
- time
- 2026-10-03 17:47 UTC · 1 week ago
- machine
- Junes-MacBook-Pro.local
- agent
- claude-opus-5-5
- session
- faster whole-repo steal
- parent
- 7653310330f2
↓ kepr-e5acc75f.tar.gzatlas at this save
files changed4 files
package.json+1 −1src/mirror/remote.ts+6 −1tests/koh-version.txt+1 −1tests/kohremote.test.ts+2 −0package.json+1 −1
@@ -1,6 +1,6 @@11 {22 "name": "kepr",3- "version": "3.0.211",3+ "version": "3.0.212",44 "private": true,55 "type": "module",66 "scripts": {src/mirror/remote.ts+6 −1
@@ -184,7 +184,10 @@184184 });185185 }186186 187-/** Each entry is `<key> <length>\n` and then that many bytes, keyed as the single routes are. */187+/**188+ * Each entry is `<key> <length>\n` and then that many bytes, keyed as the single routes are, and189+ * the last line is `end 0`.190+ */188191 function* bundle(mirror: Database): Generator<Uint8Array> {189192 const encoder = new TextEncoder();190193 function* entry(key: string, bytes: Uint8Array): Generator<Uint8Array> {@@ -202,6 +205,8 @@202205 WHERE EXISTS (SELECT 1 FROM save_files f WHERE f.hash = o.hash)`,203206 );204207 for (const row of objects.iterate()) yield* entry(`objects/${row.hash}`, row.data);208+ // A connection cut between two entries would otherwise pass for the whole repo.209+ yield encoder.encode("end 0\n");205210 }206211 207212 // Field names and their order are Koh's, and every optional is an empty string, as `json2.encode`tests/kohremote.test.ts+2 −0
@@ -149,6 +149,8 @@149149 ...(await listed("events")),150150 ...(await listed("objects")),151151 ];152+ expect(new TextDecoder().decode(body.subarray(body.length - 6))).toBe("end 0\n");153+ entries.delete("end");152154 expect([...entries.keys()].sort()).toEqual(keys.sort());153155 for (const key of keys) {154156 const single = new Uint8Array(await (await get(key)).arrayBuffer());