Motivation
As a first-time user I avoided #[derive(SelfRouting)] for an event enum with payload-carrying variants, because the routing semantics were not obvious from the outside: Topic<E> for E with Hash + Eq bounds reads as whole-value comparison, which for RunRequested { config } would make every payload its own topic. Whether the derive actually routes by discriminant is not discoverable without reading the macro — so a cautious user routes around the feature entirely. That is an API-shape signal worth acting on.
There is also a maintenance argument for keeping explicit topics the encouraged default: subscriptions are runtime data. With a hand-written topic enum, the exhaustive match in from_event turns "added a variant" into a compile error at the single classification point. With event-as-topic subscriptions, a new variant silently reaches nobody until every subscription list is found and updated. Explicit topics turn routing drift into compile errors; self-routing turns it into silent delivery gaps — decisive for systems where an unheard event means stalled work.
Proposal
Present routing as a ladder, and enforce the first rung's boundary:
SelfRouting — for closed, fieldless signal protocols (the pingpong example is its perfect habitat). Make the derive reject payload-carrying variants at compile time, with an error message pointing to the next rung. This also dissolves the value-vs-discriminant ambiguity outright.
- (Optional middle rung) a derive that generates a parallel fieldless topic enum (one topic per variant) plus the
Topic impl — the common ceremony for free, while keeping topic and event as distinct types.
- Hand-written
Topic impl — real systems, where grouping variants into stable interfaces (e.g. one RunOutcome topic covering RunCompleted | RunFailed) is design work the API should encourage; also the natural attachment point for per-topic overflow_policy().
Docs suggestion: a short "choosing your routing" section ordering these three rungs.
Drafted by Claude (the jidoka-ai agent) from first-use experience; posted by the maintainer.
Motivation
As a first-time user I avoided
#[derive(SelfRouting)]for an event enum with payload-carrying variants, because the routing semantics were not obvious from the outside:Topic<E> for EwithHash + Eqbounds reads as whole-value comparison, which forRunRequested { config }would make every payload its own topic. Whether the derive actually routes by discriminant is not discoverable without reading the macro — so a cautious user routes around the feature entirely. That is an API-shape signal worth acting on.There is also a maintenance argument for keeping explicit topics the encouraged default: subscriptions are runtime data. With a hand-written topic enum, the exhaustive
matchinfrom_eventturns "added a variant" into a compile error at the single classification point. With event-as-topic subscriptions, a new variant silently reaches nobody until every subscription list is found and updated. Explicit topics turn routing drift into compile errors; self-routing turns it into silent delivery gaps — decisive for systems where an unheard event means stalled work.Proposal
Present routing as a ladder, and enforce the first rung's boundary:
SelfRouting— for closed, fieldless signal protocols (the pingpong example is its perfect habitat). Make the derive reject payload-carrying variants at compile time, with an error message pointing to the next rung. This also dissolves the value-vs-discriminant ambiguity outright.Topicimpl — the common ceremony for free, while keeping topic and event as distinct types.Topicimpl — real systems, where grouping variants into stable interfaces (e.g. oneRunOutcometopic coveringRunCompleted | RunFailed) is design work the API should encourage; also the natural attachment point for per-topicoverflow_policy().Docs suggestion: a short "choosing your routing" section ordering these three rungs.
Drafted by Claude (the jidoka-ai agent) from first-use experience; posted by the maintainer.