Axum host (id_effect_axum)
Workspace crate id_effect_axum runs Effect<A, E, R> programs inside Axum handlers on the same Tokio runtime as #[tokio::main] / axum::serve.
Mental model
- Axum stays
async fnat the wire edge; your domain stays inEffectwith environmentR(oftenClonestate or anid_effect::Context). - The bridge takes
State(or&mut Rfrom custom extractors), builds an effect from&mut R, then drives it to completion withid_effect_tokio::run_asyncusingtokio::task::block_in_place+Handle::block_onso theEffectvalue never crosses aSendasync boundary incorrectly.
Runtime requirements
Workspace effects are intentionally not Send in the general case. Axum handlers must return Send futures; the id_effect_axum adapter satisfies that contract by running the interpreter on the multi-thread runtime’s blocking integration path. Use a multi-thread Tokio runtime (default for #[tokio::main]). On current_thread, prefer driving effects outside this adapter or supply a dedicated integration.
Tests: #[tokio::test] defaults to current-thread and can panic with this bridge—use e.g. #[tokio::test(flavor = "multi_thread", worker_threads = 2)] for router tests (see crate tests for the pattern).
API surface
routing::get/post/ … — ergonomic wrappers when the handler isFn(&mut R) -> Effect<…>.run_with_env— you already have&mut RorState(mut R); build and run one effect.execute— Axum handler:State+IntoResponsefor success and failure.json::decode_json_schema— validate JSON bodies withSchema::decode_unknownand map errors to HTTP responses (e.g. 422 with paths).
Further reading
cargo doc --open -p id_effect_axum- Examples:
cargo run -p id_effect_axum --example 010_routing_hello - Tokio bridge for interpreter semantics; Tower for generic
Servicecomposition without Axum.