Add .rx.awaiting to report whether an expression is still resolving - #1176
Open
philippjfr wants to merge 1 commit into
Open
Add .rx.awaiting to report whether an expression is still resolving#1176philippjfr wants to merge 1 commit into
.rx.awaiting to report whether an expression is still resolving#1176philippjfr wants to merge 1 commit into
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1176 +/- ##
==========================================
+ Coverage 86.90% 86.97% +0.07%
==========================================
Files 9 9
Lines 5398 5444 +46
==========================================
+ Hits 4691 4735 +44
- Misses 707 709 +2 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
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.
Problem
Since #1173 an
rxnode whose asynchronous operation is in flight reportsparam.Undefinedrather than the value it computed from inputs that have since been superseded. That fixed the
stale value, but it left no way to ask a reactive expression whether anything feeding it is
still in flight.
API
reactive_ops.awaitingis a read-only property on the.rxnamespace:It is a plain
bool, not a reactive expression, which makes it the only member of thenamespace that is not composable (apart from
.rx.value).Changes
reactive_ops.awaitingwalks the graph and asks each node whether it is settling:rx._upstream()yields the node and everything it derives its value from. Inputs reach a nodeby three routes and all of them have to be followed, because an operation is only as settled
as the nodes feeding it:
_prevchain of the pipeline the node belongs to,_sharedinput it was cloned from when a pipeline branches,rxpassed as an argument to one of its operations, which_iter_rxfinds by descending the same containersresolve_valuedoes (list, tuple, set,dict keys and values, slice components).
The walk is iterative with an
id()-keyed seen-set, because reusing an input clones it andlinks the clones through
_shared, so the graph is a DAG rather than a chain and a naive walkwould revisit nodes.
rx._settlingisself._awaiting or self._awaiting_ref, i.e. either of the two resolutionmechanisms.
rx._awaiting_refchecks the node's internal parameters againstParameters._awaiting_reffrom #1175, covering the case where the asynchronous callable isheld on a parameter rather than applied as an operation. Both are private;
_awaitingkeepsits existing meaning and
awaitingis the only public addition.Design notes
Reading it does not schedule anything.
awaitingdeliberately does not touch_objorotherwise resolve the node, so an expression whose value has never been requested reports
Falserather thanTrue. "Nothing has been asked for yet" is not the same as "a result ispending", and a property that started work as a side effect of being read would be a trap in
a loading indicator.
Generators settle per emission. A generator or async generator ref settles on each value
it yields rather than on exhaustion, so
awaitingisTrueonly until the next valuearrives. A spinner driven by it stops between emissions instead of spinning until the stream
ends, which is the useful reading for a streaming source.
_skippedwas not usable for this. It conflates "the async result is not in yet" with"an operation raised
Skip", which are precisely the two statesawaitingexists to tellapart.
Docs
Adds a
.rx.awaitingsection to theReactive_Expressions.ipynbuser guide, contrasting itwith
.rx.updating():updating()tracks a synchronous computation, while an asynchronousoperation outlives the update that scheduled it. The list of special methods on
.rxclosesby saying each entry returns a reactive expression, so
awaitingis mentioned after it withthe difference called out rather than being added to the list.
The example uses a single top-level
awaitin one cell so a docs build is deterministicrather than depending on when the notebook's kernel gets around to a background task.
AI Disclosure
Written with the assistance of Claude Opus 5.