Execute a previewed batch with a resumable ledger
zotExecute.RdRecalculates the plan's digest and requires it to match both the preview and its approval, refuses a ledger written for a different batch, and skips the entries an earlier run completed. Every row is recorded before and after its effect, so an interrupted batch leaves a ledger that names the row whose outcome is unknown.
Arguments
- config
A
zotConfig()object.- preview
The
zotPreview()being executed.- approval
Its
zotApprove()record.- ledgerPath
JSON ledger file; reuse the same path to resume.
Details
Patch operations read the current item version, use a conditional write,
and compare requested fields with a subsequent API read. Create operations
record the new key after it can be read. Trash operations use the status
returned by zotTrash(). The approval record is application metadata; this
function does not independently determine who authorized the batch.
The digest is recalculated from the plan being executed, so a preview whose
rows changed after approval is refused instead of written under the old
consent. Before each effect the row is written as "attempt" and the ledger
is replaced atomically; the result overwrites it immediately afterwards. A
resumed batch that meets an "attempt" stops with a zotLedgerError: that
row's effect is unknown, and only the caller can reconcile it against the
library before retrying.
See also
zotPreview(), zotApprove(), and zotVerify().
Examples
Store <- new.env(parent = emptyenv())
Store$version <- 1L
Store$title <- "Before"
Performer <- function(config, method, path, query, body, version) {
if (method == "GET") {
return(list(
status = 200L, headers = list(),
body = list(version = Store$version, data = list(title = Store$title))
))
}
Store$title <- body$title
Store$version <- Store$version + 1L
list(status = 204L, headers = list(), body = NULL)
}
Config <- structure(
list(userID = "42", key = "example", apiBase = "https://example.invalid",
performer = Performer),
class = "zotConfig"
)
Plan <- data.table::data.table(
action = "patch", library = "user", itemKey = "K1",
payload = list(list(title = "After"))
)
Preview <- zotPreview(Plan, describe = "Synthetic offline patch")
Approval <- zotApprove(Preview, notes = "Documentation example")
LedgerPath <- tempfile(fileext = ".json")
Ledger <- zotExecute(Config, Preview, Approval, ledgerPath = LedgerPath)
Ledger$items$K1$status
#> [1] "done"
unlink(LedgerPath)