{
"$schema": "https://context7.com/schema/context7.json",
"url": "https://context7.com/powersemmi/ruststream",
"public_key": "pk_uUlur6QCUlrZ8v1BsB2Wn",
"folders": [
"docs",
"src",
"crates/ruststream-macros",
".agents/skills",
"website/static"
],
"excludeFolders": [
"website/i18n"
],
"rules": [
"Import `ruststream::prelude::*` in a service, or the broker crate's own prelude, which re-exports it; the broker and the codec stay explicit choices.",
"Declare a handler as an `async fn` under `#[subscriber(..)]` whose first parameter is `&T` for one message or `&[T]` for a batch; mount it with `b.include(handler)` inside `with_broker`, and a batch handler with `.batch(n)`.",
"A reply type derives `Outgoing`: `#[outgoing(name = \"..\")]` fixes its destination and the subscriber writes the bare `reply`; a type with no name takes `reply(\"dest\")` at the mount site (a declared name wins, and startup warns).",
"Publish from inside a handler through an `Out(out): Out<impl Publisher>` parameter bound at the mount site with `.out(marker, policy).build()`; a handler signature never names a broker's publisher type.",
"The codec is chosen at the mount site (`with_broker_codec`, `Router::with_codec`, `.out_reply(policy).codec(..)`), never per message type; a type that is its own encoding derives `Serialized` or `Deserialized` and needs no codec.",
"A value a broker's delivery already holds (a row a driver read) reaches a handler as `&T`, or `&[T]` for a batch, once the broker crate's derive puts `T` on that lane; the type derives `Clone`, not `Deserialize`.",
"A batch of carried values mounts with no reply and no `Out` slots, and a test asserts carried values with `with_value` and `received_values`, not `with`.",
"Cap redeliveries at the mount site with `.max_attempts(n)` and `.dead_letter(name)` right after `include`; `.out_retry(policy)` only replaces the publisher the retry copy leaves through.",
"Test a service by handing its production app to `ruststream::testing::TestApp::start` and address a broker by its production type, `tb.broker::<KafkaBroker>()`; do not mock the broker traits or build a second app for tests.",
"A broker crate's `testing` feature runs each broker in process under `TestApp::start`; `TestApp::start_live` runs the same test body against a running stand.",
"Generate `main` with `#[ruststream::app]` and run the service with `cargo run -- run`; use `start()` only when the service runs beside another server such as an HTTP framework.",
"Give a handler that computes its own threads with `threads(n)` (or `threads(n, by_key)`) instead of `spawn_blocking` or `rayon` inside it; keep `workers(n)` for I/O-bound concurrency.",
"A `threads(n)` handler's leftovers (spawned tasks, `and_after`, `after(..)`, `retry_after` timers) stay on its thread; it sends work to the app's runtime only through `spawn` or `run` on `Ctx<MainRuntime>`.",
"Size the app's runtime for I/O with `#[ruststream::app(flavor = \"current_thread\")]` or `worker_threads = n` when the computing handlers run on `threads(n)`.",
"To find the handlers that belong on `threads(n)`, turn on the `poll-diagnostics` feature: every subscription samples its handler's time in `poll` and warns past the threshold.",
"Tune poll diagnostics with `RustStream::poll_diagnostics(PollDiagnostics::new().threshold(..).sample_every(..))` before `with_broker`; export them with `Metrics::observe_poll_diagnostics` or `Otel::observe_poll_diagnostics`.",
"Broker-specific settings live on the broker crate's subscription descriptor and publish policy, in that crate's vocabulary; the core exposes none.",
"A broker crate's own mount step reads the subscription's concurrency, batch size and name off the settings builder (`dispatch()`, `batch_size()`, `subscription_name()`) instead of a setting of its own that repeats `workers(n)`, `threads(n)` or `batch(n)`.",
"Use `ruststream-sqlx` for a transactional outbox over any RustStream broker and for task queues in the service's own Postgres, MySQL/MariaDB or SQLite tables; its docs.rs overview at https://docs.rs/ruststream-sqlx is the guide.",
"A transform that names a destination per delivery reads the address with `HeaderMap::get_shared` and passes the `Str` to `Outgoing::set_name`, so the name shares the delivery's buffer instead of being copied out of it.",
"Misuse is rejected at compile time by design: read the compiler error, it names the missing derive, the unbound slot or the wrong position; do not work around it with runtime checks.",
"Check what a change costs per message with `just bench --baseline=main`: it counts instructions and allocations per delivery on the core's own scenarios, and its numbers are the ones a pull request cites.",
"`just bench --baseline=main` fails on more than two percent more instructions, or on an allocation above a scenario's declared floor.",
"Open a pull request as a draft and leave it a draft until the maintainer marks it ready for review: CI runs nothing on a draft, so its time is spent once, on the work the maintainer wants checked."
]
}