jaeb 0.3.9

simple snapshot-driven event bus
Documentation
# AGENTS.md

Guidance for autonomous coding agents working in this repository.
Rust-specific guidelines are in `RUST_RULES.md`.

## Mission

- Maintain and evolve `jaeb`, an in-process snapshot-driven event bus for Tokio.
- Preserve correctness for dispatch, retry/dead-letter behavior, and shutdown guarantees.
- Keep public APIs and docs coherent across workspace crates.

## Workspace Overview

- Root crate: `jaeb` (library, benchmarks, integration tests)
- Plugin crate: `summer-jaeb` (summer-rs integration)
- Proc-macro crate: `summer-jaeb-macros` (`#[event_listener]`)
- Examples:
    - `examples/jaeb-demo`
    - `examples/summer-jaeb-demo`

Key paths:

- `src/lib.rs` - public re-exports and module surface
- `src/bus.rs` - `EventBus` API and builder
- `src/registry.rs` - snapshot registry, dispatch lanes, async task tracking, failure notifications
- `src/handler.rs` - async/sync handler traits + type erasure (`IntoHandler`)
- `src/types.rs` - `Event`, `FailurePolicy`, `DeadLetter`, internal `BusConfig`
- `src/subscription.rs` - unsubscribe handle
- `src/error.rs` - bus/handler error types
- `tests/*.rs` - API-level behavior contracts
- `summer-jaeb/src/lib.rs` - plugin registration pipeline
- `summer-jaeb-macros/src/lib.rs` - macro expansion and compile-time validation

## Build, Test, and Validation Commands

Run from repository root unless noted.

- Format: `cargo fmt --all`
- Lints: `cargo clippy --all-targets --all-features -- -D warnings`
- Root tests: `cargo test`
- Metrics feature tests: `cargo test --features metrics`
- Full workspace tests: `cargo test --workspace`
- Docs: `cargo doc --no-deps --all-features`
- Benchmarks (optional): `cargo bench`

Notes:

- CI enforces warnings as errors (`RUSTFLAGS=-Dwarnings`).
- CI also runs fmt, clippy, docs, security audit, and tests on Linux/macOS/Windows and stable/nightly.

## Architectural Model (Do Not Break)

### Core event bus model

- `EventBus` is a cloneable handle over shared runtime state (`Arc<Inner>`).
- Listener and middleware routing data is exposed as immutable snapshots (`ArcSwap<RegistrySnapshot>`).
- `publish` dispatches directly against the current snapshot and waits for sync listeners.
- `try_publish` is non-blocking and returns `EventBusError::ChannelFull` when immediate dispatch capacity is unavailable.

### Listener dispatch semantics

- Dispatch mode is inferred from trait implementation:
    - `EventHandler<E>` -> async dispatch
    - `SyncEventHandler<E>` -> sync dispatch
- Sync listeners run in a per-event-type serialized lane (FIFO for sync path).
- Async listeners are spawned in a separate lane; `publish` may return before they finish.
- Async handlers require `E: Clone` because events are cloned per invocation.

### Failure handling and dead letters

- Each listener has a `FailurePolicy`:
    - `max_retries`
    - optional `retry_strategy`
    - `dead_letter` toggle
- Retries happen per listener invocation.
- Dead letters are emitted after terminal failure when enabled.
- Dead-letter recursion is explicitly guarded (a `DeadLetter` failure must not produce another dead letter).
- `subscribe_dead_letters` always forces `dead_letter = false` for that listener.
- A lightweight control loop handles failure notifications and dead-letter publication.

### Shutdown semantics

- `shutdown` marks the bus stopped, closes publish permits, then drains in-flight async tasks.
- If `shutdown_timeout` is configured, remaining async tasks are aborted at deadline.
- After shutdown, all operations should return `EventBusError::Stopped`.

## summer-jaeb Plugin Contracts

- Reads config under `[jaeb]` (see `summer-jaeb/src/config.rs`).
- Builds `EventBus` through `EventBus::builder()` and registers it as a summer component.
- Discovers listeners through `inventory` and calls registrar `register()` during plugin build.
- Listener auto-registration is expected to work without manual wiring.

## `#[event_listener]` Macro Contracts

The macro in `summer-jaeb-macros` must keep these guarantees:

- Target must be a free function (not a method).
- First parameter must be `&EventType`.
- Return type must be explicit (`-> HandlerResult`).
- Additional parameters must use `Component(name): Component<Type>` syntax.
- Async functions map to `EventHandler`; sync functions map to `SyncEventHandler`.
- Dead-letter listeners (`DeadLetter`) must be sync.
- Failure policy attrs are rejected for dead-letter listeners.
- Generated code must use absolute paths (`::jaeb`, `::summer`, `::summer_jaeb`) to avoid import fragility.

## Style and Conventions

- Rust edition: 2024.
- Unsafe code is forbidden (`#![forbid(unsafe_code)]` in root crate).
- Use `tracing` for operational signals; preserve existing event/span names where possible.
- Follow existing test style:
    - integration tests in `tests/`
    - explicit `expect("...")` messages
    - deterministic assertions for async behavior (timeouts/notifications when needed)
- Keep `rustfmt.toml` constraints in mind (`max_width = 150`).

## Change Guidance by Area

### If editing dispatch/runtime logic

- Re-run at least: `dispatch`, `retry`, `dead_letter`, `shutdown`, `panic_safety` tests.
- Verify behavior for both sync and async handlers.
- Verify dead-letter behavior during normal operation and shutdown-drain path.

### If editing public API (`bus.rs`, `types.rs`, `handler.rs`)

- Update docs/examples in code comments and `README.md`.
- Preserve re-exports in `src/lib.rs` unless intentionally changing API surface.
- Add or adjust integration tests for any behavior change.

### If editing macro/plugin crates

- Run workspace tests (`cargo test --workspace`).
- Validate compile-time diagnostics remain clear and specific.
- Ensure state injection and inventory registration still work in `summer-jaeb-demo`.

## Known Nuances

- `cargo test` at workspace root primarily exercises the root package; use `--workspace` (or `-p`) when touching sub-crates.

## Pre-PR Checklist for Agents

- Code compiles and is formatted.
- Reviewer subagent was invoked and issues are addressed.
- Clippy passes with `-D warnings`.
- Relevant tests pass (feature/workspace scope based on change).
- Public docs updated when semantics or API changed.
- `CHANGELOG.md` updated when introducing user-visible behavior changes.
- Increase patch version in `Cargo.toml` after a code change.