Skip to content

feature: BackgroundTask.progressStream (Rx push) + ADR#589

Merged
xerial merged 2 commits into
mainfrom
feature/background-task-progress-stream
Jun 20, 2026
Merged

feature: BackgroundTask.progressStream (Rx push) + ADR#589
xerial merged 2 commits into
mainfrom
feature/background-task-progress-stream

Conversation

@xerial

@xerial xerial commented Jun 20, 2026

Copy link
Copy Markdown
Member

Follow-up to #588 (BackgroundTask, issue #552).

What

  1. progressStream: Rx[P] on BackgroundTask — a push stream of progress updates that completes when the task finishes, for reactive consumers (a live CLI progress bar / UI) that want to react rather than poll. The poll snapshot (progress) stays.
  2. ADR adr/2026-06-20-background-task.md capturing feature: Add BackgroundTask — cross-platform cancellable, progress-pollable worker (#552) #588's non-obvious decisions, linked from CLAUDE.md.

Design notes (two real footguns avoided)

  • Backed by an RxVar[Option[P]] used only as the notification channel; progress stays on the AtomicReference because RxVar.get reads a non-@volatile var outside any lock — not safe for cross-thread polling. reportProgress updates both.
  • Uses flatMap (not filter) to skip the initial replayed None: a false filter predicate emits OnCompletion downstream (RxRunner FilterOp), which would prematurely end the stream. flatMap { Some(p) => Rx.single(p); None => Rx.empty } skips the None instead. RxVar holds only the latest value, so an unconsumed stream doesn't accumulate (no buffering leak, unlike Rx.queue).
  • JS: the body runs inline during start(), so a later subscriber sees only the final value (not a live feed) — documented; use the poll snapshot on JS.

Testing

progressStream pushes reported progress and completes (JVM + Native; not cross-platform since JS has nothing live to observe). Full suites: JVM 1651 / JS 1401 / Native 1413.

Plan: plans/2026-06-20-background-task-progress-stream.md.

🤖 Generated with Claude Code

Follow-up to #588.

- progressStream: Rx[P] on BackgroundTask — a push stream of progress updates
  that completes when the task finishes, for reactive consumers (live progress
  bars). Backed by an RxVar[Option[P]] used only as the notification channel; the
  poll snapshot stays on the AtomicReference (RxVar.get isn't cross-thread
  visibility-safe). Uses flatMap (not filter) to skip the initial replayed None —
  a false filter predicate emits OnCompletion downstream, which would prematurely
  end the stream; RxVar holds only the latest value, so an unconsumed stream
  doesn't accumulate.
- JS: the body runs inline, so a later subscriber sees only the final value (not
  a live feed) — documented; use the poll snapshot on JS.
- ADR adr/2026-06-20-background-task.md capturing the #588 design + the non-obvious
  decisions (Node worker_threads can't host a Scala closure -> JS inline,
  cooperative cancel + onCancel hook, catch-Throwable + finally-signal so await
  never hangs, hook draining on completion, the filter-vs-flatMap footgun).
  Linked from CLAUDE.md.

Test: progressStream pushes reported progress and completes (JVM + Native).
JVM 1651 / JS 1401 / Native 1413 pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@xerial

xerial commented Jun 20, 2026

Copy link
Copy Markdown
Member Author

/gemini review

@github-actions github-actions Bot added the feature New feature label Jun 20, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a push-based progressStream: Rx[P] to BackgroundTask alongside its existing poll-based snapshot, allowing reactive consumers to observe progress updates. It also adds an Architecture Decision Record (ADR) detailing the cross-platform design choices of BackgroundTask and includes concurrency tests for the new stream on JVM and Native platforms. The feedback suggests wrapping progressVar.stop() in a try-catch block to guarantee that any exception thrown during stream completion does not prevent the completion gate from being signalled, which would otherwise cause await() to hang indefinitely.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread uni/src/main/scala/wvlet/uni/control/BackgroundTask.scala Outdated

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a push-based Rx[P] progress stream (progressStream) to the cross-platform BackgroundTask utility, allowing reactive consumers to observe progress updates. The implementation uses RxVar as a notification channel while retaining AtomicReference as the thread-safe source of truth for polling. It also adds an Architecture Decision Record (ADR) detailing the design and cross-platform constraints of BackgroundTask, along with corresponding concurrency tests for JVM and Native platforms. No review comments were provided, so there is no additional feedback.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

A progressStream subscriber throwing during stream completion could propagate out
of progressVar.stop() and skip gate.signal(), hanging await() forever. Complete
the stream inside a try whose finally signals the gate.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@xerial xerial merged commit 2028934 into main Jun 20, 2026
21 of 22 checks passed
@xerial xerial deleted the feature/background-task-progress-stream branch June 20, 2026 03:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature New feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant