TransactionPlan

A sequence of operations to run as one transaction, assembled before any of it runs.

A plan is for the case a transaction { } block does not cover: the sequence itself is data. Where one layer decides what has to happen - a screen with a variable number of rows on it, a service turning a request into operations - and another runs it, the block form would mean passing a lambda that closes over everything it touched. A plan is a value; it can be built up, counted, inspected and handed on.

Steps run in the order they were added, and a step may use what an earlier one produced through the StepHandle that add returned:

val plan = TransactionPlan()

val edictId = plan.add(
db.insertInto("edicts").values(edict).returning("id")
.asStep().fetchFieldStrict<Int>(edict)
)

for (item in levy) {
plan.add(
db.insertInto("edict_items").values(listOf("edict_id", "province_id", "amount"))
.asStep().update(
"edict_id" to edictId.value(),
"province_id" to item.provinceId,
"amount" to item.amount
)
)
}

val results = db.executeTransactionPlan(plan)

Where the sequence is fixed and written out in one place, a transaction { } block says the same thing in fewer moving parts and with the values in plain Kotlin locals. Reach for a plan when the sequence is not known where it is executed.

Executing a plan does not consume it: the steps are copied out and the results kept in a map of the run's own, with nothing written back. The same plan runs again unchanged, which is what makes retrying a serialization failure or a deadlock a loop around executeTransactionPlan rather than a rebuild - and each run resolves its handles against its own results, so the second run reads what the second run produced.

Constructors

Link copied to clipboard
constructor()

Types

Link copied to clipboard
internal class PlannedStep(val handle: StepHandle<*>, val query: RunnableQuery<*>, val params: Map<String, Any?>, val run: (Map<String, Any?>) -> Any?)

A step and the handle it was filed under, which is all the executor needs of either.

Properties

Link copied to clipboard
val size: Int

How many steps the plan holds.

Functions

Link copied to clipboard
fun <T> add(step: TransactionStep<T>): StepHandle<T>

Appends a step, and returns the handle later steps use to refer to what it will produce.

Link copied to clipboard

Appends every step of other, in its order, after the steps already here.

Link copied to clipboard

The whole of what this plan will do, as text: every step's index, its SQL, and where each of its parameters comes from.

Link copied to clipboard

Whether the plan holds no steps at all.

Link copied to clipboard
Link copied to clipboard
open override fun toString(): String