Skip to content

Skip the empty input messages Shiny sends after deferred inputs - #73

Open
christophsax wants to merge 2 commits into
mainfrom
fix/shiny-empty-input-sends
Open

christophsax wants to merge 2 commits into
mainfrom
fix/shiny-empty-input-sends

Conversation

@christophsax

Copy link
Copy Markdown
Contributor

Works around rstudio/shiny#4436.

Shiny's input batcher checks whether a send is already queued but never records that one is, so every deferred setInput() queues its own send. The first carries all pending inputs and the rest go out as {}. The server runs a full input cycle for each empty message: manageHiddenOutputs() over every output of the session, then a flush.

A dock board hits this hard. Mounting a block card sets about a dozen inputs, so a first visit to a 15-block view sent 267 messages, 174 of them empty, and the dock's initialized report waited 2 to 4 s behind them before anything on the view evaluated. With this dependency on the page the same visit sends 48 messages. Measured on a demo board with about 90 blocks; details are in the commit message.

shiny_input_batch_dep() wraps Shiny.shinyapp.sendInput to return early on an empty object. Nothing is lost, since the inputs such a send would carry already went out with the first one. Once Shiny fixes the batcher, no empty send reaches the wrapper and the dependency can go.

Attaching it is a one-line change in blockr.dock's page (blockr_app_ui.dock_board()), which follows once this is merged. The other dock speed fixes are in BristolMyersSquibb/blockr.dock#503.

Adds V8 to Suggests for the test, which runs the script against a stub of Shiny.shinyapp.

Shiny 1.14.0's InputBatchSender checks sendIsEnqueued but never sets it,
so every deferred setInput queues its own send. The first carries all
pending inputs, the rest send an empty update, and the server runs a
full input cycle for each (manageHiddenOutputs over every output, then a
flush). On a first visit to a 15-block dock view that was 177 of 218
messages, and the dock's initialized report waited 2 to 4 s behind them.

shiny_input_batch_dep() wraps Shiny.shinyapp.sendInput to return early
on an empty object. The inputs such a send would carry already went out
with the first one.
@codecov

codecov Bot commented Oct 1, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

Files with missing lines Coverage Δ
R/theme.R 100.00% <100.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

The helper's skip_if_not_installed() runs outside test_that(), where lintr
does not see testthat, so it is called as testthat::. The coverage test
learns that shiny-input-batch.js is tested in R.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant