Why there is no `Ash.Changeset.around_transaction`?
I was wondering why there is no
around_transaction
function in Ash.Changeset
. We already have a around_action
option, but that one runs inside a transaction, meaning that I can't use it if I wan't to add something to the DB regardless if the action itself fails or not.
I know that there is a before_transaction
and after_transaction
, but depending on what I'm doing this would not work.
Just to give a more concrete example.
I'm planning to port this into a Ash change:
The idea in this function is that I will first use Mutex
to make sure that I always have only one code path reaching this code block at a time, after it, I create a transaction, which basically means that I have a transaction
table and I store a row there for that user
and type
.
I then run the apply_function
, if that function doesn't return an error, it will call the delete_transaction!
function that will remove the transaction and return the response, otherwise, it will just crash leaving the added transaction in the DB, this means that next time this code is called, it will fail to create a transaction and it will run the update_function
instead.
If I just wanted to create the transaction row in the DB, I would be able to create two changes, one with after_transaction
(to create the row) and one with before_transaction
(to delete it), but that doesn't work with the Mutex
call, for the mutex I need something like around_action
but for transactions.10 Replies
We could potentially add an
around_transaction
hook, it just hadn’t come up before
In the meantime, you can make a manual action, set transaction? false
and then in the manual action implementation call the appropriate action with changeset.params
I can do that, but then I would need to create one manual action for each action that I want to use this right?
Yes, unfortunately
Would you say this is something in the roadmap? I was looking into the code to see if I could do a PR, but seems like it is not somthing that I can do without spending some time understanding the Ash.Changeset code first
Something to keep in mind with transaction hooks is that they don’t work when composed with other resource actions. It only works if the action is the “top level” action. The hooks will still fire, but if they are already in a transaction then they won’t of course be “around” the transaction.
Its probably not that hard to accomplish tbh
There is a function called
with_hooks
in changeset that you’d basically copy the implementation of the around action hooks, and call that first thing in that with hooks functionSomething to keep in mind with transaction hooks is that they don’t work when composed with other resource actions. It only works if the action is the “top level” action. The hooks will still fire, but if they are already in a transaction then they won’t of course be “around” the transaction.That's fine, the idea is to only use it in "top level" actions anyway 🙂
@Zach Daniel can you take a look into this PR? https://github.com/ash-project/ash/pull/632
GitHub
feat: Adds Ash.Changeset around_transaction by sezaru · Pull Reques...
This doesn't unit tests since I couldn't find unit tests for around_action, before_transaction or after_transaction to use as reference.
Contributor checklist
Bug fixes include regression...
Seems to work for me, but I'm not sure if I missed some corner case
That looks right to me. Will review more thoroughly when I get home. Well want to warn on any around transaction hooks like we do the other ones
Like add this to the top of the function before running the around transaction hooks:
warn_on_transaction_hooks(changeset, changeset.around_transaction, "around_transaction")
I pushed a commit with that change