-
-
Notifications
You must be signed in to change notification settings - Fork 579
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to rollback all mutations if only one of them falls? #944
Comments
Sorry, this would not adhere to the GraphQL specification, so is not something that we plan to implement. There is no dependency between mutations (other than their serial nature) and it’s valid for one to fail but the others to succeed. https://facebook.github.io/graphql/draft/#sec-Mutation One option within the GraphQL spec would be to make the mutation payloads non-nullable, but this has consequences (and goes against best practices). To handle this, the intention is to do one “transaction” per mutation. You may also be interested in a GraphQL proposal that relate to this: (Full disclosure: your request is currently possible by wrapping mutation resolvers and aborting the parent transaction when an error occurs; however this behaviour will be changing in a future release and I strongly recommend you do not do it.) Closing as wontfix; but feel free to keep discussing below. |
I fully agree with @benjie |
Oh, this is postgraphile..
|
Thanks for the quick response! Your excellent library allowed us to remove more than 20 thousand lines of golang code. Can you tell me if it’s possible to delete savepoints using a plugin or plugin+directives? If so, what plugin methods will help to do this? |
It’s not possible to delete them, but you can wrap them with further save points and rollback to those 😁 https://www.graphile.org/postgraphile/make-wrap-resolvers-plugin/ |
(This will not work in version 5, because each mutation will use its own independent transaction.) |
Does anyone have an example of how they solved this? 🙏 I understand the rationale for wontfix but there are legitimate cases where you would want to make a collection of mutations atomic |
The correct way to do this in GraphQL is to make the atomic operation a single field. |
Yes but say for example I have 2 people with a balance account, and I want to move funds from one to another. If the second were to fail, it all needs to fail. To my knowledge the only way to force that into a single mutation is by using the nested mutations plugin. Is there another way? |
Specifically my example is I need to update 10 items but it needs to be all or nothing |
To expand on my previous answer, the correct way to do this in GraphQL would be with a mutation like this that achieves the full atomic operation in a single field: mutation {
transferBalance(input: {amount: 10, fromId: 27, toId: 93}) {
success
}
} In PostGraphile you could do this with a Custom Mutation such as: create function transfer_balance(amount int, from_id int, to_id int) returns boolean as $$
begin
update users set balance = balance - amount where id = from_id;
update users set balance = balance + amount where id = to_id;
return true;
end;
$$ language plpgsql volatile; or via makeExtendSchemaPlugin. |
Just my 2cents from a Postgres perspective. I am working on a system where we detect a change in an external object, which then needs to be updated / inserted or deleted in PG. Much faster and more reliable to do it this way than issuing individual statements from the calling program. All mutations are handled through functions, no direct table access. |
Fantastic, thanks for that I'll have a play around with some pg functions to handle this |
This is useful for applications with large client logic, they will be able to manipulate mutations as Lego cubes, without creating separate custom mutations just for the sake of combining them under one transaction.
The text was updated successfully, but these errors were encountered: