Restore live autonomy with direct runtime and fresh snapshot capacity

This commit is contained in:
Codex
2026-09-22 15:07:24 -04:00
parent c5f84a7221
commit bc50395221
6 changed files with 103 additions and 16 deletions
+21 -5
View File
@@ -93,12 +93,20 @@ function rows(sql){
}
async function deliverEvents(){
// Reserve capacity for current snapshots so historical events cannot starve
// live decisions. The remaining slots continue draining history in order.
const fresh=rows(`SELECT id,HEX(kind),HEX(payload)
FROM acore_auth.azerothai_event_outbox
WHERE delivered_at IS NULL AND kind='player.snapshot'
AND created_at >= NOW() - INTERVAL 90 SECOND
ORDER BY id ASC LIMIT ${Math.max(1,Math.floor(EVENT_BATCH/2))}`);
const batch=rows(`SELECT id,HEX(kind),HEX(payload)
FROM acore_auth.azerothai_event_outbox
WHERE delivered_at IS NULL
ORDER BY CASE WHEN kind IN ('player.whisper','player.chat') THEN 0 ELSE 1 END, id
LIMIT ${EVENT_BATCH}`);
for(const [id,kindHex,payloadHex] of batch){
${fresh.length?`AND id NOT IN (${fresh.map(row=>Number(row[0])).join(',')})`:''}
ORDER BY CASE WHEN kind IN ('player.whisper','player.chat') AND created_at >= NOW() - INTERVAL 90 SECOND THEN 0 ELSE 1 END, id
LIMIT ${Math.max(1,EVENT_BATCH-fresh.length)}`);
for(const [id,kindHex,payloadHex] of [...fresh,...batch]){
const kind=Buffer.from(kindHex||'','hex').toString('utf8');
const payloadText=Buffer.from(payloadHex||'','hex').toString('utf8');
let payload;
@@ -116,7 +124,7 @@ async function deliverEvents(){
mysql(`UPDATE acore_auth.azerothai_event_outbox SET delivered_at=NOW(6) WHERE id=${Number(id)}`);
if(EVENT_GAP_MS)await sleep(EVENT_GAP_MS);
}
return batch.length;
return fresh.length+batch.length;
}
async function deliverResults(){
@@ -136,6 +144,14 @@ async function deliverResults(){
function cleanup(){
mysql(`
CREATE TABLE IF NOT EXISTS acore_auth.azerothai_snapshot_archive LIKE acore_auth.azerothai_event_outbox;
INSERT IGNORE INTO acore_auth.azerothai_snapshot_archive
SELECT * FROM acore_auth.azerothai_event_outbox
WHERE delivered_at IS NULL AND kind='player.snapshot'
AND created_at < NOW() - INTERVAL 90 SECOND;
UPDATE acore_auth.azerothai_event_outbox e
JOIN acore_auth.azerothai_snapshot_archive a ON a.id=e.id
SET e.delivered_at=NOW(6) WHERE e.delivered_at IS NULL;
UPDATE acore_auth.azerothai_event_outbox
SET delivered_at=NOW(6)
WHERE delivered_at IS NULL
@@ -151,10 +167,10 @@ console.log(`AzerothAI ALE DB relay started: ${BASE}, poll ${POLL_MS}ms`);
while(!stopping){
try{
if(Date.now()-lastCleanup>60_000){cleanup();lastCleanup=Date.now();}
await deliverEvents();
await deliverResults();
await pullCommand();
if(Date.now()-lastCleanup>60_000){cleanup();lastCleanup=Date.now();}
await sleep(POLL_MS);
}catch(error){
console.error(new Date().toISOString(),error instanceof Error?error.message:String(error));
+28
View File
@@ -0,0 +1,28 @@
// Run the built worker without Wrangler's development proxy or file watcher.
import './sites-env.mjs';
import {createRequire} from 'node:module';
import path from 'node:path';
import {readdirSync} from 'node:fs';
import {unstable_getMiniflareWorkerOptions} from 'wrangler';
const require = createRequire(import.meta.url);
const wranglerRequire = createRequire(require.resolve('wrangler'));
const {Miniflare} = wranglerRequire('miniflare');
const config = path.resolve('dist/server/wrangler.json');
const {workerOptions, externalWorkers, main} = unstable_getMiniflareWorkerOptions(config);
if (!main) throw new Error('Build the application before starting the local runtime');
const root = path.dirname(main);
const modules = readdirSync(root, {recursive: true})
.filter(file => /\.(m?js)$/.test(file))
.map(file => ({type: 'ESModule', path: path.join(root, file)}));
modules.sort((a, b) => a.path === main ? -1 : b.path === main ? 1 : 0);
const runtime = new Miniflare({
host: process.env.RUNTIME_HOST || (process.argv.includes('--lan') ? '0.0.0.0' : '127.0.0.1'),
port: Number(process.env.RUNTIME_PORT || 8787),
d1Persist: path.resolve('.wrangler/state/v3/d1'),
workers: [{...workerOptions, modules, modulesRoot: root}, ...externalWorkers],
});
console.log(`AzerothAI local runtime ready: ${await runtime.ready}`);
for (const signal of ['SIGINT', 'SIGTERM']) {
process.once(signal, async () => { await runtime.dispose(); process.exit(0); });
}
+2 -2
View File
@@ -1,6 +1,6 @@
import {spawnSync} from 'node:child_process';
import {writeFileSync,mkdirSync} from 'node:fs';
const result=spawnSync(process.execPath,['node_modules/typescript/bin/tsc','core/service.ts','core/seed.ts','core/ale.ts','core/conversation.ts','--types','@cloudflare/workers-types,node','--outDir','.test-build','--module','commonjs','--target','es2022','--moduleResolution','node','--esModuleInterop','--skipLibCheck','--strict'],{stdio:'inherit'});
const result=spawnSync(process.execPath,['node_modules/typescript/bin/tsc','core/service.ts','core/seed.ts','core/ale.ts','core/conversation.ts','core/autonomy.ts','--types','@cloudflare/workers-types,node','--outDir','.test-build','--module','commonjs','--target','es2022','--moduleResolution','node','--esModuleInterop','--skipLibCheck','--strict'],{stdio:'inherit'});
if(result.status)process.exit(result.status);
mkdirSync('.test-build',{recursive:true});writeFileSync('.test-build/package.json','{"type":"commonjs"}');
process.exit(spawnSync(process.execPath,['--test','tests/core.test.cjs','tests/hardcore.test.cjs','tests/living-world.test.cjs','tests/ale.test.cjs','tests/brains.test.cjs','tests/conversation.test.cjs'],{stdio:'inherit'}).status??1);
process.exit(spawnSync(process.execPath,['--test','tests/core.test.cjs','tests/hardcore.test.cjs','tests/living-world.test.cjs','tests/ale.test.cjs','tests/brains.test.cjs','tests/conversation.test.cjs','tests/autonomy.test.cjs'],{stdio:'inherit'}).status??1);