feat(simulation): serve atlas layer requests over the bridge — completes #969 (D-225)

Closes the server-side layer-stream loop. serve_atlas_requests (PreInput) drains
the AtlasRequestBuffer and runs each through handle_atlas_request (cache hit ->
Ready; miss -> resolve via BodySourceResolver + enqueue an Immediate AnalyzeBody
-> Pending), buffering AtlasLayerResponses. send_atlas_responses (PostSnapshot)
flushes them to the client. main.rs wires BodySourceResolverResource (base root
= systems.db's 3rd ancestor; mod roots layer on later). Misses flow through the
#968 background tier and a re-request hits the now-warm cache.

Full path now live server-side: client request -> receive() demux -> serve ->
proxy -> (cache | queue+cascade) -> response -> client. The client half (send
request, decode response, render overlays) is #960.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-24 18:06:33 +02:00
co-authored by Claude Opus 4.7
parent dfdc578429
commit 1bece0b201
3 changed files with 111 additions and 1 deletions
+21
View File
@@ -265,6 +265,25 @@ impl Default for ServerRunning {
#[derive(Resource, Default)]
pub struct AtlasRequestBuffer(pub Vec<AtlasLayerRequest>);
/// Outbound atlas layer responses, filled by the proxy serve system and flushed
/// to the client in `PostSnapshot` (#969, D-225).
#[derive(Resource, Default)]
pub struct AtlasResponseBuffer(pub Vec<AtlasLayerResponse>);
/// Flush buffered atlas responses to the client (#969, D-225). A failed send is
/// logged but not fatal — an atlas response is not load-bearing like a snapshot.
pub fn send_atlas_responses(
bridge: Option<Res<BridgeResource>>,
mut buffer: ResMut<AtlasResponseBuffer>,
) {
let Some(bridge) = bridge else { return };
for resp in buffer.0.drain(..) {
if let Err(e) = bridge.send_atlas_response(&resp) {
tracing::warn!("failed to send atlas response for {}: {}", resp.body_id, e);
}
}
}
/// Bridge plugin for client-server communication
/// Abstracts transport layer (LocalBridge/NetworkBridge)
pub struct BridgePlugin;
@@ -281,9 +300,11 @@ impl Plugin for BridgePlugin {
.init_resource::<DebugEnabled>()
.init_resource::<crate::perception::query::ActivePerceptionMode>()
.init_resource::<AtlasRequestBuffer>()
.init_resource::<AtlasResponseBuffer>()
// Bridge I/O — PreInput (receive) and PostSnapshot (send)
.add_systems(Update, receive_bridge_inputs.in_set(TickPhase::PreInput))
.add_systems(Update, send_bridge_snapshot.in_set(TickPhase::PostSnapshot))
.add_systems(Update, send_atlas_responses.in_set(TickPhase::PostSnapshot))
// Debug commands — Snapshot phase
.add_systems(
Update,