Throws PatchConflictError after maxAttempts consecutive conflicts.
Throws PatchConflictError with reason: 'deleted_during_retry' if
the row is deleted between the initial read and the write (opt into
resurrection via allowResurrection: true).
Requires the store to implement both getWithVersion and putIfMatch.
Mutation caveat: always build a fresh object in update — never mutate
the current argument in place. In-memory stores hand out a shallow copy
(nested references shared across retries) while Postgres deserializes JSONB
fresh each time; the safe pattern ({ ...current, field: newValue }) works
on both.
Error propagation: if update throws, the exception propagates
immediately and no retry happens.
Backoff: default is jittered exponential (low single-digit ms). Override
with options.backoffMs. Return 0 to disable.
Size: each retry re-reads the full document. Avoid on rows close to
maxDocumentBytes — split into per-entity rows instead.
Read-compute-write loop that retries on version conflict, using
getWithVersionputIfMatchunder the hood. The right primitive for counter-like updates where two handlers might read the same pre-state and otherwise lose one write.updatereceives the current document (ornullif the row doesn't exist) and returns the next document. Returningnullaborts without writing.Throws PatchConflictError after
maxAttemptsconsecutive conflicts. Throws PatchConflictError withreason: 'deleted_during_retry'if the row is deleted between the initial read and the write (opt into resurrection viaallowResurrection: true).Requires the store to implement both
getWithVersionandputIfMatch.Mutation caveat: always build a fresh object in
update— never mutate thecurrentargument in place. In-memory stores hand out a shallow copy (nested references shared across retries) while Postgres deserializes JSONB fresh each time; the safe pattern ({ ...current, field: newValue }) works on both.Error propagation: if
updatethrows, the exception propagates immediately and no retry happens.Backoff: default is jittered exponential (low single-digit ms). Override with
options.backoffMs. Return0to disable.Size: each retry re-reads the full document. Avoid on rows close to
maxDocumentBytes— split into per-entity rows instead.