manifold
manifold copied to clipboard
manifold.deferred/timeout! does not unwrap the target deferred
Case in point:
(require '[manifold.deferred :as md])
(let [d (md/deferred)]
(-> d
(md/timeout! 1000 :timeout)
(md/chain println))
;; Succeeding d with a deferred that never succeeds.
(md/success! d (md/deferred)))
;; println never triggers
Is this an expected behavior? If not, would it be a breaking change to fix it?
Looks like this is expected https://github.com/ztellman/manifold/blob/master/docs/deferred.md#composing-with-deferreds
Note that if a timeout is placed on a deferred returned by chain, the timeout elapsing will prevent any further stages from being executed.
This ticket is about a different thing, it's about timeout!
not working for nested deferreds.
In the example, I use 3-arity timeout!
which doesn't short-circuit the chain:
(-> (md/deferred) (md/timeout! 1000 :timeout) (md/chain println))
;; Prints :timeout after a second.
@alexander-yakushev This doesn't have anything to do with timeout!
. If you remove the timeout!
call from the let
, it still exhibits the same behavior:
(let [d (md/deferred)]
(-> d
(md/chain println))
;; Succeeding d with a deferred that never succeeds.
(md/success! d (md/deferred)))
=> true
The reason is that chain
is designed to pause on unrealized inputs. From the docstring: "When composing, either x
or the returned values may be values which can be converted to a deferred, causing the composition to be paused." (Maybe not the clearest language there...)
Since you resolve d
with another deferred immediately, the timeout doesn't kick in, and d
's value is passed down to (md/chain println)
. But, since the value of d
was an unrealized deferred, the chain
pauses.