You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Make insertGraph() and upsertGraph() atomic by default #477
insertGraph() and upsertGraph() write a graph with many queries, and they aren't atomic unless the caller passes a transaction. A database error halfway, e.g. a UniqueViolationError in a later step, leaves the rows of the earlier steps written. The checks before the first write catch invalid graphs, but not the errors that only the database raises.
Both methods should run in their own transaction when the query isn't already in one:
A query that already runs in a transaction, passed to it or bound to its model, keeps using it.
The transaction covers the whole call, including the loads of upsertGraph(), so that the reads match the writes.
{ transaction: false } keeps the current behaviour.
This changes behaviour for hooks that run queries through another connection than context.transaction: they wait for the transaction, and on SQLite with its single connection they deadlock. The migration guide needs to say so, with transaction: false or running those queries in the transaction as the way out. The notes that the methods aren't atomic by default in the guide go.
Strict mode (#429) is atomic since #533: strict calls run in their own transaction unless the query already runs in one, with no transaction: false opt-out. Non-strict calls stay as they are until the next major.
Activity
Run strict insertGraph() and upsertGraph() in a transaction (#429, #477)
Run strict insertGraph() and upsertGraph() in a transaction (#429, #477…
lehni commentedon Oct 25, 2026
Strict mode (#429) is atomic since #533: strict calls run in their own transaction unless the query already runs in one, with no
transaction: falseopt-out. Non-strict calls stay as they are until the next major.lehni commentedon Oct 25, 2026
Superseded by #534: once strict mode is the default, every call is atomic, without a
transaction: falseopt-out.