what I mean is that the bigger surrogateId will update the variable
"nextEndedEventId" and alpha cannot find the smaller one.
> eventRepository.findFirstUncompensatedEventByIdGreaterThan(nextEndedEventId,
> TxEndedEvent.name())
.forEach(event -> {
LOG.info("Found uncompensated event {}", event);
nextEndedEventId = event.id();
commandRepository.saveCompensationCommands(event.globalTxId());
});
@Query("SELECT t FROM TxEvent t "
+ "WHERE t.type = ?1 AND t.surrogateId > ?2 AND EXISTS ( "
+ " SELECT t1.globalTxId FROM TxEvent t1 "
+ " WHERE t1.globalTxId = t.globalTxId "
+ " AND t1.type = 'TxAbortedEvent' AND NOT EXISTS ( "
+ " SELECT t2.globalTxId FROM TxEvent t2 "
+ " WHERE t2.globalTxId = t1.globalTxId "
+ " AND t2.localTxId = t1.localTxId "
+ " AND t2.type = 'TxStartedEvent' "
+ " AND t2.creationTime > t1.creationTime)) AND NOT EXISTS ( "
+ " SELECT t3.globalTxId FROM TxEvent t3 "
+ " WHERE t3.globalTxId = t.globalTxId "
+ " AND t3.localTxId = t.localTxId "
+ " AND t3.type = 'TxCompensatedEvent') AND ( "
+ " SELECT MIN(t4.retries) FROM TxEvent t4 "
+ " WHERE t4.globalTxId = t.globalTxId "
+ " AND t4.localTxId = t.localTxId "
+ " AND t4.type = 'TxStartedEvent' ) = 0 "
+ "ORDER BY t.surrogateId ASC")
List<TxEvent> findFirstByTypeAndSurrogateIdGreaterThan(String type, long
surrogateId, Pageable pageable);
Take the saga-spring-demo as example.
There are two request at the same time. They firstly invoke the car service and
succeed. Then they invoke the hotel service,but the hotel service fail.
if we can't ensure the order of message of two different invocations, Alpha may
receive messages in the following order:
<img width="673" alt="5c1da0985073e2642b6429432d974011"
src="https://user-images.githubusercontent.com/9289881/44309435-294e9480-a3f9-11e8-8755-cdfb02d6bd66.png">
`
String sagaGlobalId = UUID.randomUUID().toString(); //Request1
String bookingApplicationLocalId = UUID.randomUUID().toString();
String carServiceLocalId = UUID.randomUUID().toString();
String hotelServiceLocalId = UUID.randomUUID().toString();
String anotherSagaGlobalId = UUID.randomUUID().toString();//Request2
String anotheBookingApplicationLocalId = UUID.randomUUID().toString();
String anotherCarServiceLocalId = UUID.randomUUID().toString();
String anotherHoterServceiLocalId = UUID.randomUUID().toString();
asyncStub.onConnected(serviceConfig, compensateResponseObserver);
blockingStub.onTxEvent(someGrpcEvent(SagaStartedEvent, sagaGlobalId,
bookingApplicationLocalId));
blockingStub.onTxEvent(someGrpcEvent(SagaEndedEvent, anotherSagaGlobalId,
anotheBookingApplicationLocalId));
blockingStub.onTxEvent(someGrpcEvent(TxStartedEvent, sagaGlobalId,
carServiceLocalId));
blockingStub.onTxEvent(someGrpcEvent(TxEndedEvent, sagaGlobalId,
carServiceLocalId));
//surrogateId --> 4
blockingStub.onTxEvent(someGrpcEvent(TxStartedEvent, anotherSagaGlobalId,
anotherCarServiceLocalId));
blockingStub.onTxEvent(someGrpcEvent(TxEndedEvent, anotherSagaGlobalId,
anotherCarServiceLocalId));
//surrogateId --> 6
blockingStub.onTxEvent(someGrpcEvent(TxStartedEvent, sagaGlobalId,
hotelServiceLocalId));
blockingStub.onTxEvent(someGrpcEvent(TxStartedEvent, anotherSagaGlobalId,
anotherHoterServceiLocalId));
//the latter hotelservice abort event come first
blockingStub.onTxEvent(someGrpcEvent(TxAbortedEvent, anotherSagaGlobalId,
anotherHoterServceiLocalId));
await().atMost(2, SECONDS).until(() -> !receivedCommands.isEmpty());
//the TxAbortedEvent of the first hotelservice TxAbortedEvent didn't come
until the previous TxAbortedEvent has been found
blockingStub.onTxEvent(someGrpcEvent(TxAbortedEvent, sagaGlobalId,
hotelServiceLocalId));
//now, the variable "nextEndedEventId" is 6, so the TxEndedEvent whose
surrogateId is 4 can't be found.
await().atMost(10, SECONDS).until(() -> receivedCommands.size() > 1);
assertThat(receivedCommands.size(), is(2));
`
[ Full content available at:
https://github.com/apache/incubator-servicecomb-saga/issues/253 ]
This message was relayed via gitbox.apache.org for [email protected]