jakartaee / transactions

Welcome to the Jakarta EE Transactions API Project (formerly JTA)
https://jakartaee.github.io/transactions/
Other
29 stars 30 forks source link

support explicit ordering of commits for XAResources enlisted in a transaction #58

Open glassfishrobot opened 12 years ago

glassfishrobot commented 12 years ago

As reported here: http://java.net/jira/browse/JMS_SPEC-28 (and originally here: http://java.net/jira/browse/JAVAEE_SPEC-1) :

Currently there is no standard way how to enforce the ordering of the XAResource commits for the transaction. There are workarounds such as http://docs.redhat.com/docs/en-US/JBoss_Enterprise_Application_Platform/5/html/Transactions_Development_Guide/chap-Transactions_JTA_Programmers_Guide-Test.html#form-Transactions_JTA_Programmers_Guide-The_XAResource_Interface-Extended_XAResource_control for example, but I think that a properly specified standard API would be much better.

glassfishrobot commented 5 years ago
glassfishrobot commented 12 years ago

@glassfishrobot Commented Reported by paul_parkinson

glassfishrobot commented 12 years ago

@glassfishrobot Commented irobins said: There are some good reasons for wanting to do this but there are other ways to accomplish it than extending XAResource. One way (we did this as a WebSphere vendor extension) is as an extension to the resource-reference. We found this a simple way to enable different apps to use resources in different orders without polluting any runtime beyond the TM and ConnectionManager.

glassfishrobot commented 12 years ago

@glassfishrobot Commented tomjenkinson said: Please can you clarify the use case that this feature is intended to address? I think that there are at least two interpretations of what this Jira could be intended to address:

The first interpretation I see is that we will support explicit ordering of commit completions (we won't move on to the next resource until we receive any true completion value, i.e. any value that is not an XAER_RMFAIL). A feature like this would be able to address use cases such as "race conditions". There is a good article describing race conditions of XAResources here: http://jbossts.blogspot.co.uk/2011/04/messagingdatabase-race-conditions.html. However, providing a capability to address the issues discussed in that article would require the Transaction Manager to wait for completed commits (i.e. retry the commits for resources returning XAER_RMFAIL before moving on to higher order XAResources). This would couple the transaction manager into the business logic which is not desirable. For example, if we do not wait for the commit completion message (either XA_OK or a heursitic) the user will still need to add business logic to compensate for data unavailability which would be unexpected and (in my mind) undermine the value of the feature should the programmer be expecting an "explicit ordering of commits" (I allow heurisics as this feature does not mention it is intended to address heurisitic outcomes). For example, consider a database (DB) and message broker (MQ) resource pair where you want the DB to commit first so the MQ can view the revised state: DB.prepare() MQ.prepare() tm.log(); DB.commit() -> returns XAER_RMFAIL MQ.commit() -> business logic fails as expected db rows are not yet committed DB.commit(retried)

The second interpretation I see could be that we will support explicit ordering of commit attempts. In this case we would move onto the next resource regardless of the result of the current XAResource.commit(). A feature like this can support use cases that do not couple the transaction manager to the business logic (i.e. in the event of a commit failure, the transaction manager is still at liberty to move on to higher ordered XAResources). For example if certain XAResources are more "probable" to fail, a developer may wish to attempt those first. However, if this is the intended use case, I think that the feature would be better described as "support explicit ordering of prepares for XAResources enlisted in a transaction", or possibly "support explicit ordering of commit attempts for XAResources enlisted in a transaction".

glassfishrobot commented 12 years ago

@glassfishrobot Commented leos.bitto said: "providing a capability to address the issues discussed in that article would require the Transaction Manager to wait for completed commits (i.e. retry the commits for resources returning XAER_RMFAIL before moving on to higher order XAResources). This would couple the transaction manager into the business logic which is not desirable." - I think that if the users explicitly state that they want the ordering of the XAResource commits (for example DB first, JMS later), then the Transaction Manager should simply obey this. Such coupling of TM to the business logic is quite light in my opinion, and it is fully justified by the fact that otherwise the race conditions between the JMS commit and the DB commit have to be handled in the user code, which is ugly.

glassfishrobot commented 11 years ago

@glassfishrobot Commented mmusgrove said: Please could we also include Synchronizations in this discussion. I know we already have limited ordering semantics with interposed synchronizations as standard but we have had other ordering requirements from the JCA (and I think JPA) teams within the wildfly application server. What I'd like to see is an interface that allows us to order some synchronisations relative to each other and allow others to run as normal - ie the synchronisations would form a partially ordered set where we have the choice to run independent partial orders in parallel.

glassfishrobot commented 11 years ago

@glassfishrobot Commented leos.bitto said: I don't think that adding more requirements to this Jira issue is a good idea because that it has been originally reported in December 2011, it is still not resolved and there is not even any progress visible. Regarding Synchronizations there actually is an easy solution: register only one Synchronization which would be implemented to allow runnning other Synchronizations with any order you like (composite pattern).

glassfishrobot commented 7 years ago

@glassfishrobot Commented This issue was imported from java.net JIRA JTA_SPEC-4

glassfishrobot commented 6 years ago

@jhalliday Commented Proposal to start off the design discussion:

Three distinct use cases are identified for this feature.

1) Support for Last Resource Commit Optimization, in which a non-XA RM participates in the transaction via a XAResource that maps prepare->commit and commit->nullop. For the optimization to be effective, such as resource must be called last in the prepare phase of the 2PC. To support this the XAResource must be able to indicate that it is a LR. Currently this is typically accomplished by product specific datasource deployment configuration mechanisms.

