spring-graphql
spring-graphql copied to clipboard
Explore support for (multiple) transactions and update documentation to provide guidance
In GraphQL it is possible to execute 1.n mutation.
mutation multipleMutations {
m1:createRoute(flightNumber:"LH2722") {
id
}
m2:createRoute(flightNumber:"LH2728") {
id
}
}
If I write the data per mutation via a CrudRepository
, each mutation is transactional on its own. But how can I pack all mutations into a transaction bracket. Is there transaction support via a transactional ExcecutionStrategy
or is there possibly @Transaction
directives support?
mutation @Transaction multipleMutations {
m1:createRoute(flightNumber:"LH2722") {
id
}
m2:createRoute(flightNumber:"LH2728") {
id
}
}
Perhaps the documentation could be expanded to include a Transaction chapter and describe the current options.
This is not implemented because it goes against the specification.
If the operation is a mutation, the result of the operation is the result of executing the operation’s top level selection set on the mutation root object type. This selection set should be executed serially.
It is expected that the top level fields in a mutation operation perform side-effects on the underlying data system. Serial execution of the provided mutations ensures against race conditions during these side-effects. https://spec.graphql.org/October2021/#sel-EANNHDDAADFA6Gy9X
A proposal for something like what you want was launched in December last year: https://github.com/graphql/graphql-wg/blob/5a09fee3dabd8c7a9313de765ab0370586d13941/notes/2021-12-02.md#discuss-graphql-mutation-designs-with-large-schemas-nested-mutations-30m-aleksandar https://github.com/graphql/graphql-wg/discussions/815
In the meantime you could change your API:
type Mutation {
createRoute(routes: [CreateRouteFlightInput!]!): CreateRoutePayload!
}
input CreateRouteFlightInput {
flightNumber: ID!
}
type CreateRoutePayload {
ids: [ID!]!
}
# mutation
mutation multipleMutations {
createRoute(routes: [{flightNumber: "LH2722"}, {flightNumber: "LH2728"}]) {
ids
}
}
Lists in GraphQL are ordered. So it becomes an application-level concern that the returned ids are ordered.
A GraphQL list is a special collection type which declares the type of each item in the List (referred to as the item type of the list). List values are serialized as ordered lists, where each item in the list is serialized as per the item type.
You could of course create a custom ExcecutionStrategy
that wraps everything in a Spring transaction, but I am unaware of any other framework doing so. Doing this won't be the recommanded route, as your implementation might defer from the spec at later stages.
@jord1e Thank you for the explanation, the links to the discussions and the workaround.
The topic of mutations and transactions can certainly be discussed in a differentiated manner. And there are some articles about it on the internet.
So I would be grateful if we could include a sentence about it in the Spring GraphQL Documentation?
For example in chapter 5 Data Integration oder chapter 6 Annotated Controllers.
This is just a first suggestion:
Spring GraphQL does not support transactions, neither for queries nor for mutations or subscriptions.
Transactions are the responsibility of the developer outside of Spring GraphQL.
After some thought, I also have to say that transaction support at the Spring GraphQL level doesn't make any sense and comes with many questions and problems. I think the transactions need to be resolved via Spring services transactions and repositories transactions depending on the business use case.