Skip to content

Short targets, event dropping, EventSink (0.10.0) - #9

Merged
rinekri merged 6 commits into
masterfrom
feature/stale-events-short-targets
Oct 4, 2026
Merged

rinekri merged 6 commits into
masterfrom
feature/stale-events-short-targets

Conversation

@rinekri

@rinekri rinekri commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Short target builders (details(id)) keep alive ancestors' payloads; full builders (packageDetails(detailsId, id)) remain for cold start / initial / jumps into non-alive branches.
  • Events that can't be applied are dropped instead of crashing: DropReason.MissingPayload and DropReason.StaleSource. onEventDropped always fires; strictEventDropping throws EventDroppedException for MissingPayload only.
  • EventSink: source path + generation checked at dequeue; LocalEventSink in way-compose. A sink resolves like sendEvent scoped to its node: a screen starts at itself, a flow/parallel at the active leaves under it, then bubbles through the node and enclosing parallels; Back stays in the node's region. Root sink ≡ sendEvent, so UI always uses LocalEventSink.
  • Drops are all-or-nothing and fire no onPreTransition/onPostTransition (except the hand-rolled-schema builder backstop).
  • HistoryTarget restores parameterized nodes with their recorded payloads.
  • Re-targeting an alive node with a different argument rebuilds it (new generation, old sinks stale); equal argument is a no-op.
  • Imported schema reachable from several parents: one target per path (<node>Via<Parent>), new Schema.targets(). Rejected at build time: shared schema with children, parallel parent, parents in different parallel regions.
  • Codegen: keyword parameter names escaped; nullable imported-schema roots not treated as parameterized.
  • Compose: sink keyed on service + generation; state reset per service; NavigationState equality includes generations.
  • Version 0.10.0, CHANGELOG and README updated.

Test plan

  • ./gradlew spotlessCheck build :way:allTests :way-compose:testDebugUnitTest --rerun-tasks green: way 278, way-gradle-plugin 98, way-compose 9 (new, Robolectric), sample-compose 4.

🤖 Generated with Claude Code

….10.0

- Generate short target builders (own param only) alongside full ones
- Drop events with missing payloads or stale sources instead of crashing
- Add strictEventDropping and ServiceExtensionPoint.onEventDropped
- Add EventSink with per-path generations; LocalEventSink in way-compose
…t schemas

- Strict mode throws only for MissingPayload; StaleSource is an expected race
- Assign generations before onEntry so sinks obtained there are live
- Pass plain events to the enqueued-event scheduler, keep sink source on resend
- Resolve missing payloads before onPreTransition; drops fire no pre/post hooks
- Restore parameterized nodes from history with their recorded payloads
- Rebuild an alive node re-targeted with a different argument
- Generate one target per parent path for multi-parent imported schemas
  (Schema.targets), with per-path node building and finish routing
- Codegen: escape keyword parameter names, skip nullable imported roots
- Compose: key sink on service and generation, reset state per service,
  include generations in NavigationState equality
- Add way-compose Robolectric tests and many runtime/codegen corner-case tests
A node's EventSink now resolves events the way sendEvent does, scoped to
that node: a screen's sink starts at the screen, a flow's or parallel's
sink starts at the active leaves under it, then bubbles up through the
node and every enclosing parallel. The root sink is equivalent to
sendEvent, so UI can always use LocalEventSink. Back stays in the node's
region. resolveSourcedTransition is merged into resolveTransition.

Sample app screens use LocalEventSink instead of an injected FlowEventSink.
NavigationService implements EventSink: sendEvent is removed, service.send(event)
is the root sink (whole tree, never stale); the queue/dispatch is private.
BaseScreenNode and BaseFlowNode get a public eventSink, attached by the service
right before every onEntry and never cleared, so a send after exit is dropped as
StaleSource. LocalEventSink falls back to LocalNavigationService outside any node.
Migrate call sites, tests and docs.
@rinekri
rinekri merged commit c6031d4 into master Oct 4, 2026
1 check passed
@rinekri
rinekri deleted the feature/stale-events-short-targets branch November 9, 2026 15:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant