Connection lifecycle

Updated Nov 29, 2025

WireframeApp supports optional setup and teardown callbacks that run once per connection. Setup can return arbitrary state retained until teardown executes after the stream finishes processing.[^2] During handle_connection the framework caches middleware chains, enforces read timeouts, and records metrics for inbound frames, serialization failures, and handler errors before logging warnings.[^6][^7] PacketParts::inherit_correlation ensures response packets carry the correct correlation identifier even when middleware omits it.[^8]

Immediate responses are available through send_response and send_response_framed, both of which report serialization or I/O problems via SendError.[^6][^5]

use tokio::io::{self, AsyncReadExt, AsyncWriteExt};

use wireframe::{
    app::{SendError, WireframeApp},
    message::Message,
};

#[derive(bincode::Encode, bincode::BorrowDecode, Debug, PartialEq)]
struct Ready(&'static str);

#[tokio::main]
async fn main() -> Result<(), SendError> {
    let app = WireframeApp::default();
    let (mut client, mut server) = io::duplex(64);

    let ready = Ready("ready");
    app.send_response(&mut server, &ready).await?;
    server.shutdown().await?;

    let mut buffer = Vec::new();
    client.read_to_end(&mut buffer).await?;
    let (decoded, _) = Ready::from_bytes(&buffer).expect("decode Ready frame");
    assert_eq!(decoded, ready);

    Ok(())
}