Skip to contents

Inside board_server() every state change flows through one board_update reactive. Core registers two observers framing the change: an initial one that validates the payload and runs augment_board_update() for auto-fixups, and a final one that runs apply_board_update() and resets the reactive. Plugins or callbacks may register their own observers in between, provided they use a finite priority — the highest and lowest reactive priorities are reserved for core.

Usage

validate_board_update(payload, board, ..., session = get_session())

augment_board_update(upd, board, ..., session = get_session())

apply_board_update(board, upd, ..., session = get_session())

Arguments

payload, upd

A board update payload — see Validation above for the accepted shape.

board

A board object.

...

Forwarded between methods. For apply_board_update(), the final observer also splices board_server()'s ... in here.

session

A shiny session, default get_session().

Value

validate_board_update() returns invisible(payload) (or throws a blockr_abort() error). augment_board_update() returns the (possibly extended) payload. apply_board_update() returns a board.

Details

All three functions dispatch on the board class. Subclasses override to validate, augment, or react to their own payload slots, typically composing with NextMethod(). validate_board_update() is also a caller-facing entry point: it mirrors the initial observer's checks against a caller-supplied payload, useful for staging layers (e.g. accumulating LLM-proposed updates) that need to fail loudly before publishing.

Validation

The default .board method runs a structural check on the payload (block / link / stack per-slot rules) and a cross-reference check that link endpoints and stack members resolve in the post-update merged view. Unknown top-level keys are passed through, so subclass payload slots reach subclass augment / apply methods.

Augment

The default .board method inserts implied link removals and stack updates that follow from block removals, plus link-input completion. Subclass methods may extend the payload with their own fixups; an error thrown here aborts the update before apply runs.

Apply

The default .board method applies the core delta to the supplied board and returns it: added blocks are appended, link and stack deltas are folded in through modify_board_links() / modify_board_stacks(), and removed blocks are dropped last (once the earlier steps have freed them of every link and stack). Subclass methods compose with NextMethod() to layer their own payload slots on top of the core-updated board (blockr.dock, for instance, cascades view membership), so a single apply_board_update() call yields the full board for any subclass. The board handed in is a plain board snapshot with no reactive surface; the returned board is what the final observer assigns back to rv$board. The reactive side effects that mirror the delta — block UI insertion / removal, server construction / teardown, link and stack wiring — run around this single reduce.

Errors thrown from either augment or apply are caught by the observer, reported via notify(), and the reactive is reset so the app keeps running.

Outcome

Alongside the human-facing notify() toast, every update cycle records a machine-readable result into board$last_update (the read-only board handed to plugins and callbacks). It is a list with a monotonically increasing seq, a logical ok, the phase it ended in ("validate" or "apply"), and a message (conditionMessage() on failure, NA on success); it is NULL before the first update. The seq advances on every write so that two consecutive identical outcomes still invalidate a downstream observer. A programmatic caller can watch this field to learn whether a dispatched update was rejected, failed to apply, or landed.

See also

On a locked board (see is_board_locked()) the update is dropped rather than applied.

Examples

brd <- new_board(
  blocks = c(a = new_dataset_block("iris"), b = new_subset_block()),
  links = links(ab = new_link(from = "a", to = "b"))
)

validate_board_update(
  list(links = list(rm = "ab")),
  brd
)

try(
  validate_board_update(
    list(links = list(add = links(xy = new_link(from = "x", to = "y")))),
    brd
  )
)
#> Error in blockr_abort("Expecting all links to refer to known block IDs.",  : 
#>   Expecting all links to refer to known block IDs.