feat: add world voxel snapshot forwarding
Collect chunk voxel data from the bot world and stream snapshot, chunk, and unwatch messages through the forward protocol.
This commit is contained in:
@@ -97,6 +97,27 @@ function setup() {
|
||||
ensure(value = initial) { active = value; return manager.ensure(value); }};
|
||||
}
|
||||
|
||||
test('lifecycle updates use reliable bot_event even while volatile logs are saturated', async t => {
|
||||
const f = setup(); t.after(() => f.manager.stop());
|
||||
await f.ensure();
|
||||
const socket = f.sockets[0], stream = f.streams[0], received = [];
|
||||
socket.on('bot_event', event => received.push(event));
|
||||
socket.volatile = {emit() {}};
|
||||
const base = {bot_id: 2, context_generation: randomUUID(), stream_id: randomUUID(), emitted_at: Date.now()};
|
||||
for (let seq = 1; seq <= 160; seq++) stream.event({...base, seq, name: 'log', payload: {records: []}});
|
||||
for (const [index, status] of ['online', 'disconnecting', 'offline'].entries()) {
|
||||
stream.event({...base, seq: 161 + index, name: 'status_update', payload: {status, context_exists: true}});
|
||||
}
|
||||
assert.deepEqual(received.map(event => event.payload.status), ['online', 'disconnecting', 'offline']);
|
||||
assert.ok(received.every(event => event.forward_session_id === f.command.forward_session_id));
|
||||
stream.event({...base, seq: 165, name: 'message', payload: {text: 'not a lifecycle event'}});
|
||||
assert.equal(received.length, 3);
|
||||
socket.io.engine.writeBuffer.length = 64;
|
||||
stream.event({...base, seq: 166, name: 'status_update', payload: {status: 'offline', context_exists: true}});
|
||||
assert.equal(socket.connected, false);
|
||||
assert.equal(stream.listeners, 0);
|
||||
})
|
||||
|
||||
const tick = () => new Promise(resolve => setImmediate(resolve));
|
||||
const code = response => response.data.code;
|
||||
|
||||
@@ -299,7 +320,7 @@ test('lease expiry retires data channel and queue capacity stays bounded under s
|
||||
assert.equal(stalled.sockets.length, 1);
|
||||
});
|
||||
|
||||
test('bot events are never forwarded while connected, congested or disconnected', async t => {
|
||||
test('lifecycle events are forwarded while ready and congestion closes the stale transport', async t => {
|
||||
const app = setup();
|
||||
t.after(() => app.manager.stop());
|
||||
await app.ensure();
|
||||
@@ -308,23 +329,28 @@ test('bot events are never forwarded while connected, congested or disconnected'
|
||||
let resyncs = 0;
|
||||
stream.resync = () => { resyncs++; };
|
||||
const event = {name: 'status_update', seq: 1, payload: {status: 'offline', context_exists: false}};
|
||||
let lifecycle = 0;
|
||||
socket.on('bot_event', () => lifecycle++);
|
||||
stream.event(event);
|
||||
assert.equal(socket.sent.filter(([name]) => name === 'bot_event').length, 0);
|
||||
assert.equal(lifecycle, 1);
|
||||
assert.equal(socket.sent.filter(([name]) => name === 'bot_log').length, 0);
|
||||
stream.event({name: 'log', seq: 2, payload: {records: []}});
|
||||
assert.equal(socket.sent.filter(([name]) => name === 'bot_log').length, 1);
|
||||
socket.emit('relay_status', {forward_session_id: app.command.forward_session_id, node_ready: true, reason: 'resync_required'});
|
||||
assert.equal(resyncs, 1);
|
||||
socket.io.engine.writeBuffer.length = 64;
|
||||
stream.event({...event, seq: 2});
|
||||
stream.event({name: 'log', seq: 3, payload: {records: []}});
|
||||
assert.equal(socket.sent.filter(([name]) => name === 'bot_log').length, 1);
|
||||
assert.equal(socket.sent.filter(([name]) => name === 'bot_event').length, 0);
|
||||
assert.equal(lifecycle, 1);
|
||||
assert.equal(socket.connected, false);
|
||||
socket.emit('relay_status', {forward_session_id: app.command.forward_session_id, node_ready: true, reason: 'resync_required'});
|
||||
assert.equal(resyncs, 1);
|
||||
socket.disconnect();
|
||||
stream.event({...event, seq: 3});
|
||||
stream.event({name: 'log', seq: 4, payload: {records: []}});
|
||||
assert.equal(socket.sent.filter(([name]) => name === 'bot_log').length, 1);
|
||||
assert.equal(socket.sent.filter(([name]) => name === 'bot_event').length, 0);
|
||||
assert.equal(lifecycle, 1);
|
||||
assert.equal(stream.listeners, 0);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user