Take until the shutdown marker, inclusive
Requirement
Tonight's event feed contains a SHUTDOWN marker;
everything after it belongs to the next run and must not appear in
the report. Keep every event up to and including the marker
and print each as an event: line. The feed is in the
code; both versions must print the lines shown under
Expected output.
Expected output
event: boot event: listen :8080 event: GET /orders event: GET /health event: SIGTERM event: drain connections event: SHUTDOWN
Side by side
RxDart
FxDart
Why they differ
Plain takeWhile has an off-by-one problem for this job:
the element that breaks the predicate is exactly the one you still
want. Both libraries ship the inclusive fix, spelled from opposite
ends — RxDart's takeWhileInclusive keeps going
while not the marker, FxDart's takeUntilInclusive
(FxTS's takeUntil, renamed for Dart clarity) stops
at the marker. Same cut, inverted predicate.
The models even agree on what happens next. After emitting the marker, RxDart cancels the upstream subscription, so the two straggler events are never delivered; FxDart simply stops pulling, so they are never produced. As in the budget search of Part 1, cancellation and demand are the two models' words for the same economy — nothing downstream can tell which model was underneath. A tie, and a handy translation pair to know when moving code between the two.
Benchmark
N = 100
Time Tie
Peak memory Tie
N = 1,000,000
Time FxDart wins
Peak memory RxDart wins
Bars are medians of repeated timed iterations in fresh processes per side (small N is batched for timer resolution). Sides within 5% of each other — or within 0.6 ms, a difference no person can perceive — count as a tie; close relative races are re-measured up to 5 runs. In an app, anything under a few milliseconds is invisible to the user regardless of which bar is shorter. Memory is peak process RSS. The Dart VM and the dataset are identical on both sides, so the difference between the two bars is what the pipeline itself holds onto.