This demo runs a stateless thumbnail application inside one Hydro Process,
with an Axum HTTP server connected through sidecar_bidi:
HTTP request → sidecar → Hydro map(render) → sidecar → HTTP response
Each instance is independent. A hosting platform can route requests between instances and scale their number; there is no Hydro cluster or shared application state. The example includes a local launcher, not platform deployment packaging.
From this directory:
cargo run --example thumbnail_local -- 127.0.0.1:8080The address is optional and defaults to 127.0.0.1:8080. Wait for HTTP listening;
Hydro compiles and launches the service process. Ctrl-C stops the deployment.
curl --fail-with-body --data-binary @photo.jpg \
-H 'Content-Type: application/octet-stream' \
'http://127.0.0.1:8080/thumbnail?width=320&height=240' \
--output thumbnail.pngPOST /thumbnail accepts PNG/JPEG bytes and returns a PNG that fits the requested
box, preserves aspect ratio, and never upscales. EXIF orientation is not applied.
GET /health returns ok.
Basic limits keep the demo manageable:
- Width and height: 1–2048 (
400for invalid dimensions). - Request body: up to 8 MiB (
413above that). - Decoding: up to 8192 pixels per axis and a 128 MiB decoder allocation budget
(
422for invalid, unsupported, or oversized images). - Each sidecar channel holds up to 64 queued items. A full request queue returns
503; this is a queue limit, not a total in-flight request limit. - Waiting for a reply times out after 30 seconds (
504). Closed processing channels return503.
Image processing runs synchronously on Hydro's single runtime thread, so HTTP handling and timeout polling pause during rendering. Timeouts are cooperative; client cancellation does not stop work already submitted. This is a demonstration of stateless application execution, not a production HTTP runtime or benchmark.
src/http.rs is independent of the thumbnail application. It provides
Bridge<Input, Output> for Axum handlers and serve to attach a router to a
Hydro process. Applications supply routes, validation, and response formatting.
- Call
http::serve(&process, address, config, q!(|bridge| { /* router */ })). The router factory executes in the deployed process and uses the bridge as Axum state. - In a handler, call
bridge.call(input).awaitand format the output. Bridge errors implementIntoResponse(503or504). - Transform each request with
message.map(process)and complete the response stream. The thumbnail example uses:
responses.complete(
requests
.map(q!(|message| message.map(self::render)))
.weaken_ordering::<NoOrder>(),
);Each Message<Input, Output> carries its own one-shot reply channel. Mapping it
produces Message<Output, Output> while preserving that channel, so results go
back to the right caller without request IDs or a shared response registry.
Messages move through a local dataflow; they cannot be cloned or serialized.
Payloads only need Send + 'static.
Config sets channel capacity and reply timeout. For an application-managed
server, connect returns the bridge and raw sidecar channels; start also binds
and starts an Axum server. See src/thumbnail.rs for the complete integration.
cargo test --lib
# With the service running:
python3 scripts/smoke_thumbnail.py
# Or specify its address:
python3 scripts/smoke_thumbnail.py http://127.0.0.1:9090The tests cover image processing, reply routing, and basic bridge errors. The smoke test exercises the generated Hydro process through HTTP, including concurrent requests.