2) Support for anticipatory 1PC, in which resources expected to vote XA_RDONY are called early in the prepare phase, such that if only a single resource then remains that may not be read-only, it can be called with one phase commit. To support this, the driver implementing the resource must track the connection usage or query the server to determine the likely vote. This is dynamic, i.e. per-transaction, unlike the LRCO which is static per-deployment.

3) In transactions which include a message queue and a database, produced messages may be consumed downstream by logic that expects to see the corresponding update in the db. For example a 'sendWelcomeMessage' listener may consume a 'customerRegistration' message produced from a transaction that also writes the customer details to the db. The message is not self-contained, so the welcome processing logic needs to read those customer details back from the db, using a row key provided in the message. In such architectures, if the tx lock release (i.e. XA commit call) order is indeterminate, then the message may be made available and processed downstream before the db locks are released to allow the row to be seen. Thus we need commit phase ordering, to indicate that the JMS XAResource should be ordered after the DB XAResource.

To support these cases, the following spec changes are proposed:

Add two new enumerations:

public enum PreparePriority {
  EARLY, // indicates likely RDONLY or fail.
  NORMAL, // default
  EXCLUSIVE_LAST // for Last Resource Commit Optimization.
}

public enum CommitPriority {
  EARLY,
  NORMAL, // default
  LATE
}

These will be used with the following new methods:

public interface XAResource {
...
    default public CommitPriority getCommitPriority(Xid xid) throws XAException {
        return CommitPriority.NORMAL;
    }

    default public PreparePriority getPreparePriority(Xid xid) throws XAException {
        return PreparePriority.NORMAL;
    }

The use of enums is new to JTA, since in most cases defined int constant values correspond to those from the C based XA spec. Thus an alternative could use int constants in place of enums for consistency of API design, perhaps on range similar to that used for Thread priorities. Likewise the use of default interface methods is new, since they didn't exist when the decision was made to add methods to the new TransactionSynchronizationRegistry API that would have been better suited to e.g. Transaction. An alternative design would avoid them by defining a new sub-interface, e.g. 'PrioritizableXAResource extends XAResource'

The spec should require that

Let the discussion commence...

glassfishrobot commented 6 years ago

@tomjenkinson Commented I could see the benefit for also adding an EXCLUSIVE_FIRST in commit ordering. LRCO style behaviour may also be implemented by writing a transaction manager log entry and then committing the 1PC resource first, we do that for some algorithms in Narayana.

glassfishrobot commented 5 years ago

@gandhirajan Commented Any update on this feature request? I feel its very much required.

omasseau commented 1 year ago

Indeed it would be very useful to have this feature. Most of the time we need JMS to be committed after the DB.

jhalliday commented 6 months ago

Some notes extending and modifying my previous position:

Metadata relating to prepare and commit ordering could also be used to inform enlistment decisions. These issues are somewhat related, as e.g. a TM may choose not to allow more than a single LastResource in the same transaction as that's unsafe... except if one is also read-only, in which case it's not a problem.

That may point towards generalising the previous interface proposal so extra information can be used for a variety of puposes in a more extensible manner e.g.

public interface XAResource {
...
    default public ResourceMetadata getMetadata(Xid xid) throws XAException {
        return ResourceMetadata.NORMAL;
    }

However, in terms of the implementation and despite default methods, it's potentially tricky to change XAResource, as whilst it's arguably under the purview of the JTA spec, it's distributed as part of OpenJDK rather than in the spec jar. Thus alternatives including e.g.

public interface XAResourceWithMetadata extends XAResource {

    public XAResourceMetadata getMetadata(Xid xid) throws XAException;

or

 transactionManager.enlistResource(resource, metadata)

(and if we wish to digress slightly:)

transactionManager.registerSynchronization(sync, metadata)

or annotations

@ReadOnlyResource
@OnePhaseResource
public class SomeVendorsXAResource implements XAResource

though that causes multiple classes to be needed for different combinations of annotations, similar to the older but still feasible marker interfaces approach

public class SomeReadOnlyXAResource implements ReadOnlyXAResource