Question

Let's assume we have some configuration GUI that in its current form uses direct DB transactions to submit new configurations for more than one configurable component in a consistent manner.

Now let's move the data (DB) stuff behind some SOAP/WS API. The GUI has no direct DB access anymore. The transactional behaviour must remain, but the API should NOT be designed to explcitly accommodate the GUI form submissions. In fact, I don't even know how the new GUI will work or how the user input will be structured. Therefore I need to provide something like WS-AtomicTransaction on the API server side. However, there are (at least) two caveats:

  • The GUI is written in PHP: I don't think there is any WS-Transaction support in PHP available.
  • I don't want to keep DB transactions open on the server side while waiting for additional client requests.

Solutions I can think of:

  • using Camel's aggregation. However, that would make things more complicated in at least two ways:
    • You cannot use DB row ids of newly inserted rows in the subsequent calls inside the same transaction. You need to use some sort of symbolic back-referencing because there would be no communication between client and server while processing the aggregated messages.
    • call replies would not be immediate (or the immediate and separate reply to each single call would only be some sort of a stub, ie. not containing any useful information beyond "your message has been attached to TX xyz" -- if that's at all possible in the Camel aggregation case).
  • the two disadvantages of the previous solution make me think of request batches where possibly the WS standards provide means for referencing call results in subsequent calls inside the batch transaction. Is there any such thing already available? Maybe even as a PHP client?
  • trying to eliminate lock contention in the database by carefully using row-level locks etc. However, when inserting new elements, my guess is that usually pages and index pages need to be locked by the DB.
  • maybe some server-side persistence layer using optimistic locking? But again, that would not return any DB IDs back to the client before the final commit if DB writes would be postponed until the commit (don't know if that's possible at all).

What do YOU think?

Was it helpful?

Solution

Transactions are a powerful tool and we easily get into a thinking pattern in which we see every problem as a nail we hit with this big hammer. I can relate to your confusion because I've experienced it myself. Unfortunately I have no better advice for you than to try not think in terms of transactions but of atomic API calls.

When I think in terms of transactions, my thought pattern usually goes like this:

  • start transaction
  • read (repeat as required)
  • update (repeat as required)
  • commit/roll back

It takes some time to realize that we overuse this pattern. Actual conflicts are rare and there are many other ways of dealing with them. Here is a commonly used one in APIs

  • read and send data to client (atomic API call)
  • update data (on the client)
  • send original + updates back to the server (atomic API call)
    • start transaction (on server)
    • read
    • compare with original from client
    • if not same, return error (client should retry)
    • if same, update
    • commit

The last six points are part of the implementation of the API call.

Ferenc Mihaly http://theamiableapi.com

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top