Separate looted currency and preserve growing realm state in atomic chunks
Core tests / core (push) Successful in 49s

This commit is contained in:
Codex
2026-09-24 03:16:52 +12:00
parent e7b9df9e08
commit 8e01cdee22
13 changed files with 54 additions and 17 deletions
+15 -6
View File
@@ -1,4 +1,5 @@
import { env } from 'cloudflare:workers';
import { splitState } from './state-chunks';
import { seed } from './seed';
import type { State,StateStore,Bot,Recipe,Home } from './types';
@@ -68,13 +69,21 @@ export class D1Store implements StateStore {
if(!env.DB) throw new Error('Realm database unavailable');
const initial=seed();
await env.DB.prepare('INSERT OR IGNORE INTO realm_state (id,revision,payload) VALUES (?,?,?)').bind('realm',0,JSON.stringify(initial)).run();
const row=await env.DB.prepare('SELECT payload FROM realm_state WHERE id=?').bind('realm').first<{payload:string}>();
if(!row)throw new Error('Realm state unavailable');
return migrate(JSON.parse(row.payload));
await this.chunks();
const result=await env.DB.prepare("SELECT s.payload AS manifest,c.payload AS chunk FROM realm_state s LEFT JOIN realm_state_chunks c ON c.token=json_extract(s.payload,'$.chunkToken') WHERE s.id=? ORDER BY c.part").bind('realm').all<{manifest:string;chunk:string|null}>();
const rows=result.results;if(!rows.length)throw new Error('Realm state unavailable');
const manifest=JSON.parse(rows[0].manifest);
if(manifest.chunkToken){if(rows.length!==manifest.parts||rows.some(r=>r.chunk===null))throw new Error('Realm state chunks incomplete');return migrate(JSON.parse(rows.map(r=>r.chunk).join('')));}
return migrate(manifest);
}
private async chunks(){await env.DB!.prepare('CREATE TABLE IF NOT EXISTS realm_state_chunks (token TEXT,part INTEGER,payload TEXT,PRIMARY KEY(token,part))').run();}
async save(s:State,expected:number){
s.revision=expected+1;
const result=await env.DB!.prepare('UPDATE realm_state SET revision=?,payload=? WHERE id=? AND revision=?').bind(s.revision,JSON.stringify(s),'realm',expected).run();
if(result.meta.changes!==1)throw new Error('State changed in another request. Refresh and try again.');
await this.chunks();s.revision=expected+1;
const token=crypto.randomUUID(),parts=splitState(s),manifest=JSON.stringify({chunkToken:token,parts:parts.length});
const statements=[env.DB!.prepare('UPDATE realm_state SET revision=?,payload=? WHERE id=? AND revision=?').bind(s.revision,manifest,'realm',expected),
...parts.map((part,i)=>env.DB!.prepare('INSERT INTO realm_state_chunks(token,part,payload) SELECT ?,?,? WHERE EXISTS (SELECT 1 FROM realm_state WHERE id=? AND payload=?)').bind(token,i,part,'realm',manifest)),
env.DB!.prepare('DELETE FROM realm_state_chunks WHERE token<>? AND EXISTS (SELECT 1 FROM realm_state WHERE id=? AND payload=?)').bind(token,'realm',manifest)];
const result=await env.DB!.batch(statements);
if(result[0].meta.changes!==1)throw new Error('State changed in another request. Refresh and try again.');
}
}