Skip to content

shinyasync 0.2.0

Choose a tag to compare

@dawiegriesel dawiegriesel released this 15 Oct 07:10
· 48 commits to main since this release

shinyasync 0.2.0

  • New vignette, vignette("testing"), on testing async reactives with
    shiny::testServer(): a few lines pump the event loop and the mock session
    until a task settles, using only the mock session's public methods (#7).
  • print() on a reactiveAsync() or observeAsync() shows what dependency
    capture resolved: the calls evaluated on the session, the objects and
    packages shipped to the worker, and the rewritten worker expression, or the
    error that stops the expression being sent. Nothing is evaluated and the
    task is not started, so it is safe anywhere in a server function. In
    shiny::devmode() each async reactive prints itself on its first run, and
    each mirai_async() call site the first time it runs in a session;
    options(shinyasync.print = FALSE) turns that off (#5).
  • pool_async() is now optional. The first task that runs while no daemons
    are set starts a pool with the defaults, with a message, held by the
    session it runs in. Previously each task warned and ran in a fresh process.
  • New mirai_async() starts a mirai with the same dependency capture as
    reactiveAsync(): helper functions, the functions they call, objects and
    packages are shipped automatically, and reactive reads, req() and
    invalidateLater() are evaluated on the session thread. It returns the
    plain mirai, so a reactiveValAsync() can be fed without hand-shipping
    every helper (#4).
  • New has_value_async() is TRUE when reading an async reactive would
    return a value rather than halt or throw. With status_async() it tells a
    first run, which wants a spinner, from a refresh, which wants a "showing
    the previous result" note (#3).
  • A chained async reactive now waits for its upstream. Each reactiveAsync()
    run records the reactive reads it was computed from; a downstream that
    reads it keeps its previous value while the upstream is catching up with
    its own inputs, so it never combines a new input with an upstream value
    computed from the old one, and re-runs once the upstream has settled.
    Staleness follows a chain and upstream errors propagate down it, as in a
    chain of reactive() expressions. No guard is needed in the expression (#2).
  • A reactive in a module's returned list, read as mod$wind() or
    mod[["wind"]](), is now hoisted like wind(). Previously the list was
    shipped to the worker and the read failed there.
  • status_async() and has_value_async() calls inside an async expression
    are evaluated on the session thread, like reactive reads, when their
    argument is a name or a literal list field such as mod$r.
  • status_async() now starts a reactiveAsync() that has not run yet, the
    same way reading its value does. Previously a UI that read the value only
    once the status was "success" never started the task (#1).