Skip to content

Kotlin: Push once

pushOnce() sends the head of the outbox in one request and applies the server's answer: an applied verdict clears the entry and advances the exactly-once watermark, a rejected verdict reverts the row to the server state and journals the reason. It never pulls, and it never drops a write.

Examples#

Basic#

// app/src/main/kotlin/com/example/todo/TodoScreen.kt (excerpt)
kizunasync.pushOnce()

Push, then read what the server refused#

// app/src/main/kotlin/com/example/todo/TodoScreen.kt (excerpt)
kizunasync.pushOnce()
val refused = kizunasync.rejections()

Parameters#

NameTypeRequiredDescription
(none)——This function takes no arguments. The slice is chosen from the outbox in insertion order.

Returns#

Unit. One call sends up to 500 queued entries, or the whole consecutive run of an atomic batch when the head belongs to one, so a group that must apply together is never split across two requests. An empty outbox returns without a request.

Errors#

CodeCondition
REMOTEA transport fault. The entries stay queued for the next attempt.
PERMANENT_TRANSPORTThe server refused the request definitively. pushOnce re-raises it as is: only Sync keeps the consecutive-failure budget that eventually dead-letters the head.
UNKNOWN_OPAn outbox row carries an operation outside insert, update, and delete.
MALFORMED_PUSH_RESPONSEThe response carried neither verdicts nor a batch outcome, answered a non-atomic request with a batch abort, or carried a batch outcome outside the closed union.
VERDICT_BIJECTIONThe verdicts did not correspond one to one with the mutations sent.
UNKNOWN_VERDICT_REASONA rejection reason outside COLUMN_DENIED, CONSTRAINT, DELETE_WINS, PRECONDITION, RLS_DENIED, and SUPERSEDED.
UNKNOWN_BATCH_OFFENDERA batch abort named a mutation that was not in the batch.
UNKNOWN_SIGNALThe response carried a lifecycle signal other than RESET_REQUIRED.
STORE, JSONThe local database or the response could not be read.
ENGINE_UNAVAILABLEThe client has no engine because Initializing has not run.

Notes#

Each refused write raises MUTATION_REJECTED and lands in the journal, which List rejections reads and Dismiss a rejection acknowledges. An atomic batch the server refused raises BATCH_ABORTED naming the offender, and every member of that batch is reverted, the offender to the authoritative row the server returned and the rest to their captured pre-images.

Row Level Security is enforced here rather than at write time: a mutation a policy refuses comes back as a RLS_DENIED verdict instead of an HTTP error, so one bad row does not fail the request. Supabase documents the policy side under Row Level Security; Push describes the request itself.

A soft-blocked client returns without a request, and a RESET_REQUIRED signal on the response latches that block while leaving the outbox untouched.

Found a problem? Edit this page on GitHub