release: ruststream 0.5#102
Draft
powersemmi wants to merge 8 commits into
Draft
Conversation
* feat: add Field/FieldMut compile-time selector traits The shared foundation for typed per-message context (#93) and typed application state (#94): zero-sized selector keys resolved by monomorphization to a direct field read, with no hashing, boxing, or downcasting. FieldMut adds the write side for middleware scratch values. * wip(#93): add BuildContext, drop IncomingMessage::extensions Foundation for the typed per-delivery context: BuildContext<M> builds a handler context value from the broker message (blanket impl for () = the zero-field default). IncomingMessage loses the erased extensions() type-map; brokers expose fields via BuildContext instead. Tree is red until the Context<'a, C> rewrite and dispatch/publish cascade land. * wip(#93): Context<'a, C> core - typed cx, context()/set() by key Context gains the per-delivery context type param C (default ()), holding a typed cx: C instead of the erased Extensions type-map. get()/insert() replaced by context(KEY)/set(KEY, v) via Field/FieldMut. publisher() no longer threads extensions. Callers (dispatch, typed, batch, publishing, memory, examples) and the After builder + tests still pending. * wip(#93): thread C through mount path, drop Extensions, green - HandlerExt<M,C>, scope.handle/push_handle thread the context type so hand-written typed-context handlers mount (macro handlers stay C=()). - Remove the now-unused Extensions type-map type entirely. - Rewrite context unit tests + the integration test for the typed context (broker field by key; middleware scratch via FieldMut; state isolation). - Fix doc links; example drops the dead extensions snippet. Lib + all tests + doctests + clippy(-D warnings) + fmt + doc(-D warnings) + --no-default-features all green. * docs(#93): typed per-delivery context in the Context guide Rewrite the per-delivery section of the Context guide and the lifespan note from the removed Extensions type-map to the typed per-delivery context (ctx.context(KEY) / ctx.set(KEY, v), Field / BuildContext). * feat(#93): thread C through scope mount path and the global blanket stack scope.subscribe/push_subscribe now carry the context type like scope.handle, and BlanketLayer::apply<M, C, H> threads it through the app-global stack (Identity/Stack/Tracing/Metrics + the example layers), so a hand-written typed-context handler mounts via b.handle/b.subscribe and is still wrapped by the global stack. The router-builder route path stays C=() (fast-follow). * feat(#93): macro and include typed-context support The #[subscriber] macro detects the context type from the handler's ctx: &mut Context<'_, C> parameter and threads it through SubscriberDef (new type Context) and the generated Handler impl. Typed (the decoder), mount_subscriber, push_subscribe_workers, and the include/include_on methods carry D::Context with a BuildContext bound, so a macro handler reads broker fields by key end-to-end. PublishingDef/batch forms and the router-builder include path stay C=() (documented sub-fast-follow). #93 complete: green across lib, tests (21 suites), doctests (50), clippy -D warnings, fmt, doc -D warnings, --no-default-features.
* feat: add Field/FieldMut compile-time selector traits The shared foundation for typed per-message context (#93) and typed application state (#94): zero-sized selector keys resolved by monomorphization to a direct field read, with no hashing, boxing, or downcasting. FieldMut adds the write side for middleware scratch values. * wip(#93): add BuildContext, drop IncomingMessage::extensions Foundation for the typed per-delivery context: BuildContext<M> builds a handler context value from the broker message (blanket impl for () = the zero-field default). IncomingMessage loses the erased extensions() type-map; brokers expose fields via BuildContext instead. Tree is red until the Context<'a, C> rewrite and dispatch/publish cascade land. * wip(#93): thread C through mount path, drop Extensions, green - HandlerExt<M,C>, scope.handle/push_handle thread the context type so hand-written typed-context handlers mount (macro handlers stay C=()). - Remove the now-unused Extensions type-map type entirely. - Rewrite context unit tests + the integration test for the typed context (broker field by key; middleware scratch via FieldMut; state isolation). - Fix doc links; example drops the dead extensions snippet. Lib + all tests + doctests + clippy(-D warnings) + fmt + doc(-D warnings) + --no-default-features all green. * feat(#94): typed application state Replace the `Any`-keyed `State` type-map with a single typed application state value threaded through the runtime at compile time. The state type `S` is produced by `on_startup` (the value the hook returns becomes the state and fixes the app's state type) and read with `ctx.state() -> &S`, with no lookup, `Option`, or downcast. - `Context<'a, C, S>`, `Handler<M, C, S>`, and the middleware stack (`BlanketLayer::apply<M, C, S, H>`, `Layer` handlers, `Typed`) thread `S` parallel to the per-delivery context `C`. - `RustStream<L, St>` is a producer-model builder: `on_startup` transitions `RustStream<L, St> -> RustStream<L, St2>`. `run`, the CLI runner, and `build_spec` are now `St`-generic. - A `#[subscriber]` handler that names the state as the third `Context` generic is bound to it; one that names none is generic over the state and mounts on any app. Mounting only succeeds when the declared state matches the app's, checked at compile time. - `PublishingDef` carries a `type State` so a publishing reply handler can read typed state too. Router registrations thread `St` through `RouterDef<B, St>`/`MountRoute`; metadata collection moves to a state-independent `RouterHandlers` trait. - Batch handlers keep a unit-state context (a documented follow-up). Examples, integration tests, and the Context/Lifespan guides are migrated to the typed-state API.
* feat: add Field/FieldMut compile-time selector traits The shared foundation for typed per-message context (#93) and typed application state (#94): zero-sized selector keys resolved by monomorphization to a direct field read, with no hashing, boxing, or downcasting. FieldMut adds the write side for middleware scratch values. * wip(#93): add BuildContext, drop IncomingMessage::extensions Foundation for the typed per-delivery context: BuildContext<M> builds a handler context value from the broker message (blanket impl for () = the zero-field default). IncomingMessage loses the erased extensions() type-map; brokers expose fields via BuildContext instead. Tree is red until the Context<'a, C> rewrite and dispatch/publish cascade land. * wip(#93): thread C through mount path, drop Extensions, green - HandlerExt<M,C>, scope.handle/push_handle thread the context type so hand-written typed-context handlers mount (macro handlers stay C=()). - Remove the now-unused Extensions type-map type entirely. - Rewrite context unit tests + the integration test for the typed context (broker field by key; middleware scratch via FieldMut; state isolation). - Fix doc links; example drops the dead extensions snippet. Lib + all tests + doctests + clippy(-D warnings) + fmt + doc(-D warnings) + --no-default-features all green. * feat: add Field/FieldMut compile-time selector traits The shared foundation for typed per-message context (#93) and typed application state (#94): zero-sized selector keys resolved by monomorphization to a direct field read, with no hashing, boxing, or downcasting. FieldMut adds the write side for middleware scratch values. * wip(#93): add BuildContext, drop IncomingMessage::extensions Foundation for the typed per-delivery context: BuildContext<M> builds a handler context value from the broker message (blanket impl for () = the zero-field default). IncomingMessage loses the erased extensions() type-map; brokers expose fields via BuildContext instead. Tree is red until the Context<'a, C> rewrite and dispatch/publish cascade land. * wip(#93): thread C through mount path, drop Extensions, green - HandlerExt<M,C>, scope.handle/push_handle thread the context type so hand-written typed-context handlers mount (macro handlers stay C=()). - Remove the now-unused Extensions type-map type entirely. - Rewrite context unit tests + the integration test for the typed context (broker field by key; middleware scratch via FieldMut; state isolation). - Fix doc links; example drops the dead extensions snippet. Lib + all tests + doctests + clippy(-D warnings) + fmt + doc(-D warnings) + --no-default-features all green. * feat(#95): publisher keys instead of string names Replace the string-keyed named-publisher registry with compile-time publisher keys. A key is a distinct zero-sized type, so a misspelled key is a compile error (an undeclared identifier) where a misspelled string name was only a runtime `None`, and the registry slot is the key type's `TypeId` rather than a hashed string on every publish. - New `PublisherKey` trait and `publisher_key!` declarative macro to declare keys; `Publishers` becomes `HashMap<TypeId, Arc<dyn ErasedPublisher>>`. - `RustStream::publisher(KEY, p)`, `BrokerScope::publisher(KEY)`, and `ctx.publisher(KEY)` take a key in place of a `&str`; the string forms are removed. The publishing example, the cross-broker bridge tests, and the Publishing guide are migrated to keys.
- `run`/`run_until` and the CLI runner gain `L: Send, St: Send + Sync` bounds, and `dispatch` gains `St: Send + Sync`, so the futures the runtime spawns are provably `Send` (clippy::future_not_send, denied via `-D warnings`). - Shorten the first doc paragraph of `RouterHandlers` and `RouterSink` (clippy::too_long_first_doc_paragraph). - Drop redundant `std::convert::` qualifications and a `Some(..).unwrap_or_default()` in the migrated tests. - Replace the inline `Field`/per-delivery-context fence in the Context guide with a compiled `examples/context_field.rs` snippet, per the repo's compiled-snippet rule.
bug_003 - extend typed application state to batch handlers, removing the per-message/batch asymmetry: - `SliceHandler<T, S>`, `BatchHandler<M, S>`, and `TypedBatch`/`decode_batch` thread the state `S`; `BatchDef::Handler` is relaxed like `SubscriberDef` so a stateless batch handler is generic over the state and a state-reading one is pinned to its declared type. - `BatchPublishingDef` gains a `type State` (mirroring `PublishingDef`); `spawn_batch_dispatch`/`run_batch` thread the real `Arc<St>` instead of discarding it, and the macro's `expand_batch`/`expand_batch_publishing` lift the state type out of the handler signature. - New `batch_handler_reads_typed_state` integration test. bug_004 - correct two `ReplyPublisher`/`Transactional` doc comments that still described the removed per-delivery `extensions` commit-token flow. bug_005 - the Context guide's methods table showed `publisher(name)`; it takes a compile-time `PublisherKey`, so it now reads `publisher(KEY)`. bug_008 - the lifespan/context guides claimed a stateless handler "mounts on any app"; clarify that a `publish(..)` handler instead pins its state to `()` when none is named.
Clone the recorded values out of the lock so the guard is not held across `run.await` (clippy::await_holding_lock / significant_drop_tightening on newer toolchains).
…gistry) (#104) * refactor: publishers live in typed state, drop the named-publisher registry With typed application state (#94), a shared publisher is just a typed field of the state struct, reached with `ctx.state()` - typed end to end, with no erased runtime lookup. That makes the separate named-publisher registry added in #95 redundant, so it is removed: - delete `PublisherKey`, the `publisher_key!` macro, `RustStream::publisher`, `BrokerScope::publisher`, `Context::publisher`, and `ScopedPublisher`; - drop the `Publishers` registry and the per-delivery publish pipeline from `Delivery` (only `ctx.publisher` fed them); `ErasedPublisher` stays for the `retry_after` fallback; - the reply path (`publish(..)`) and its app-wide `publish_layer` pipeline are unchanged. To publish from a handler now, put the publisher in the state struct and call its own API (`ctx.state().egress.publish(..)`). The publishing example, the cross-broker test (captures the publisher directly), and the Publishing / Context / Lifespan / Subscribers guides are migrated; the test that asserted `ctx.publisher` ran the pipeline is removed with the feature. * refactor: parameterize publishing defs over state, drop the pinned State assoc type A `publish(..)` handler used to carry `type State` on its def, which forced a stateless publishing handler to pin `State = ()` and so write `_ctx: &mut Context<'_, (), AppState>` just to mount on a stateful app - the asymmetry ultrareview flagged (bug_008). Plain subscribers never had this: a handler that ignores the state is generic over it. Split the metadata-only `PublishingDef`/`BatchPublishingDef` from a new `PublishingCall<S>`/`BatchPublishingCall<S>` that runs the body over state `S`. A handler that reads the state implements the call trait only for its declared `S` (mounts on a matching app); one that ignores it is generic over `S` (mounts on any app), mirroring `Handler<M, C, S>`. The macro now emits the def with metadata only plus a generic-or-concrete call impl, so a stateless publishing handler omits the `Context` parameter entirely. Migrate the examples (respond/validate/confirm/settle drop their unused `_ctx`) and the context guide's stale "publish handlers pin their state" note.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Release integration PR: merges the
v0.5integration branch intomainto cut ruststream 0.5. This is the umbrella PR for the 0.5 compile-time-context set; its diff fills in as the feature stack lands onv0.5.0.5 is a breaking release (minor bump pre-1.0):
Context<'_, C>, broker fields read by compile-timeFieldkey;IncomingMessagecontract change.Context<'_, C, S>/Handler<M, C, S>, producer-modelRustStream<L, St>builder withon_startup,ctx.state() -> &S.ctx.state()and used via its own API - no registry, no key lookup.publisher_key!/PublisherKey/ctx.publisher(KEY)were removed; the type-erased publisher survives only as the broker-agnosticretry_afterfallback, wired explicitly withscope.retry_via(..).PublishingDef/BatchPublishingDefcarry metadata only; the handler body runs throughPublishingCall<S>/BatchPublishingCall<S>. A statelesspublish(..)handler is generic over the state and omits theContextparameter, matching plain subscribers (no more pinnedtype State).[workspace.package].versionbumped to 0.5.0 (already onv0.5).Merge order (must land on
v0.5before this is ready)feat/93-typed-context->v0.5feat/94-typed-state-> retarget tov0.5, mergefeat/95-publisher-keys-> retarget tov0.5, mergerefactor/publishers-in-state->v0.5(drops the named-publisher registry)PublishingCall<S>) ->v0.5latest/0.4Type of change
raising the MSRV - a minor version bump pre-1.0)
Checklist
just checkpasses per feature PR)-D warnings)just test)# Examplesdoctest, and user-facing changes are reflected inexamples/where applicable