Transaction batching primitives for write coalescing.
Accumulates transaction data in an atom, then flushes as a single operation on scope exit. Designed for KG/Datahike workloads where N individual transact! calls create lock contention.
Usage: (with-batch [batch (tx-batch conn)] (batch-add! batch {:kg-edge/from "a" :kg-edge/to "b"}) (batch-add! batch {:kg-edge/from "c" :kg-edge/to "d"})) ;; Single transact! on scope exit with all accumulated tx-data
Transaction batching primitives for write coalescing.
Accumulates transaction data in an atom, then flushes as a single
operation on scope exit. Designed for KG/Datahike workloads where
N individual transact! calls create lock contention.
Usage:
(with-batch [batch (tx-batch conn)]
(batch-add! batch {:kg-edge/from "a" :kg-edge/to "b"})
(batch-add! batch {:kg-edge/from "c" :kg-edge/to "d"}))
;; Single transact! on scope exit with all accumulated tx-data(batch-add! batch tx-datum)Add transaction data to a batch. Accepts a single tx-datum (map or vector) or a collection of tx-data.
Examples: (batch-add! batch {:kg-edge/from "a" :kg-edge/to "b"}) (batch-add! batch [:db/add eid :attr val]) (batch-add! batch [{:entity/id 1} {:entity/id 2}])
Add transaction data to a batch. Accepts a single tx-datum (map or vector)
or a collection of tx-data.
Examples:
(batch-add! batch {:kg-edge/from "a" :kg-edge/to "b"})
(batch-add! batch [:db/add eid :attr val])
(batch-add! batch [{:entity/id 1} {:entity/id 2}])(batch-count batch)Return the number of accumulated tx-data items in the batch.
Return the number of accumulated tx-data items in the batch.
(batch-flush! batch)Flush accumulated tx-data as a single transaction.
Returns: (r/ok result) on success (r/err :batch/empty) if no data accumulated (r/err :batch/flush-failed {...}) on exception
Flush accumulated tx-data as a single transaction.
Returns:
(r/ok result) on success
(r/err :batch/empty) if no data accumulated
(r/err :batch/flush-failed {...}) on exception(normalize-tx-datum tx-datum)Normalize tx-datum into flat vector of individual datoms. Maps -> [map], [:db/add ...] -> [[:db/add ...]], colls -> (vec coll). Pure function — no side effects.
Normalize tx-datum into flat vector of individual datoms. Maps -> [map], [:db/add ...] -> [[:db/add ...]], colls -> (vec coll). Pure function — no side effects.
(transparent-batch-scope batch-var flush-fn)Create a reusable transparent-batch scope function bound to a dynamic var.
Arguments: batch-var - the Var of a dynamic binding (e.g. #'tx-batch) flush-fn - (fn [accumulated-data]) called once with all batched data
Returns a function (fn [thunk]) that:
Transparent: existing code that checks @batch-var will accumulate data instead of writing immediately, with zero code changes. Nestable: inner scopes delegate to the outermost scope.
Usage: ;; Define once (at namespace level): (def with-tx-batch-fn (transparent-batch-scope #'tx-batch (fn [data] (proto/transact! store data))))
;; Call from anywhere (including cross-namespace resolution): (with-tx-batch-fn (fn [] (transact! a) (transact! b) (transact! c))) ;; => single flush with [a b c]
Create a reusable transparent-batch scope function bound to a dynamic var.
Arguments:
batch-var - the Var of a dynamic binding (e.g. #'*tx-batch*)
flush-fn - (fn [accumulated-data]) called once with all batched data
Returns a function (fn [thunk]) that:
1. If batch-var is already bound (nested scope), just calls thunk —
data accumulates into the outer scope
2. Otherwise, binds batch-var to a fresh atom, runs thunk, flushes
Transparent: existing code that checks @batch-var will accumulate
data instead of writing immediately, with zero code changes.
Nestable: inner scopes delegate to the outermost scope.
Usage:
;; Define once (at namespace level):
(def with-tx-batch-fn
(transparent-batch-scope #'*tx-batch*
(fn [data] (proto/transact! store data))))
;; Call from anywhere (including cross-namespace resolution):
(with-tx-batch-fn (fn [] (transact! a) (transact! b) (transact! c)))
;; => single flush with [a b c](tx-batch conn flush-fn)Create a new transaction batch tied to a connection.
Returns a batch map: {:conn conn ;; connection/store for flushing :tx-data (atom []) ;; accumulated transaction data :flush-fn flush-fn} ;; function (fn [conn tx-data]) to execute
flush-fn receives the connection and the accumulated tx-data vector. It should perform the actual transact! call.
Create a new transaction batch tied to a connection.
Returns a batch map:
{:conn conn ;; connection/store for flushing
:tx-data (atom []) ;; accumulated transaction data
:flush-fn flush-fn} ;; function (fn [conn tx-data]) to execute
flush-fn receives the connection and the accumulated tx-data vector.
It should perform the actual transact! call.(with-batch [sym batch-expr] & body)Transaction batching scope. Accumulates tx-data, flushes once on exit.
Normal path: body executes, then batch-flush! runs. Returns flush Result. Exception path: body throws, data is NOT flushed (no partial writes), returns err with exception info.
Usage: (with-batch [batch (tx-batch conn transact-fn!)] (batch-add! batch {:kg-edge/from "a" :kg-edge/to "b"}) (batch-add! batch {:kg-edge/from "c" :kg-edge/to "d"})) ;; => (r/ok tx-result) or (r/err :batch/flush-failed ...)
Transaction batching scope. Accumulates tx-data, flushes once on exit.
Normal path: body executes, then batch-flush! runs. Returns flush Result.
Exception path: body throws, data is NOT flushed (no partial writes),
returns err with exception info.
Usage:
(with-batch [batch (tx-batch conn transact-fn!)]
(batch-add! batch {:kg-edge/from "a" :kg-edge/to "b"})
(batch-add! batch {:kg-edge/from "c" :kg-edge/to "d"}))
;; => (r/ok tx-result) or (r/err :batch/flush-failed ...)cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |