Replies: 1 comment 1 reply
-
I like both ideas. Adding transactional support to the other endpoints through an optional query param like Adding new paths to the existing transactions endpoint might be a bit tricky since that endpoint is using the transaction id as a path argument. I don't see that we would be able to remove the existing transactions endpoint any time soon and more likely never. Might be cleaner to create a brand new endpoint, maybe I would prefer adding transactional support to the other endpoints, but I'm worried that the code changes required to support this would be quite big. There is a protocol endpoint that we can use to notify clients of the new changes, but it's not really rich enough for doing protocol negotiation. I know that the last time we changed the protocol version we broke a bunch of clients, both old clients talking to new servers and new clients talking to old servers. Would probably be much nicer if it supported some sort of negotiation by either returning a list of supported protocols or by taking an argument of protocols supported by the clients and returning the highest one supported by the server. I really don't want to change the protocol version for RDF4J 5.0.0 because of how brittle older clients are. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Hello, I use RDF4J in my day-to-day and help a bunch of people with it as well, and love it. Howerver, one pain point that keeps coming up is interacting and building around the transaction endpoint(s). I'll illustrate the problems I've been facing further in a bit and some ideas we've had how to address them. I was wondering, primarily, if the project would be willing to go through an API change as part of 5.x.x (as I know it's not a trivial task). To be up front, would love to contribute a solution back, just want to get some community input before I put too much work in on it. Also, fully note there's been some discussion on this in the past in #4492 #4519 and some ideas there were used as the seed for this train of thought.
Current Pain Points with the Transaction API
The current issues that we've come up against when using the transaction API can be broken down fairly well into: (1) confusion due to overloaded HTTP methods making it difficult to decipher API; and (2) a little cumbersome to create wrapper libraries around API calls since there are two implementations transactional and non-transactions when in the library they are the same calls, just in different contexts.
A Few Ideas
Idea 1: Endpoint Per Transaction
This idea is pulled from #4492 where you have one endpoint per action as illustrated in the following:
Pros: This method solves the issue with the overloaded endpoint and is easy to understand at a glance how to use
Cons: This method still requires a different interaction pattern with transactions from the other APIs in RDF4J
Idea 2: Mirror Non-Transactional API with Different Base URL
This idea was also mentioned in #4492 as a possible solution, and I'll try to flesh it out a bit more here. Essentially, just as in the Repository API, we can mirror the same non-transactional API and use the base URL / transaction resource rather than the repository resource to provide the transactional “context” that we desire. The API would therefore look something akin to the following:
You could even consider adding the graph store API to this at some point if desired as well, quite easily.
Pros: This method addresses the pain points with overloaded endpoints as well as provides the easiest way to create a transactional wrapper, you just need to change the base URL of your client from /repositories/{id} to /transactions/{xid}/data
Cons: Some methods such as named graphs maybe wouldn't be implemented, and some may assume since the APIs are mirrored that it is, but docs should be able to address this to some extent, and it would be easy to add if needed (though maybe you woukd want to exclude some enpoints like PUT the data of an entire repository). Possibly also some code duplication in transactional v. non-transactional controllers.
Idea 2: Add Query Parameter / Header to Other Endpoints
This idea leverages the fact that a transaction is more-or-less a “context” we would like a given action to execute in. This idea would see the transaction creation API return an 'xid' in its payload, which the caller would attach to other API calls it wants to execute in this transaction. This would fully separate the transaction as a separate REST resource to manage from the actual calls to the repository API. There are a few examples of this out in the wild to varying degrees of clarity (example). The API would therefore look something akin to the following:
POST /repository/{id}/transactions ⇒ application/json: {"xid": "1234"} or something similar and Location: /transactions/1234
You could easily add or exclude specific endpoints just by adding the parameter.
Pros: Exact same API methods for transactional and non-transactional and separation of transaction resource from repository resources (perhaps a bit more RESTful).
Cons: Controllers for non-transactional APIs would become more complex / the line between transactional and non-transactional is perhaps not as clear. Also, could more easily break a multi-node setup which does not use sticky sessions, so that would need to be considered (I think it shouldn't be too hard to workaround however).
Backwards Compatibility
As this is a major API change, backwards compatibility could pose more of an challenge. However, if a change like this made it into 5.0, perhaps this would be chalked up to migration. I understand that is not a very good paved path, however, so I would maybe suggest keeping the old API around but add a deprecation warning header and eventually remove it further down the line to make migration a bit easier (especially if a change like this didn't make it in till say 5.1+). I intentionally tried to design the ideas suggested to still allow the old API to coexist without interruption (DELETE /transactions/{xid} could be rollback by default or something).
Conclusion
Let me know your thoughts and concerns! This has been something I've been chatting with some people for a little while on and think it would be a great quality of life improvement and would be very happy to implement it if there are not any major reservations. Also these are just ideas and am very open to discussing and changing them with feedback!
Looking forward to hearing from you all!
~ Benji
Beta Was this translation helpful? Give feedback.
All reactions