Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request juju#17926 from SimonRichardson/state-base-context…
…-run juju#17926 RunAtomic starts to add the ability to call discrete state methods within a transaction scope, without exposing the underlying transaction implementation at the service layer. It solves the problem of trying to execute business logic at the service layer without exposing sql.Tx or sqlair.TX types. The AtomicContext interface type is a typed context.Context that can be provided as a parameter to the Run closure. The RunAtomic method gets a DB and then creates a transaction. Within that transaction, a txContext is then created that captures both the context and the sqlair.TX. This tuple can then be passed as an argument to the closure. The txContext ensures that the sqlair.TX can only be within the closure for the lifetime of the transaction. This is to prevent capturing the AtomicContext and using it outside of the RunAtomic method. This type of usage will cause an error later on in the state code if someone does attempt to use it. The tuple was defined this way, as it's not possible to modify a generic context.Value without creating a new context, or creating a bespoke implementation. Thus the tuple presents the best approach to ensuring safety and easy access. It should be noted that because of go invariance it's not possible to swap a RunAtomic closure for the following type: st.RunAtomic(ctx, func(ctx context.Context) error { ... }) This will simply not compile. The RunAtomic function must be of instance type: st.RunAtomic(ctx, func(txCtx AtomicContext) error { ... }) Lastly, I've added a note that the AtomicContext implementation (txContext) can be pooled[1] to keep the allocations of the txContext low. That is not part of this changeset and can be done in future work. 1. https://pkg.go.dev/sync#Pool <!-- The PR title should match: <type>(optional <scope>): <description>. Please also ensure all commits in this PR comply with our conventional commits specification: https://docs.google.com/document/d/1SYUo9G7qZ_jdoVXpUVamS5VCgHmtZ0QA-wZxKoMS-C0 --> <!-- Why this change is needed and what it does. --> ## Checklist <!-- If an item is not applicable, use `~strikethrough~`. --> - [x] Code style: imports ordered, good names, simple structure, etc - [x] Comments saying why design decisions were made - [x] Go unit tests, with comments saying what you're testing ## QA steps Nothing is using this, more patches will be added to build upon this infrastructure. ## Links **Jira card:** JUJU-
- Loading branch information