You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by ni...@apache.org on 2018/03/04 12:04:48 UTC
[incubator-servicecomb-saga] 01/02: SCB-363 Remove legacy code
This is an automated email from the ASF dual-hosted git repository.
ningjiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-servicecomb-saga.git
commit b8e39d16f6a650dce447b2dcae0fdd240b8de385
Author: Yang Bo <ya...@huawei.com>
AuthorDate: Fri Mar 2 01:09:12 2018 +0800
SCB-363 Remove legacy code
The support for legacy mode will be dropped, remove all the related
code from master branch.
---
docs/api/api.md | 168 -----
docs/old_saga.md | 53 --
integration-tests/coverage-aggregate/pom.xml | 20 -
pom.xml | 50 +-
saga-core/pom.xml | 103 ---
.../servicecomb/saga/core/BackwardRecovery.java | 49 --
.../apache/servicecomb/saga/core/Compensation.java | 33 -
.../saga/core/CompensationTaskConsumer.java | 69 --
.../servicecomb/saga/core/CompositeSagaLog.java | 40 --
.../saga/core/CompositeSagaResponse.java | 48 --
.../apache/servicecomb/saga/core/Descriptive.java | 25 -
.../apache/servicecomb/saga/core/EventContext.java | 28 -
.../servicecomb/saga/core/EventEnvelope.java | 47 --
.../apache/servicecomb/saga/core/EventStore.java | 25 -
.../servicecomb/saga/core/FailedSagaResponse.java | 50 --
.../org/apache/servicecomb/saga/core/Fallback.java | 25 -
.../servicecomb/saga/core/FallbackPolicy.java | 62 --
.../servicecomb/saga/core/ForwardRecovery.java | 53 --
.../servicecomb/saga/core/GraphBasedSaga.java | 132 ----
.../apache/servicecomb/saga/core/IdGenerator.java | 25 -
.../saga/core/LoggingRecoveryPolicy.java | 46 --
.../servicecomb/saga/core/LongIdGenerator.java | 30 -
.../servicecomb/saga/core/NoOpSagaRequest.java | 107 ----
.../apache/servicecomb/saga/core/Operation.java | 33 -
.../servicecomb/saga/core/PersistentLog.java | 22 -
.../servicecomb/saga/core/PersistentStore.java | 26 -
.../servicecomb/saga/core/RecoveryPolicy.java | 26 -
.../servicecomb/saga/core/RequestProcessTask.java | 67 --
.../servicecomb/saga/core/RestOperation.java | 59 --
.../org/apache/servicecomb/saga/core/Saga.java | 27 -
.../apache/servicecomb/saga/core/SagaContext.java | 36 --
.../servicecomb/saga/core/SagaContextImpl.java | 133 ----
.../servicecomb/saga/core/SagaDefinition.java | 25 -
.../apache/servicecomb/saga/core/SagaEndTask.java | 48 --
.../servicecomb/saga/core/SagaEndedEvent.java | 38 --
.../apache/servicecomb/saga/core/SagaEvent.java | 39 --
.../servicecomb/saga/core/SagaException.java | 29 -
.../org/apache/servicecomb/saga/core/SagaLog.java | 22 -
.../apache/servicecomb/saga/core/SagaRequest.java | 48 --
.../servicecomb/saga/core/SagaRequestImpl.java | 153 -----
.../apache/servicecomb/saga/core/SagaResponse.java | 61 --
.../saga/core/SagaStartFailedException.java | 25 -
.../servicecomb/saga/core/SagaStartTask.java | 56 --
.../servicecomb/saga/core/SagaStartedEvent.java | 46 --
.../apache/servicecomb/saga/core/SagaState.java | 27 -
.../org/apache/servicecomb/saga/core/SagaTask.java | 31 -
.../servicecomb/saga/core/SagaTaskFactory.java | 98 ---
.../saga/core/SuccessfulSagaResponse.java | 43 --
.../apache/servicecomb/saga/core/TaskConsumer.java | 29 -
.../apache/servicecomb/saga/core/TaskRunner.java | 72 ---
.../apache/servicecomb/saga/core/ToJsonFormat.java | 26 -
.../apache/servicecomb/saga/core/Transaction.java | 27 -
.../saga/core/TransactionAbortedEvent.java | 57 --
.../saga/core/TransactionCompensatedEvent.java | 56 --
.../saga/core/TransactionEndedEvent.java | 56 --
.../saga/core/TransactionFailedException.java | 29 -
.../saga/core/TransactionStartedEvent.java | 45 --
.../saga/core/TransactionTaskConsumer.java | 123 ----
.../apache/servicecomb/saga/core/Transport.java | 22 -
.../saga/core/TransportFailedException.java | 28 -
.../saga/core/actors/ActorBasedSaga.java | 65 --
.../saga/core/actors/ActorBasedSagaFactory.java | 83 ---
.../saga/core/actors/CompletionCallbackActor.java | 69 --
.../saga/core/actors/EventContextImpl.java | 60 --
.../servicecomb/saga/core/actors/RequestActor.java | 206 ------
.../saga/core/actors/RequestActorBuilder.java | 108 ----
.../saga/core/actors/RequestActorContext.java | 82 ---
.../saga/core/actors/messages/AbortMessage.java | 37 --
.../core/actors/messages/AbortRecoveryMessage.java | 33 -
.../core/actors/messages/CompensateMessage.java | 32 -
.../messages/CompensationRecoveryMessage.java | 22 -
.../saga/core/actors/messages/FailMessage.java | 33 -
.../saga/core/actors/messages/Message.java | 21 -
.../saga/core/actors/messages/TransactMessage.java | 39 --
.../messages/TransactionRecoveryMessage.java | 32 -
.../core/application/SagaExecutionComponent.java | 87 ---
.../saga/core/application/SagaFactory.java | 30 -
.../application/interpreter/FromJsonFormat.java | 24 -
.../interpreter/RestRequestChecker.java | 55 --
.../saga/core/dag/ByLevelTraveller.java | 83 ---
.../saga/core/dag/FromLeafTraversalDirection.java | 38 --
.../saga/core/dag/FromRootTraversalDirection.java | 38 --
.../saga/core/dag/GraphBasedSagaFactory.java | 80 ---
.../servicecomb/saga/core/dag/GraphBuilder.java | 109 ----
.../saga/core/dag/GraphCycleDetector.java | 25 -
.../saga/core/dag/GraphCycleDetectorImpl.java | 70 ---
.../org/apache/servicecomb/saga/core/dag/Node.java | 86 ---
.../core/dag/SingleLeafDirectedAcyclicGraph.java | 38 --
.../servicecomb/saga/core/dag/Traveller.java | 29 -
.../saga/core/dag/TraversalDirection.java | 29 -
.../infrastructure/ContextAwareEventStore.java | 56 --
.../saga/infrastructure/EmbeddedEventStore.java | 58 --
.../servicecomb/saga/transports/RestTransport.java | 27 -
.../saga/transports/TransportFactory.java | 23 -
.../saga/core/BackwardRecoveryTest.java | 57 --
.../servicecomb/saga/core/CompensationImpl.java | 27 -
.../saga/core/CompositeSagaLogTest.java | 49 --
.../saga/core/CompositeSagaResponseTest.java | 73 ---
.../apache/servicecomb/saga/core/DummyEvent.java | 31 -
.../servicecomb/saga/core/FallbackPolicyTest.java | 91 ---
.../servicecomb/saga/core/ForwardRecoveryTest.java | 59 --
.../servicecomb/saga/core/LongIdGeneratorTest.java | 36 --
.../servicecomb/saga/core/RestOperationTest.java | 89 ---
.../servicecomb/saga/core/RetrySagaLogTest.java | 80 ---
.../servicecomb/saga/core/SagaEndTaskTest.java | 47 --
.../servicecomb/saga/core/SagaEventMatcher.java | 68 --
.../saga/core/SagaExecutionComponentTestBase.java | 250 --------
.../servicecomb/saga/core/SagaIntegrationTest.java | 687 --------------------
.../servicecomb/saga/core/SagaStartTaskTest.java | 64 --
.../servicecomb/saga/core/TransactionImpl.java | 27 -
.../ActorBasedSagaExecutionComponentTest.java | 31 -
.../core/actors/ActorBasedSagaIntegrationTest.java | 691 ---------------------
.../core/actors/CompletionCallbackActorTest.java | 138 ----
.../saga/core/actors/EventContextImplTest.java | 93 ---
.../saga/core/actors/RequestActorBuilderTest.java | 173 ------
.../saga/core/actors/RequestActorTest.java | 399 ------------
.../dag/DirectedAcyclicGraphTraversalTest.java | 102 ---
.../dag/GraphBasedSagaExecutionComponentTest.java | 33 -
.../saga/core/dag/GraphBuilderTest.java | 148 -----
.../saga/core/dag/GraphCycleDetectorTest.java | 73 ---
.../apache/servicecomb/saga/core/dag/NodeTest.java | 80 ---
.../infrastructure/ContextAwareEventStoreTest.java | 43 --
saga-core/src/test/resources/application.conf | 21 -
saga-core/src/test/resources/log4j2.xml | 30 -
saga-demo/conditional-transaction-demo/README.md | 174 ------
.../conditional-transaction-demo-tests/pom.xml | 301 ---------
.../saga/demo/tests/ConditionalTransactionIT.java | 155 -----
.../docker-compose.yaml | 75 ---
.../conditional-transaction-demo/inventory/pom.xml | 74 ---
.../inventory/InventoryApplication.java | 29 -
.../transaction/inventory/InventoryController.java | 89 ---
.../inventory/InventoryControllerTest.java | 79 ---
.../membership/pom.xml | 74 ---
.../membership/MembershipApplication.java | 29 -
.../membership/MembershipController.java | 62 --
.../conditional-transaction-demo/payment/pom.xml | 75 ---
.../transaction/payment/PaymentApplication.java | 29 -
.../transaction/payment/PaymentController.java | 84 ---
.../transaction/payment/PaymentControllerTest.java | 61 --
saga-demo/conditional-transaction-demo/pom.xml | 40 --
.../conditional-transaction-demo/supplier/pom.xml | 74 ---
.../transaction/supplier/SupplierApplication.java | 29 -
.../transaction/supplier/SupplierController.java | 52 --
.../src/main/resources/META-INF/LICENSE.txt | 202 ------
.../src/main/resources/META-INF/NOTICE.txt | 11 -
.../dependency-free-transaction-demo/README.md | 168 -----
.../car-rental-service/pom.xml | 85 ---
.../saga/demo/car/rental/CarRentalApplication.java | 32 -
.../saga/demo/car/rental/CarRentalController.java | 100 ---
.../src/main/resources/microservice.yaml | 30 -
.../demo-tests/pom.xml | 333 ----------
.../apache/servicecomb/saga/demo/tests/DemoIT.java | 150 -----
.../docker-compose.yaml | 101 ---
.../flight-booking-service/pom.xml | 85 ---
.../flight/booking/FlightBookingApplication.java | 32 -
.../flight/booking/FlightBookingController.java | 77 ---
.../src/main/resources/microservice.yaml | 30 -
.../hotel-reservation-service/pom.xml | 85 ---
.../reservation/HotelReservationApplication.java | 32 -
.../reservation/HotelReservationController.java | 78 ---
.../src/main/resources/microservice.yaml | 30 -
.../payment-service/pom.xml | 85 ---
.../saga/demo/payment/PaymentApplication.java | 32 -
.../saga/demo/payment/PaymentController.java | 81 ---
.../src/main/resources/microservice.yaml | 32 -
saga-demo/dependency-free-transaction-demo/pom.xml | 67 --
saga-demo/pom.xml | 2 -
saga-discovery/pom.xml | 37 --
.../saga-discovery-servicecenter/pom.xml | 124 ----
.../center/ServiceCenterDiscoveryConfig.java | 43 --
.../src/main/resources/META-INF/spring.factories | 18 -
.../src/main/resources/microservice.yaml | 30 -
.../discovery/service/center/DummyController.java | 56 --
.../center/ServiceCenterDiscoveryApplication.java | 32 -
.../ServiceCenterDiscoveryRestTransportTest.java | 132 ----
.../src/test/resources/log4j2-test.xml | 30 -
.../src/test/resources/registry.yaml | 23 -
saga-format/pom.xml | 74 ---
.../saga/core/FailedSagaRequestContext.java | 40 --
.../servicecomb/saga/core/JacksonToJsonFormat.java | 65 --
.../servicecomb/saga/core/SagaRequestContext.java | 37 --
.../saga/core/SuccessfulSagaRequestContext.java | 41 --
.../servicecomb/saga/format/ChildrenExtractor.java | 55 --
.../servicecomb/saga/format/JacksonFallback.java | 64 --
.../saga/format/JacksonFromJsonFormat.java | 58 --
.../saga/format/JacksonRestCompensation.java | 52 --
.../saga/format/JacksonRestFallback.java | 43 --
.../saga/format/JacksonRestOperation.java | 62 --
.../saga/format/JacksonRestTransaction.java | 36 --
.../saga/format/JacksonSagaEventFormat.java | 114 ----
.../saga/format/JsonFailedSagaResponse.java | 29 -
.../saga/format/JsonRestSagaRequest.java | 72 ---
.../saga/format/JsonSagaDefinition.java | 60 --
.../servicecomb/saga/format/JsonSagaRequest.java | 39 --
.../saga/format/JsonSuccessfulSagaResponse.java | 30 -
.../servicecomb/saga/format/SagaEventFormat.java | 25 -
.../servicecomb/saga/format/TransportAware.java | 26 -
.../saga/format/ChildrenExtractorTest.java | 75 ---
.../saga/format/JacksonFromJsonFormatTest.java | 261 --------
.../saga/format/JacksonRestOperationTest.java | 69 --
.../saga/format/JsonRestSagaRequestTest.java | 95 ---
.../saga/format/JsonSagaDefinitionTest.java | 34 -
.../saga/format/SagaEventFormatTest.java | 180 ------
saga-performance/README.md | 47 --
saga-performance/images/grafana.png | Bin 15508 -> 0 bytes
saga-performance/scripts/saga.jmx | 289 ---------
saga-persistence/pom.xml | 36 --
saga-persistence/saga-persistence-jpa/pom.xml | 89 ---
.../jpa/EclipseLinkJpaConfiguration.java | 50 --
.../src/main/resources/META-INF/spring.factories | 18 -
saga-spring/pom.xml | 233 -------
.../saga/spring/JpaPersistentStore.java | 69 --
.../servicecomb/saga/spring/SagaController.java | 222 -------
.../servicecomb/saga/spring/SagaEventEntity.java | 85 ---
.../servicecomb/saga/spring/SagaEventRepo.java | 44 --
.../saga/spring/SagaExecutionQueryService.java | 160 -----
.../saga/spring/SagaRecoveryListener.java | 37 --
.../saga/spring/SagaShutdownListener.java | 42 --
.../saga/spring/SagaSpringApplication.java | 39 --
.../servicecomb/saga/spring/SagaSpringConfig.java | 136 ----
saga-spring/src/main/resources/META-INF/aop.xml | 25 -
.../src/main/resources/META-INF/spring.factories | 20 -
saga-spring/src/main/resources/application.conf | 88 ---
saga-spring/src/main/resources/application.yaml | 30 -
saga-spring/src/main/resources/log4j2.xml | 30 -
.../src/main/resources/schema-postgresql.sql | 26 -
.../ActorBasedSagaSpringApplicationTest.java | 25 -
.../GraphBasedSagaSpringApplicationTest.java | 25 -
.../saga/spring/GreetingController.java | 42 --
.../servicecomb/saga/spring/SagaRecoveryTest.java | 181 ------
.../saga/spring/SagaServiceDiscoveryTest.java | 113 ----
.../saga/spring/SagaSpringApplicationTestBase.java | 390 ------------
saga-spring/src/test/resources/data.sql | 29 -
saga-spring/src/test/resources/log4j2-test.xml | 30 -
saga-spring/src/test/resources/registry.yaml | 23 -
saga-web/pom.xml | 130 ----
.../servicecomb/saga/web/SagaWebApplication.java | 34 -
saga-web/src/main/resources/application.yaml | 29 -
saga-web/src/main/resources/microservice.yaml | 31 -
saga-web/src/main/resources/static/css/request.css | 66 --
saga-web/src/main/resources/static/css/style.css | 41 --
saga-web/src/main/resources/static/detail.html | 174 ------
saga-web/src/main/resources/static/index.html | 31 -
saga-web/src/main/resources/static/js/date.js | 660 --------------------
saga-web/src/main/resources/static/js/request.js | 294 ---------
saga-web/src/main/resources/static/js/table.js | 128 ----
saga-web/src/main/resources/static/request.html | 232 -------
saga-web/src/main/resources/static/result.html | 67 --
transports/pom.xml | 39 --
transports/transport-httpclient-spring/pom.xml | 80 ---
.../saga/transports/HttpClientTransportConfig.java | 40 --
.../src/main/resources/META-INF/spring.factories | 19 -
.../saga/transports/RestTransportTest.java | 123 ----
.../src/test/resources/log4j2.xml | 30 -
transports/transport-httpclient/pom.xml | 63 --
.../transports/httpclient/HttpClientTransport.java | 121 ----
.../httpclient/HttpClientTransportTest.java | 192 ------
.../src/test/resources/log4j2.xml | 30 -
transports/transport-resttemplate/pom.xml | 71 ---
.../resttemplate/RestTemplateTransport.java | 121 ----
260 files changed, 4 insertions(+), 20094 deletions(-)
diff --git a/docs/api/api.md b/docs/api/api.md
deleted file mode 100755
index e0a9e8f..0000000
--- a/docs/api/api.md
+++ /dev/null
@@ -1,168 +0,0 @@
-# Saga API
-### Post transaction and compensation requests to Saga
-```
-POST /requests
-```
-
-#### Description
-
-1. Define requests in order and recovery policy by JSON format as below,put them to body.
-```
-{
- "policy": "",
- "requests": [
- {
- "id": "",
- "type": "",
- "serviceName": "",
- "parents": [
-
- ],
- "transaction": {
- "method": "",
- "path": "",
- "params": {
-
- }
- },
- "compensation": {
- "method": "",
- "path": "",
- "params": {
-
- }
- }
- }
- ]
-}
-```
-JSON parameters:
-- policy - support `BackwardRecovery` or `ForwardRecovery`.
-- requests - transactions array.
- - id - request id. It should be unique among this collection of requests.
- - type - support `rest` for now.
- - serviceName - user-defined service name.
- - parents - request ids. It means this request is only executed after all requests in the parents field are completed.
- - transaction - user-defined transaction that executed by the Saga.
- - method - user-defined, HTTP method.
- - path - user-defined, HTTP path.
- - params - support `form`,`json`,`body`,`query`.
- - compensation - user-defined compensation that executed by the Saga.
- - method - user-defined, HTTP method.
- - path - user-defined, HTTP path.
- - params - support `form`,`json`,`body`,`query`.
-
-2. Set content type to `text/plain`.
-
-3. Send them to Saga service.
-
-#### Example request
-```
-curl -XPOST -H "Content-Type: text/plain" -d @./request.json http://<docker.host.ip:saga.port>/requests
-```
-
-#### Example response
-```
-success
-```
-
-#### Status codes
-- **200** – no error
-- **400** – bad parameter
-- **500** – server error
-
-
-### Get all the Saga events
-```
-GET /events
-```
-
-#### Description
-Get all the Saga events.
-
-#### Example request
-```
-curl -XGET http://<docker.host.ip:saga.port>/events
-```
-
-#### Example response
-```
-{
- "88658e73-eff5-4d31-887e-019201d6b560": [
- {
- "id": 1,
- "sagaId": "88658e73-eff5-4d31-887e-019201d6b560",
- "creationTime": "2017-09-15T01:15:40Z",
- "type": "SagaStartedEvent",
- "contentJson": "{\"policy\": \"BackwardRecovery\", \"requests\": [{\"id\": \"request-car\", \"type\": \"rest\", \"serviceName\": \"car-rental-service\", \"transaction\": {\"path\": \"/rentals\", \"method\": \"post\", \"params\": {\"form\": {\"customerId\": \"mike\"}}}, \"compensation\": {\"path\": \"/rentals\", \"method\": \"put\", \"params\": {\"form\": {\"customerId\": \"mike\"}}}}, {\"id\": \"request-hotel\", \"type\": \"rest\", \"serviceName\": \"hotel-reservation-service [...]
- },
- {
- "id": 2,
- "sagaId": "88658e73-eff5-4d31-887e-019201d6b560",
- "creationTime": "2017-09-15T01:15:40Z",
- "type": "TransactionStartedEvent",
- "contentJson": "{\"id\": \"request-flight\", \"type\": \"rest\", \"parents\": [], \"fallback\": {\"type\": \"NOP\"}, \"serviceName\": \"flight-booking-service\", \"transaction\": {\"path\": \"/bookings\", \"method\": \"post\", \"params\": {\"form\": {\"customerId\": \"mike\"}}}, \"compensation\": {\"path\": \"/bookings\", \"method\": \"put\", \"params\": {\"form\": {\"customerId\": \"mike\"}}, \"retries\": 3}}"
- },
- {
- "id": 3,
- "sagaId": "88658e73-eff5-4d31-887e-019201d6b560",
- "creationTime": "2017-09-15T01:15:40Z",
- "type": "TransactionStartedEvent",
- "contentJson": "{\"id\": \"request-car\", \"type\": \"rest\", \"parents\": [], \"fallback\": {\"type\": \"NOP\"}, \"serviceName\": \"car-rental-service\", \"transaction\": {\"path\": \"/rentals\", \"method\": \"post\", \"params\": {\"form\": {\"customerId\": \"mike\"}}}, \"compensation\": {\"path\": \"/rentals\", \"method\": \"put\", \"params\": {\"form\": {\"customerId\": \"mike\"}}, \"retries\": 3}}"
- },
- {
- "id": 4,
- "sagaId": "88658e73-eff5-4d31-887e-019201d6b560",
- "creationTime": "2017-09-15T01:15:40Z",
- "type": "TransactionStartedEvent",
- "contentJson": "{\"id\": \"request-hotel\", \"type\": \"rest\", \"parents\": [], \"fallback\": {\"type\": \"NOP\"}, \"serviceName\": \"hotel-reservation-service\", \"transaction\": {\"path\": \"/reservations\", \"method\": \"post\", \"params\": {\"form\": {\"customerId\": \"mike\"}}}, \"compensation\": {\"path\": \"/reservations\", \"method\": \"put\", \"params\": {\"form\": {\"customerId\": \"mike\"}}, \"retries\": 3}}"
- },
- {
- "id": 5,
- "sagaId": "88658e73-eff5-4d31-887e-019201d6b560",
- "creationTime": "2017-09-15T01:15:40Z",
- "type": "TransactionEndedEvent",
- "contentJson": "{\"request\": {\"id\": \"request-flight\", \"type\": \"rest\", \"parents\": [], \"fallback\": {\"type\": \"NOP\"}, \"serviceName\": \"flight-booking-service\", \"transaction\": {\"path\": \"/bookings\", \"method\": \"post\", \"params\": {\"form\": {\"customerId\": \"mike\"}}}, \"compensation\": {\"path\": \"/bookings\", \"method\": \"put\", \"params\": {\"form\": {\"customerId\": \"mike\"}}, \"retries\": 3}}, \"response\": {\"body\": \"{\\n \\\"statusCode\\\" [...]
- },
- {
- "id": 6,
- "sagaId": "88658e73-eff5-4d31-887e-019201d6b560",
- "creationTime": "2017-09-15T01:15:40Z",
- "type": "TransactionEndedEvent",
- "contentJson": "{\"request\": {\"id\": \"request-hotel\", \"type\": \"rest\", \"parents\": [], \"fallback\": {\"type\": \"NOP\"}, \"serviceName\": \"hotel-reservation-service\", \"transaction\": {\"path\": \"/reservations\", \"method\": \"post\", \"params\": {\"form\": {\"customerId\": \"mike\"}}}, \"compensation\": {\"path\": \"/reservations\", \"method\": \"put\", \"params\": {\"form\": {\"customerId\": \"mike\"}}, \"retries\": 3}}, \"response\": {\"body\": \"{\\n \\\"stat [...]
- },
- {
- "id": 7,
- "sagaId": "88658e73-eff5-4d31-887e-019201d6b560",
- "creationTime": "2017-09-15T01:15:41Z",
- "type": "TransactionEndedEvent",
- "contentJson": "{\"request\": {\"id\": \"request-car\", \"type\": \"rest\", \"parents\": [], \"fallback\": {\"type\": \"NOP\"}, \"serviceName\": \"car-rental-service\", \"transaction\": {\"path\": \"/rentals\", \"method\": \"post\", \"params\": {\"form\": {\"customerId\": \"mike\"}}}, \"compensation\": {\"path\": \"/rentals\", \"method\": \"put\", \"params\": {\"form\": {\"customerId\": \"mike\"}}, \"retries\": 3}}, \"response\": {\"body\": \"{\\n \\\"statusCode\\\": 200,\\n [...]
- },
- {
- "id": 8,
- "sagaId": "88658e73-eff5-4d31-887e-019201d6b560",
- "creationTime": "2017-09-15T01:15:41Z",
- "type": "TransactionStartedEvent",
- "contentJson": "{\"id\": \"request-payment\", \"type\": \"rest\", \"parents\": [\"request-car\", \"request-flight\", \"request-hotel\"], \"fallback\": {\"type\": \"NOP\"}, \"serviceName\": \"payment-service\", \"transaction\": {\"path\": \"/payments\", \"method\": \"post\", \"params\": {\"form\": {\"customerId\": \"mike\"}}}, \"compensation\": {\"path\": \"/payments\", \"method\": \"put\", \"params\": {\"form\": {\"customerId\": \"mike\"}}, \"retries\": 3}}"
- },
- {
- "id": 9,
- "sagaId": "88658e73-eff5-4d31-887e-019201d6b560",
- "creationTime": "2017-09-15T01:15:41Z",
- "type": "TransactionEndedEvent",
- "contentJson": "{\"request\": {\"id\": \"request-payment\", \"type\": \"rest\", \"parents\": [\"request-car\", \"request-flight\", \"request-hotel\"], \"fallback\": {\"type\": \"NOP\"}, \"serviceName\": \"payment-service\", \"transaction\": {\"path\": \"/payments\", \"method\": \"post\", \"params\": {\"form\": {\"customerId\": \"mike\"}}}, \"compensation\": {\"path\": \"/payments\", \"method\": \"put\", \"params\": {\"form\": {\"customerId\": \"mike\"}}, \"retries\": 3}}, \"r [...]
- },
- {
- "id": 10,
- "sagaId": "88658e73-eff5-4d31-887e-019201d6b560",
- "creationTime": "2017-09-15T01:15:41Z",
- "type": "SagaEndedEvent",
- "contentJson": "{}"
- }
- ]
-}
-```
-
-#### Status codes
-- **200** – no error
-
diff --git a/docs/old_saga.md b/docs/old_saga.md
deleted file mode 100755
index 2b79d22..0000000
--- a/docs/old_saga.md
+++ /dev/null
@@ -1,53 +0,0 @@
-# Previous Saga's Documentation
-## Major Architecture of Saga
-* saga-core(transaction and compensation handling logic)
-* saga-format(data serialization and deserialization)
-* saga-transports(communication protocol implementation such as rest or rpc in the future)
-* saga-discovery(service discovery)
-* saga-spring(restful service framework)
-
-![Saga](static_files/saga.png)
-
-## Prerequisites
-You will need:
-1. [Oracle JDK 1.8+][jdk]
-2. [Maven 3.x][maven]
-3. [Docker][docker]
-4. [PostgreSQL][postgres]
-5. [Service Center(optional)][service_center]
-6. [Docker compose(optional)][docker_compose]
-7. [Docker machine(optional)][docker_machine]
-
-[jdk]: http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
-[maven]: https://maven.apache.org/install.html
-[docker]: https://www.docker.com/get-docker
-[postgres]: https://www.postgresql.org/download/
-[service_center]: https://github.com/apache/incubator-servicecomb-service-center
-[docker_compose]: https://docs.docker.com/compose/install/
-[docker_machine]: https://docs.docker.com/machine/install-machine/
-
-## Building
-Download the source code.
-```
-git clone https://github.com/apache/incubator-servicecomb-saga.git
-```
-
-Enter the Saga root directory,build Saga project by maven command and generate a docker image named saga-spring in local.
-```
-mvn package -DskipTests -Pdocker
-```
-
-## Run Services
-A `docker-compose.yaml` file is provided to start Saga services and its dependencies(Service center and Mysql) as docker containers.
-User also can configure specified Service center or Mysql in `docker-compose.yaml`.
-
-Enter the Saga root directory, run all service images using command,
-```
-docker-compose up
-```
-
-## Reference API
-See [Saga API](docs/api/api.md) for details.
-
-## Example
-See [Saga demo](https://github.com/apache/incubator-servicecomb-saga/tree/master/saga-demo) for details.
diff --git a/integration-tests/coverage-aggregate/pom.xml b/integration-tests/coverage-aggregate/pom.xml
index a156600..cbb67ad 100644
--- a/integration-tests/coverage-aggregate/pom.xml
+++ b/integration-tests/coverage-aggregate/pom.xml
@@ -31,26 +31,6 @@
<dependencies>
<dependency>
<groupId>org.apache.servicecomb.saga</groupId>
- <artifactId>saga-core</artifactId>
- </dependency>
- <dependency>
- <groupId>org.apache.servicecomb.saga</groupId>
- <artifactId>saga-format</artifactId>
- </dependency>
- <dependency>
- <groupId>org.apache.servicecomb.saga</groupId>
- <artifactId>saga-spring</artifactId>
- </dependency>
- <dependency>
- <groupId>org.apache.servicecomb.saga.transports</groupId>
- <artifactId>transport-httpclient</artifactId>
- </dependency>
- <dependency>
- <groupId>org.apache.servicecomb.saga.discovery</groupId>
- <artifactId>saga-discovery-servicecenter</artifactId>
- </dependency>
- <dependency>
- <groupId>org.apache.servicecomb.saga</groupId>
<artifactId>omega-context</artifactId>
</dependency>
<dependency>
diff --git a/pom.xml b/pom.xml
index 85e9405..9207e14 100755
--- a/pom.xml
+++ b/pom.xml
@@ -31,19 +31,12 @@
<version>0.0.3-SNAPSHOT</version>
<modules>
- <module>saga-core</module>
- <module>transports</module>
- <module>saga-spring</module>
<module>docker-build-config</module>
- <module>saga-format</module>
- <module>saga-discovery</module>
- <module>saga-web</module>
<module>omega</module>
<module>alpha</module>
<module>pack-contracts</module>
<module>pack-common</module>
<module>integration-tests</module>
- <module>saga-persistence</module>
</modules>
<properties>
@@ -123,41 +116,6 @@
<dependencies>
<dependency>
<groupId>org.apache.servicecomb.saga</groupId>
- <artifactId>saga-core</artifactId>
- <version>0.0.3-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.apache.servicecomb.saga</groupId>
- <artifactId>saga-format</artifactId>
- <version>0.0.3-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.apache.servicecomb.saga</groupId>
- <artifactId>saga-spring</artifactId>
- <version>0.0.3-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.apache.servicecomb.saga.transports</groupId>
- <artifactId>transport-httpclient</artifactId>
- <version>0.0.3-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.apache.servicecomb.saga.transports</groupId>
- <artifactId>transport-httpclient-spring</artifactId>
- <version>0.0.3-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.apache.servicecomb.saga.transports</groupId>
- <artifactId>transport-resttemplate</artifactId>
- <version>0.0.3-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.apache.servicecomb.saga.discovery</groupId>
- <artifactId>saga-discovery-servicecenter</artifactId>
- <version>0.0.3-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.apache.servicecomb.saga</groupId>
<artifactId>omega-context</artifactId>
<version>0.0.3-SNAPSHOT</version>
</dependency>
@@ -212,10 +170,10 @@
<version>0.0.3-SNAPSHOT</version>
</dependency>
<dependency>
- <groupId>org.apache.servicecomb.saga</groupId>
- <artifactId>saga-persistence-jpa</artifactId>
- <version>0.0.3-SNAPSHOT</version>
- </dependency>
+ <groupId>org.apache.servicecomb.saga</groupId>
+ <artifactId>saga-persistence-jpa</artifactId>
+ <version>0.0.3-SNAPSHOT</version>
+ </dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
diff --git a/saga-core/pom.xml b/saga-core/pom.xml
deleted file mode 100644
index f9ba426..0000000
--- a/saga-core/pom.xml
+++ /dev/null
@@ -1,103 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Licensed to the Apache Software Foundation (ASF) under one or more
- ~ contributor license agreements. See the NOTICE file distributed with
- ~ this work for additional information regarding copyright ownership.
- ~ The ASF licenses this file to You under the Apache License, Version 2.0
- ~ (the "License"); you may not use this file except in compliance with
- ~ the License. You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <parent>
- <artifactId>saga</artifactId>
- <groupId>org.apache.servicecomb.saga</groupId>
- <version>0.0.3-SNAPSHOT</version>
- </parent>
- <modelVersion>4.0.0</modelVersion>
-
- <artifactId>saga-core</artifactId>
- <name>Saga::Core</name>
-
- <dependencies>
- <dependency>
- <groupId>com.lmax</groupId>
- <artifactId>disruptor</artifactId>
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-api</artifactId>
- </dependency>
- <dependency>
- <groupId>org.apache.logging.log4j</groupId>
- <artifactId>log4j-slf4j-impl</artifactId>
- </dependency>
- <dependency>
- <groupId>org.apache.logging.log4j</groupId>
- <artifactId>log4j-api</artifactId>
- </dependency>
- <dependency>
- <groupId>org.apache.logging.log4j</groupId>
- <artifactId>log4j-core</artifactId>
- </dependency>
- <dependency>
- <groupId>com.typesafe.akka</groupId>
- <artifactId>akka-actor_2.12</artifactId>
- </dependency>
- <dependency>
- <groupId>com.typesafe.akka</groupId>
- <artifactId>akka-slf4j_2.12</artifactId>
- </dependency>
- <dependency>
- <groupId>io.kamon</groupId>
- <artifactId>kamon-core_2.12</artifactId>
- </dependency>
- <dependency>
- <groupId>io.kamon</groupId>
- <artifactId>kamon-annotation_2.12</artifactId>
- </dependency>
-
- <!-- test dependencies -->
- <dependency>
- <groupId>com.typesafe.akka</groupId>
- <artifactId>akka-testkit_2.12</artifactId>
- </dependency>
- <dependency>
- <groupId>org.scalatest</groupId>
- <artifactId>scalatest_2.12</artifactId>
- </dependency>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- </dependency>
- <dependency>
- <groupId>org.hamcrest</groupId>
- <artifactId>hamcrest-all</artifactId>
- </dependency>
- <dependency>
- <groupId>org.mockito</groupId>
- <artifactId>mockito-core</artifactId>
- </dependency>
- <dependency>
- <groupId>org.apache.commons</groupId>
- <artifactId>commons-lang3</artifactId>
- </dependency>
- <dependency>
- <groupId>org.awaitility</groupId>
- <artifactId>awaitility</artifactId>
- </dependency>
- <dependency>
- <groupId>com.github.seanyinx</groupId>
- <artifactId>unit-scaffolding</artifactId>
- </dependency>
- </dependencies>
-
-</project>
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/BackwardRecovery.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/BackwardRecovery.java
deleted file mode 100644
index e46de2f..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/BackwardRecovery.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-import java.lang.invoke.MethodHandles;
-import kamon.annotation.EnableKamon;
-import kamon.annotation.Segment;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-
-@EnableKamon
-public class BackwardRecovery implements RecoveryPolicy {
-
- private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
-
- @Segment(name = "backwardPolicy", category = "application", library = "kamon")
- @Override
- public SagaResponse apply(SagaTask task, SagaRequest request, SagaResponse parentResponse) {
- try {
- return request.transaction().send(request.serviceName(), parentResponse);
- } catch (Exception e) {
- log.error("Applying {} policy due to failure in transaction {} of service {}",
- description(),
- request.transaction(),
- request.serviceName(),
- e
- );
-
- task.abort(request, e);
- throw e;
- }
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/Compensation.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/Compensation.java
deleted file mode 100644
index f642011..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/Compensation.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-public interface Compensation extends Operation {
-
- Compensation SAGA_START_COMPENSATION = new Compensation() {
- };
-
- Compensation SAGA_END_COMPENSATION = new Compensation() {
- };
-
- int DEFAULT_RETRIES = 3;
-
- default int retries() {
- return DEFAULT_RETRIES;
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/CompensationTaskConsumer.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/CompensationTaskConsumer.java
deleted file mode 100644
index 736c34d..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/CompensationTaskConsumer.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-import java.lang.invoke.MethodHandles;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.Map;
-
-import org.apache.servicecomb.saga.core.dag.Node;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-class CompensationTaskConsumer implements TaskConsumer {
-
- private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
- private final Map<String, SagaTask> tasks;
- private final SagaContext sagaContext;
-
- CompensationTaskConsumer(Map<String, SagaTask> tasks, SagaContext sagaContext) {
- this.tasks = tasks;
- this.sagaContext = sagaContext;
- }
-
- @Override
- public void consume(Collection<Node<SagaRequest>> nodes) {
- for (Node<SagaRequest> node : nodes) {
- SagaRequest request = node.value();
-
- if (sagaContext.isTransactionCompleted(request)) {
- log.info("Starting request {} id={}", request.serviceName(), request.id());
- tasks.get(request.task()).compensate(request);
- log.info("Completed request {} id={}", request.serviceName(), request.id());
- }
- }
- }
-
- @Override
- public boolean replay(Collection<Node<SagaRequest>> nodes) {
-
- for (Iterator<Node<SagaRequest>> iterator = nodes.iterator(); iterator.hasNext(); ) {
- SagaRequest request = iterator.next().value();
- if (sagaContext.isCompensationCompleted(request)) {
- log.info("Skipped completed compensation id={} operation={} while replay", request.id(), request.transaction());
- iterator.remove();
- } else if (!sagaContext.isTransactionCompleted(request)) {
- // this transaction never started
- log.info("Skipped pending transaction id={} operation={} while replay", request.id(), request.transaction());
- iterator.remove();
- }
- }
- return !nodes.isEmpty();
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/CompositeSagaLog.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/CompositeSagaLog.java
deleted file mode 100644
index 017129a..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/CompositeSagaLog.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-import kamon.annotation.EnableKamon;
-import kamon.annotation.Segment;
-
-@EnableKamon
-class CompositeSagaLog implements SagaLog {
-
- private final SagaLog embedded;
- private final PersistentLog persistent;
-
- CompositeSagaLog(SagaLog embedded, PersistentLog persistent) {
- this.embedded = embedded;
- this.persistent = persistent;
- }
-
- @Segment(name = "compositeSagaLog", category = "application", library = "kamon")
- @Override
- public void offer(SagaEvent sagaEvent) {
- persistent.offer(sagaEvent);
- embedded.offer(sagaEvent);
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/CompositeSagaResponse.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/CompositeSagaResponse.java
deleted file mode 100644
index 02ab48c..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/CompositeSagaResponse.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-import java.util.Collection;
-import java.util.Optional;
-
-public class CompositeSagaResponse implements SagaResponse {
- private final Collection<SagaResponse> responses;
-
- public CompositeSagaResponse(Collection<SagaResponse> responses) {
- this.responses = responses;
- }
-
- @Override
- public boolean succeeded() {
- return responses.stream().allMatch(SagaResponse::succeeded);
- }
-
- @Override
- public String body() {
- Optional<String> reduce = responses.stream()
- .map(SagaResponse::body)
- .reduce((a, b) -> a + ", " + b)
- .map(combined -> "[" + combined + "]");
-
- return reduce.orElse("{}");
- }
-
- public Collection<SagaResponse> responses() {
- return responses;
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/Descriptive.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/Descriptive.java
deleted file mode 100644
index bd367af..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/Descriptive.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-interface Descriptive {
-
- default String description() {
- return getClass().getSimpleName();
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/EventContext.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/EventContext.java
deleted file mode 100644
index 79b0c3e..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/EventContext.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-public interface EventContext {
- void beginTransaction(SagaRequest request);
-
- void endTransaction(SagaRequest request, SagaResponse response);
-
- void abortTransaction(SagaRequest request, SagaResponse response);
-
- void compensateTransaction(SagaRequest request, SagaResponse response);
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/EventEnvelope.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/EventEnvelope.java
deleted file mode 100644
index 9283b33..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/EventEnvelope.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-public class EventEnvelope {
-
- public final long id;
- public final long timestamp;
- public final SagaEvent event;
-
- public EventEnvelope(long id, SagaEvent event) {
- this.id = id;
- this.event = event;
- this.timestamp = System.currentTimeMillis();
- }
-
- // TODO: 8/21/2017 this class seems to be useless to saga
- public EventEnvelope(long id, long timestamp, SagaEvent event) {
- this.id = id;
- this.timestamp = timestamp;
- this.event = event;
- }
-
- @Override
- public String toString() {
- return "EventEnvelope{" +
- "id=" + id +
- ", timestamp=" + timestamp +
- ", event={" + event +
- "}}";
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/EventStore.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/EventStore.java
deleted file mode 100644
index 7b7e6e2..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/EventStore.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-public interface EventStore extends SagaLog, Iterable<SagaEvent> {
-
- void populate(Iterable<EventEnvelope> events);
-
- long size();
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/FailedSagaResponse.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/FailedSagaResponse.java
deleted file mode 100644
index 15d1701..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/FailedSagaResponse.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-
-public class FailedSagaResponse implements SagaResponse {
-
- private final String body;
-
- public FailedSagaResponse(String body) {
- this.body = body;
- }
-
- public FailedSagaResponse(Throwable e) {
- this.body = stackTrace(e);
- }
-
- @Override
- public boolean succeeded() {
- return false;
- }
-
- @Override
- public String body() {
- return body;
- }
-
- private String stackTrace(Throwable e) {
- StringWriter writer = new StringWriter();
- e.printStackTrace(new PrintWriter(writer));
- return writer.toString();
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/Fallback.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/Fallback.java
deleted file mode 100644
index fca68a0..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/Fallback.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-public interface Fallback extends Operation {
-
- Fallback NOP_FALLBACK = () -> TYPE_NOP;
-
- String type();
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/FallbackPolicy.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/FallbackPolicy.java
deleted file mode 100644
index 48ad67d..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/FallbackPolicy.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-import java.lang.invoke.MethodHandles;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class FallbackPolicy {
- private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
-
- private final int retryDelay;
-
- public FallbackPolicy(int retryDelay) {
- this.retryDelay = retryDelay;
- }
-
- public SagaResponse apply(String address, Compensation compensation, Fallback fallback) {
- for (int i = 0; isRetryable(i, compensation) && !isInterrupted(); i++) {
- try {
- return compensation.send(address);
- } catch (Exception e) {
- log.error("Failed to send compensation to {}", address, e);
- sleep(retryDelay);
- }
- }
-
- log.warn("Falling back after {} failures sending compensation to {}", compensation.retries(), address);
- return fallback.send(address);
- }
-
- private boolean isRetryable(int i, Compensation compensation) {
- return compensation.retries() < 0 || i <= compensation.retries();
- }
-
- private boolean isInterrupted() {
- return Thread.currentThread().isInterrupted();
- }
-
- private void sleep(int delay) {
- try {
- Thread.sleep(delay);
- } catch (InterruptedException ignored) {
- Thread.currentThread().interrupt();
- }
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/ForwardRecovery.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/ForwardRecovery.java
deleted file mode 100644
index c783990..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/ForwardRecovery.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-import java.lang.invoke.MethodHandles;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class ForwardRecovery implements RecoveryPolicy {
-
- private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
-
- @Override
- public SagaResponse apply(SagaTask task, SagaRequest request, SagaResponse parentResponse) {
- try {
- do {
- try {
- return request.transaction().send(request.serviceName(), parentResponse);
- } catch (Exception e) {
- log.error("Applying {} policy due to failure in transaction {} of service {}",
- description(),
- request.transaction(),
- request.serviceName(),
- e
- );
- Thread.sleep(request.failRetryDelayMilliseconds());
- }
- } while (true);
- } catch (InterruptedException ignored) {
- log.warn("Applying {} interrupted in transaction {} of service {}",
- description(),
- request.transaction(),
- request.serviceName(),
- ignored);
- throw new TransactionFailedException(ignored);
- }
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/GraphBasedSaga.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/GraphBasedSaga.java
deleted file mode 100644
index f4544e3..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/GraphBasedSaga.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-import java.lang.invoke.MethodHandles;
-import java.util.Map;
-import java.util.concurrent.Executor;
-import java.util.concurrent.ExecutorCompletionService;
-import java.util.concurrent.Executors;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.apache.servicecomb.saga.core.dag.ByLevelTraveller;
-import org.apache.servicecomb.saga.core.dag.FromLeafTraversalDirection;
-import org.apache.servicecomb.saga.core.dag.FromRootTraversalDirection;
-import org.apache.servicecomb.saga.core.dag.SingleLeafDirectedAcyclicGraph;
-import org.apache.servicecomb.saga.core.dag.TraversalDirection;
-import kamon.annotation.EnableKamon;
-import kamon.annotation.Segment;
-
-@EnableKamon
-public class GraphBasedSaga implements Saga {
-
- private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
-
- private final EventStore eventStore;
- private final Map<String, SagaTask> tasks;
-
- private final TaskRunner transactionTaskRunner;
- private final TaskRunner compensationTaskRunner;
- private final SagaContext sagaContext;
- private volatile SagaState currentTaskRunner;
-
- GraphBasedSaga(EventStore eventStore,
- Map<String, SagaTask> tasks,
- SagaContext sagaContext,
- SingleLeafDirectedAcyclicGraph<SagaRequest> sagaTaskGraph) {
-
- this(eventStore, Executors.newFixedThreadPool(5), tasks, sagaContext, sagaTaskGraph);
- }
-
- public GraphBasedSaga(EventStore eventStore,
- Executor executor,
- Map<String, SagaTask> tasks,
- SagaContext sagaContext,
- SingleLeafDirectedAcyclicGraph<SagaRequest> sagaTaskGraph) {
-
- this.eventStore = eventStore;
- this.tasks = tasks;
-
- this.transactionTaskRunner = new TaskRunner(
- traveller(sagaTaskGraph, new FromRootTraversalDirection<>()),
- new TransactionTaskConsumer(
- tasks,
- sagaContext,
- new ExecutorCompletionService<>(executor)));
-
- this.sagaContext = sagaContext;
- this.compensationTaskRunner = new TaskRunner(
- traveller(sagaTaskGraph, new FromLeafTraversalDirection<>()),
- new CompensationTaskConsumer(tasks, sagaContext));
-
- currentTaskRunner = transactionTaskRunner;
- }
-
- @Override
- @Segment(name = "runSaga", category = "application", library = "kamon")
- public SagaResponse run() {
- SagaResponse response = SagaResponse.EMPTY_RESPONSE;
- log.info("Starting Saga");
- do {
- try {
- currentTaskRunner.run();
- } catch (TransactionFailedException e) {
- response = new FailedSagaResponse(e);
- log.error("Failed to run operation", e);
- currentTaskRunner = compensationTaskRunner;
-
- sagaContext.handleHangingTransactions(request -> {
- tasks.get(request.task()).commit(request, sagaContext.responseOf(request.parents()));
- tasks.get(request.task()).compensate(request);
- });
- }
- } while (currentTaskRunner.hasNext());
- log.info("Completed Saga");
- return response;
- }
-
- @Override
- public void play() {
- log.info("Start playing events");
- gatherEvents(eventStore);
-
- transactionTaskRunner.replay();
-
- if (sagaContext.isCompensationStarted()) {
- currentTaskRunner = compensationTaskRunner;
- compensationTaskRunner.replay();
- }
-
- log.info("Completed playing events");
- }
-
- private void gatherEvents(Iterable<SagaEvent> events) {
- for (SagaEvent event : events) {
- event.gatherTo(sagaContext);
- }
- }
-
- private ByLevelTraveller<SagaRequest> traveller(
- SingleLeafDirectedAcyclicGraph<SagaRequest> sagaTaskGraph,
- TraversalDirection<SagaRequest> traversalDirection) {
-
- return new ByLevelTraveller<>(sagaTaskGraph, traversalDirection);
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/IdGenerator.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/IdGenerator.java
deleted file mode 100644
index 2add260..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/IdGenerator.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-import java.io.Serializable;
-
-public interface IdGenerator<T extends Serializable> {
-
- T nextId();
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/LoggingRecoveryPolicy.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/LoggingRecoveryPolicy.java
deleted file mode 100644
index 9173eca..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/LoggingRecoveryPolicy.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-import java.lang.invoke.MethodHandles;
-import kamon.annotation.EnableKamon;
-import kamon.annotation.Segment;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-
-
-@EnableKamon
-public class LoggingRecoveryPolicy implements RecoveryPolicy {
- private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
-
- private final RecoveryPolicy recoveryPolicy;
-
- public LoggingRecoveryPolicy(RecoveryPolicy recoveryPolicy) {
- this.recoveryPolicy = recoveryPolicy;
- }
-
- @Segment(name = "loggingPolicy", category = "application", library = "kamon")
- @Override
- public SagaResponse apply(SagaTask task, SagaRequest request, SagaResponse parentResponse) {
- log.info("Starting request id={} for service {}", request.id(), request.serviceName());
- SagaResponse response = recoveryPolicy.apply(task, request, parentResponse);
- log.info("Completed request id={} for service {}", request.id(), request.serviceName());
- return response;
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/LongIdGenerator.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/LongIdGenerator.java
deleted file mode 100644
index 6b16075..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/LongIdGenerator.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-import java.util.concurrent.atomic.AtomicLong;
-
-public class LongIdGenerator implements IdGenerator<Long> {
-
- private final AtomicLong atomicLong = new AtomicLong();
-
- @Override
- public Long nextId() {
- return atomicLong.incrementAndGet();
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/NoOpSagaRequest.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/NoOpSagaRequest.java
deleted file mode 100644
index 56ad05e..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/NoOpSagaRequest.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-import static org.apache.servicecomb.saga.core.Compensation.SAGA_END_COMPENSATION;
-import static org.apache.servicecomb.saga.core.Compensation.SAGA_START_COMPENSATION;
-import static org.apache.servicecomb.saga.core.Operation.TYPE_NOP;
-import static org.apache.servicecomb.saga.core.SagaTask.SAGA_END_TASK;
-import static org.apache.servicecomb.saga.core.SagaTask.SAGA_START_TASK;
-import static org.apache.servicecomb.saga.core.Transaction.SAGA_END_TRANSACTION;
-import static org.apache.servicecomb.saga.core.Transaction.SAGA_START_TRANSACTION;
-
-import java.util.Arrays;
-
-public class NoOpSagaRequest implements SagaRequest {
-
- public static final SagaRequest SAGA_START_REQUEST = new NoOpSagaRequest(
- "saga-start",
- SAGA_START_TRANSACTION,
- SAGA_START_COMPENSATION,
- SAGA_START_TASK);
-
- public static final SagaRequest SAGA_END_REQUEST = new NoOpSagaRequest(
- "saga-end",
- SAGA_END_TRANSACTION,
- SAGA_END_COMPENSATION,
- SAGA_END_TASK);
-
- private final String id;
- private final Transaction transaction;
- private final Compensation compensation;
- private final String task;
- private final String[] parents = {};
-
- private NoOpSagaRequest(String id, Transaction transaction, Compensation compensation, String task) {
- this.id = id;
- this.transaction = transaction;
- this.compensation = compensation;
- this.task = task;
- }
-
- @Override
- public Transaction transaction() {
- return transaction;
- }
-
- @Override
- public Compensation compensation() {
- return compensation;
- }
-
- @Override
- public String serviceName() {
- return "Saga";
- }
-
- @Override
- public String id() {
- return id;
- }
-
- @Override
- public String type() {
- return TYPE_NOP;
- }
-
- @Override
- public String task() {
- return task;
- }
-
- @Override
- public String[] parents() {
- return parents;
- }
-
- @Override
- public int failRetryDelayMilliseconds() {
- return 50;
- }
-
- @Override
- public String toString() {
- return "NoOpSagaRequest{" +
- "id='" + id + '\'' +
- ", transaction=" + transaction +
- ", compensation=" + compensation +
- ", task='" + task + '\'' +
- ", parents=" + Arrays.toString(parents) +
- '}';
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/Operation.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/Operation.java
deleted file mode 100644
index 13b6f8a..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/Operation.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-public interface Operation {
-
- String TYPE_NOP = "NOP";
- String TYPE_REST = "rest";
- SagaResponse SUCCESSFUL_SAGA_RESPONSE = new SuccessfulSagaResponse("success");
-
- default SagaResponse send(String address) {
- return SUCCESSFUL_SAGA_RESPONSE;
- }
-
- default SagaResponse send(String address, SagaResponse response) {
- return send(address);
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/PersistentLog.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/PersistentLog.java
deleted file mode 100644
index 26ec4bc..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/PersistentLog.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-public interface PersistentLog {
- void offer(SagaEvent sagaEvent);
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/PersistentStore.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/PersistentStore.java
deleted file mode 100644
index a7620b3..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/PersistentStore.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-import java.util.List;
-import java.util.Map;
-
-public interface PersistentStore extends PersistentLog {
-
- Map<String, List<EventEnvelope>> findPendingSagaEvents();
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/RecoveryPolicy.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/RecoveryPolicy.java
deleted file mode 100644
index c67d640..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/RecoveryPolicy.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-public interface RecoveryPolicy extends Descriptive {
-
- String SAGA_FORWARD_RECOVERY_POLICY = "ForwardRecovery";
- String SAGA_BACKWARD_RECOVERY_POLICY = "BackwardRecovery";
-
- SagaResponse apply(SagaTask task, SagaRequest request, SagaResponse parentResponse);
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/RequestProcessTask.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/RequestProcessTask.java
deleted file mode 100644
index e19c7bf..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/RequestProcessTask.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-import kamon.annotation.EnableKamon;
-import kamon.annotation.Segment;
-
-@EnableKamon
-public class RequestProcessTask implements SagaTask {
-
- private final String sagaId;
- private final SagaLog sagaLog;
- private final RecoveryPolicy recoveryPolicy;
- private final FallbackPolicy fallbackPolicy;
-
- public RequestProcessTask(
- String sagaId,
- SagaLog sagaLog,
- RecoveryPolicy recoveryPolicy,
- FallbackPolicy fallbackPolicy) {
-
- this.sagaId = sagaId;
- this.sagaLog = sagaLog;
- this.recoveryPolicy = recoveryPolicy;
- this.fallbackPolicy = fallbackPolicy;
- }
-
- @Segment(name = "commit", category = "application", library = "kamon")
- @Override
- public SagaResponse commit(SagaRequest request, SagaResponse parentResponse) {
- sagaLog.offer(new TransactionStartedEvent(sagaId, request));
-
- SagaResponse response = recoveryPolicy.apply(this, request, parentResponse);
-
- sagaLog.offer(new TransactionEndedEvent(sagaId, request, response));
- return response;
- }
-
- @Segment(name = "compensate", category = "application", library = "kamon")
- @Override
- public void compensate(SagaRequest request) {
- Compensation compensation = request.compensation();
- SagaResponse response = fallbackPolicy.apply(request.serviceName(), compensation, request.fallback());
-
- sagaLog.offer(new TransactionCompensatedEvent(sagaId, request, response));
- }
-
- @Override
- public void abort(SagaRequest request, Exception e) {
- sagaLog.offer(new TransactionAbortedEvent(sagaId, request, e));
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/RestOperation.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/RestOperation.java
deleted file mode 100644
index 5cce22d..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/RestOperation.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-import static java.util.Collections.emptyMap;
-
-import org.apache.servicecomb.saga.core.application.interpreter.RestRequestChecker;
-import java.util.Map;
-
-public class RestOperation implements Operation {
-
- private final String path;
- private final String method;
- private final Map<String, Map<String, String>> params;
-
- public RestOperation(String path, String method, Map<String, Map<String, String>> params) {
- RestRequestChecker.checkParameters(method, params);
-
- this.path = path;
- this.method = method;
- this.params = params == null? emptyMap() : params;
- }
-
- public String path() {
- return path;
- }
-
- public String method() {
- return method;
- }
-
- public Map<String, Map<String, String>> params() {
- return params;
- }
-
- @Override
- public String toString() {
- return "Operation{" +
- "path='" + path + '\'' +
- ", method='" + method + '\'' +
- ", params=" + params +
- '}';
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/Saga.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/Saga.java
deleted file mode 100644
index 44f62ea..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/Saga.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-import kamon.annotation.Segment;
-
-public interface Saga {
- @Segment(name = "runSaga", category = "application", library = "kamon")
- SagaResponse run();
-
- void play();
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaContext.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaContext.java
deleted file mode 100644
index 309be44..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaContext.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-import java.util.function.Consumer;
-
-public interface SagaContext extends EventContext {
- boolean isCompensationStarted();
-
- boolean isTransactionCompleted(SagaRequest request);
-
- boolean isCompensationCompleted(SagaRequest request);
-
- void handleHangingTransactions(Consumer<SagaRequest> consumer);
-
- SagaResponse responseOf(String requestId);
-
- boolean isChosenChild(SagaRequest request);
-
- SagaResponse responseOf(String[] parentRequestIds);
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaContextImpl.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaContextImpl.java
deleted file mode 100644
index 610ae27..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaContextImpl.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentSkipListSet;
-import java.util.function.Consumer;
-import java.util.stream.Collectors;
-
-import org.apache.servicecomb.saga.core.application.interpreter.FromJsonFormat;
-
-public class SagaContextImpl implements SagaContext {
-
- private final Map<String, SagaResponse> completedTransactions;
- private final Map<String, SagaResponse> completedCompensations;
- private final Set<String> abortedTransactions;
- private final Map<String, SagaRequest> hangingTransactions;
- private final FromJsonFormat<Set<String>> childrenExtractor;
-
- public SagaContextImpl(FromJsonFormat<Set<String>> childrenExtractor) {
- this.childrenExtractor = childrenExtractor;
- this.completedTransactions = new ConcurrentHashMap<>();
- this.completedCompensations = new HashMap<>();
- this.abortedTransactions = new ConcurrentSkipListSet<>();
- this.hangingTransactions = new ConcurrentHashMap<>();
- }
-
- @Override
- public boolean isCompensationStarted() {
- return !abortedTransactions.isEmpty() || !completedCompensations.isEmpty();
- }
-
- @Override
- public boolean isTransactionCompleted(SagaRequest request) {
- return completedTransactions.containsKey(request.id());
- }
-
- @Override
- public boolean isCompensationCompleted(SagaRequest request) {
- return completedCompensations.containsKey(request.id());
- }
-
- @Override
- public void beginTransaction(SagaRequest request) {
- hangingTransactions.put(request.id(), request);
- }
-
- @Override
- public void endTransaction(SagaRequest request, SagaResponse response) {
- completedTransactions.put(request.id(), response);
- hangingTransactions.remove(request.id());
- }
-
- @Override
- public void abortTransaction(SagaRequest request, SagaResponse response) {
- completedTransactions.remove(request.id());
- abortedTransactions.add(request.id());
- hangingTransactions.remove(request.id());
- }
-
- @Override
- public void compensateTransaction(SagaRequest request, SagaResponse response) {
- completedCompensations.put(request.id(), response);
- completedTransactions.remove(request.id());
- }
-
- @Override
- public void handleHangingTransactions(Consumer<SagaRequest> consumer) {
- for (Iterator<SagaRequest> iterator = hangingTransactions.values().iterator(); iterator.hasNext(); ) {
- consumer.accept(iterator.next());
- }
- }
-
- @Override
- public SagaResponse responseOf(String requestId) {
- return completedTransactions.getOrDefault(requestId, SagaResponse.NONE_RESPONSE);
- }
-
- private List<SagaResponse> responsesOf(String[] parentRequestIds) {
- return Arrays.stream(parentRequestIds)
- .map(this::responseOf)
- .collect(Collectors.toList());
- }
-
- @Override
- public SagaResponse responseOf(String[] parentRequestIds) {
- List<SagaResponse> responses = responsesOf(parentRequestIds);
-
- if (responses.isEmpty()) {
- return SagaResponse.EMPTY_RESPONSE;
- }
-
- if (responses.size() == 1) {
- return responses.get(0);
- }
-
- return new CompositeSagaResponse(responses);
- }
-
- @Override
- public boolean isChosenChild(SagaRequest request) {
- Set<String> chosenChildren = chosenChildrenOf(request.parents());
- return chosenChildren.isEmpty() || chosenChildren.contains(request.id());
- }
-
- private Set<String> chosenChildrenOf(String[] parentRequestIds) {
- return Arrays.stream(parentRequestIds)
- .map(this::responseOf)
- .flatMap(sagaResponse -> childrenExtractor.fromJson(sagaResponse.body()).stream())
- .collect(Collectors.toSet());
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaDefinition.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaDefinition.java
deleted file mode 100644
index 406c8df..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaDefinition.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-public interface SagaDefinition {
-
- RecoveryPolicy policy();
-
- SagaRequest[] requests();
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaEndTask.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaEndTask.java
deleted file mode 100644
index 69daba7..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaEndTask.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-import kamon.annotation.EnableKamon;
-import kamon.annotation.Segment;
-
-@EnableKamon
-public class SagaEndTask implements SagaTask {
-
- private final String sagaId;
- private final SagaLog sagaLog;
-
- public SagaEndTask(String sagaId, SagaLog sagaLog) {
- this.sagaId = sagaId;
- this.sagaLog = sagaLog;
- }
-
- @Segment(name = "endTaskCommit", category = "application", library = "kamon")
- @Override
- public SagaResponse commit(SagaRequest request, SagaResponse parentResponse) {
- sagaLog.offer(new SagaEndedEvent(sagaId, request));
- return SagaResponse.EMPTY_RESPONSE;
- }
-
- @Override
- public void compensate(SagaRequest request) {
- }
-
- @Override
- public void abort(SagaRequest request, Exception e) {
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaEndedEvent.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaEndedEvent.java
deleted file mode 100644
index c6f4f9f..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaEndedEvent.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-public class SagaEndedEvent extends SagaEvent {
-
- public SagaEndedEvent(String sagaId, SagaRequest sagaTask) {
- super(sagaId, sagaTask);
- }
-
- @Override
- public void gatherTo(EventContext sagaContext) {
- sagaContext.endTransaction(payload(), SagaResponse.EMPTY_RESPONSE);
- }
-
- @Override
- public String toString() {
- return "SagaEndedEvent{id="
- + payload().id()
- + ", sagaId=" + sagaId
- + "}";
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaEvent.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaEvent.java
deleted file mode 100644
index ceb0ebe..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaEvent.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-public abstract class SagaEvent implements Descriptive {
-
- public final String sagaId;
- private final SagaRequest payload;
-
- public SagaEvent(String sagaId, SagaRequest payload) {
- this.sagaId = sagaId;
- this.payload = payload;
- }
-
- public SagaRequest payload() {
- return payload;
- }
-
- public abstract void gatherTo(EventContext sagaContext);
-
- public String json(ToJsonFormat toJsonFormat) {
- return "{}";
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaException.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaException.java
deleted file mode 100644
index 49ce989..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaException.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-public class SagaException extends RuntimeException {
-
- public SagaException(String cause, Throwable e) {
- super(cause, e);
- }
-
- public SagaException(String cause) {
- super(cause);
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaLog.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaLog.java
deleted file mode 100644
index 2e07b9f..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaLog.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-public interface SagaLog extends PersistentLog {
-
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaRequest.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaRequest.java
deleted file mode 100644
index 337abdd..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaRequest.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-import static org.apache.servicecomb.saga.core.Fallback.NOP_FALLBACK;
-
-public interface SagaRequest {
-
- String PARAM_FORM = "form";
- String PARAM_JSON = "json";
- String PARAM_JSON_BODY = "body";
- String PARAM_QUERY = "query";
-
- Transaction transaction();
-
- Compensation compensation();
-
- default Fallback fallback() {
- return NOP_FALLBACK;
- }
-
- String serviceName();
-
- String id();
-
- String type();
-
- String task();
-
- String[] parents();
-
- int failRetryDelayMilliseconds();
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaRequestImpl.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaRequestImpl.java
deleted file mode 100644
index cbb7a23..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaRequestImpl.java
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-import static org.apache.servicecomb.saga.core.Fallback.NOP_FALLBACK;
-
-import java.util.Arrays;
-
-public class SagaRequestImpl implements SagaRequest {
-
- private final String id;
- private final String serviceName;
- private final String type;
- private final Transaction transaction;
- private final Compensation compensation;
- private final String[] parents;
- private final Fallback fallback;
- private final int failRetryDelayMilliseconds;
-
- public SagaRequestImpl(
- String id,
- String serviceName,
- String type,
- Transaction transaction,
- Compensation compensation,
- Fallback fallback,
- String[] parents,
- int failRetryDelayMilliseconds) {
-
- this.id = id;
- this.serviceName = serviceName;
- this.type = type;
- this.transaction = transaction;
- this.compensation = compensation;
- this.fallback = fallback;
- this.failRetryDelayMilliseconds = failRetryDelayMilliseconds <= 0 ? 50 : failRetryDelayMilliseconds;
- // TODO: 2017/10/21 set parent to root when null
- this.parents = parents == null ? new String[0] : parents;
- }
-
- public SagaRequestImpl(
- String id,
- String serviceName,
- String type,
- Transaction transaction,
- Compensation compensation,
- Fallback fallback,
- String[] parents) {
- this(id, serviceName, type, transaction, compensation, fallback, parents, 0);
- }
-
- public SagaRequestImpl(
- String id,
- String serviceName,
- String type,
- Transaction transaction,
- Compensation compensation,
- Fallback fallback) {
- this(id, serviceName, type, transaction, compensation, fallback, new String[0]);
- }
-
- public SagaRequestImpl(
- String id,
- String serviceName,
- String type,
- Transaction transaction,
- Compensation compensation) {
- this(id, serviceName, type, transaction, compensation, NOP_FALLBACK, new String[0]);
- }
-
- public SagaRequestImpl(
- String id,
- String serviceName,
- String type,
- Transaction transaction,
- Compensation compensation,
- String[] parents) {
- this(id, serviceName, type, transaction, compensation, NOP_FALLBACK, parents);
- }
-
- @Override
- public Transaction transaction() {
- return transaction;
- }
-
- @Override
- public Compensation compensation() {
- return compensation;
- }
-
- @Override
- public Fallback fallback() {
- return fallback;
- }
-
- @Override
- public String serviceName() {
- return serviceName;
- }
-
- @Override
- public String id() {
- return id;
- }
-
- @Override
- public String type() {
- return type;
- }
-
- @Override
- public String task() {
- return SagaTask.SAGA_REQUEST_TASK;
- }
-
- @Override
- public String[] parents() {
- return parents;
- }
-
- @Override
- public int failRetryDelayMilliseconds() {
- return failRetryDelayMilliseconds;
- }
-
- @Override
- public String toString() {
- return "SagaRequest{" +
- "id='" + id + '\'' +
- ", serviceName='" + serviceName + '\'' +
- ", type='" + type + '\'' +
- ", transaction=" + transaction +
- ", compensation=" + compensation +
- ", fallback=" + fallback +
- ", parents=" + Arrays.toString(parents) +
- '}';
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaResponse.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaResponse.java
deleted file mode 100644
index ecdfe4a..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaResponse.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-public interface SagaResponse {
-
- SagaResponse EMPTY_RESPONSE = new SagaResponse() {
- @Override
- public boolean succeeded() {
- return true;
- }
-
- @Override
- public String body() {
- return "{}";
- }
-
- @Override
- public String toString() {
- return "EMPTY_RESPONSE{body={}}";
- }
- };
-
- SagaResponse NONE_RESPONSE = new SagaResponse() {
- @Override
- public boolean succeeded() {
- return false;
- }
-
- @Override
- public String body() {
- return "{\n"
- + " \"sagaChildren\": [\"none\"]\n"
- + "}";
- }
-
- @Override
- public String toString() {
- return "NONE_RESPONSE{body={\"sagaChildren\": [\"none\"]\n}}";
- }
- };
-
- boolean succeeded();
-
- String body();
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaStartFailedException.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaStartFailedException.java
deleted file mode 100644
index 0de35da..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaStartFailedException.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-public class SagaStartFailedException extends RuntimeException {
-
- public SagaStartFailedException(String cause, Throwable e) {
- super(cause, e);
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaStartTask.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaStartTask.java
deleted file mode 100644
index d8a6bd1..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaStartTask.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-import kamon.annotation.EnableKamon;
-import kamon.annotation.Segment;
-
-@EnableKamon
-public class SagaStartTask implements SagaTask {
-
- private final String sagaId;
- private final String requestJson;
- private final SagaLog sagaLog;
-
- public SagaStartTask(String sagaId, String requestJson, SagaLog sagaLog) {
- this.sagaId = sagaId;
- this.requestJson = requestJson;
- this.sagaLog = sagaLog;
- }
-
- @Segment(name = "startTaskCommit", category = "application", library = "kamon")
- @Override
- public SagaResponse commit(SagaRequest request, SagaResponse parentResponse) {
- try {
- sagaLog.offer(new SagaStartedEvent(sagaId, requestJson, request));
- } catch (Exception e) {
- throw new SagaStartFailedException("Failed to persist SagaStartedEvent for " + requestJson, e);
- }
- return SagaResponse.EMPTY_RESPONSE;
- }
-
- @Override
- public void compensate(SagaRequest request) {
- sagaLog.offer(new SagaEndedEvent(sagaId, request));
- }
-
- @Override
- public void abort(SagaRequest request, Exception e) {
-
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaStartedEvent.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaStartedEvent.java
deleted file mode 100644
index 0d82fee..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaStartedEvent.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-public class SagaStartedEvent extends SagaEvent {
-
- private final String requestJson;
-
- public SagaStartedEvent(String sagaId, String requestJson, SagaRequest request) {
- super(sagaId, request);
- this.requestJson = requestJson;
- }
-
- @Override
- public void gatherTo(EventContext sagaContext) {
- sagaContext.endTransaction(payload(), SagaResponse.EMPTY_RESPONSE);
- }
-
- @Override
- public String json(ToJsonFormat toJsonFormat) {
- return requestJson;
- }
-
- @Override
- public String toString() {
- return "SagaStartedEvent{id="
- + payload().id()
- + ", sagaId=" + sagaId
- + "}";
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaState.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaState.java
deleted file mode 100644
index eae3678..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaState.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-interface SagaState {
-
- boolean hasNext();
-
- void run();
-
- void replay();
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaTask.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaTask.java
deleted file mode 100644
index 73efcc0..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaTask.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-public interface SagaTask {
-
- String SAGA_START_TASK = "SagaStart";
- String SAGA_REQUEST_TASK = "SagaRequest";
- String SAGA_END_TASK = "SagaEnd";
-
- SagaResponse commit(SagaRequest request, SagaResponse parentResponse);
-
- void compensate(SagaRequest request);
-
- void abort(SagaRequest request, Exception e);
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaTaskFactory.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaTaskFactory.java
deleted file mode 100644
index 0fd2450..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/SagaTaskFactory.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-import java.lang.invoke.MethodHandles;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class SagaTaskFactory {
- private final FallbackPolicy fallbackPolicy;
- private final RetrySagaLog retrySagaLog;
- private final PersistentStore persistentStore;
-
- public SagaTaskFactory(int retryDelay, PersistentStore persistentStore) {
- this.persistentStore = persistentStore;
-
- fallbackPolicy = new FallbackPolicy(retryDelay);
- retrySagaLog = new RetrySagaLog(persistentStore, retryDelay);
- }
-
- public Map<String, SagaTask> sagaTasks(String sagaId,
- String requestJson,
- RecoveryPolicy recoveryPolicy,
- EventStore sagaLog) {
-
- SagaLog compositeSagaLog = compositeSagaLog(sagaLog, persistentStore);
-
- return new HashMap<String, SagaTask>() {{
- put(SagaTask.SAGA_START_TASK, new SagaStartTask(sagaId, requestJson, compositeSagaLog));
-
- SagaLog retrySagaLog = compositeSagaLog(sagaLog, SagaTaskFactory.this.retrySagaLog);
- put(SagaTask.SAGA_REQUEST_TASK,
- new RequestProcessTask(sagaId, retrySagaLog, new LoggingRecoveryPolicy(recoveryPolicy), fallbackPolicy));
- put(SagaTask.SAGA_END_TASK, new SagaEndTask(sagaId, retrySagaLog));
- }};
- }
-
- private CompositeSagaLog compositeSagaLog(SagaLog sagaLog, PersistentLog persistentLog) {
- return new CompositeSagaLog(sagaLog, persistentLog);
- }
-
- static class RetrySagaLog implements PersistentLog {
-
- private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
- private final PersistentStore persistentStore;
- private final int retryDelay;
-
- RetrySagaLog(PersistentStore persistentStore, int retryDelay) {
- this.persistentStore = persistentStore;
- this.retryDelay = retryDelay;
- }
-
- @Override
- public void offer(SagaEvent sagaEvent) {
- boolean success = false;
- do {
- try {
- persistentStore.offer(sagaEvent);
- success = true;
- log.info("Persisted saga event {} successfully", sagaEvent);
- } catch (Exception e) {
- log.error("Failed to persist saga event {}", sagaEvent, e);
- sleep(retryDelay);
- }
- } while (!success && !isInterrupted());
- }
-
- private boolean isInterrupted() {
- return Thread.currentThread().isInterrupted();
- }
-
- private void sleep(int delay) {
- try {
- Thread.sleep(delay);
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- }
- }
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/SuccessfulSagaResponse.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/SuccessfulSagaResponse.java
deleted file mode 100644
index d69bdcd..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/SuccessfulSagaResponse.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-public class SuccessfulSagaResponse implements SagaResponse {
- private final String body;
-
- public SuccessfulSagaResponse(String body) {
- this.body = body;
- }
-
- @Override
- public boolean succeeded() {
- return true;
- }
-
- @Override
- public String body() {
- return body;
- }
-
- @Override
- public String toString() {
- return "SuccessfulSagaResponse{" +
- "body='" + body + '\'' +
- '}';
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/TaskConsumer.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/TaskConsumer.java
deleted file mode 100644
index 5ae7494..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/TaskConsumer.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-import java.util.Collection;
-
-import org.apache.servicecomb.saga.core.dag.Node;
-
-interface TaskConsumer {
-
- void consume(Collection<Node<SagaRequest>> nodes);
-
- boolean replay(Collection<Node<SagaRequest>> nodes);
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/TaskRunner.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/TaskRunner.java
deleted file mode 100644
index c078001..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/TaskRunner.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-import org.apache.servicecomb.saga.core.dag.Node;
-import org.apache.servicecomb.saga.core.dag.Traveller;
-
-import java.util.Collection;
-
-import kamon.annotation.EnableKamon;
-import kamon.annotation.Segment;
-
-@EnableKamon
-class TaskRunner implements SagaState {
-
- private final Traveller<SagaRequest> traveller;
- private final TaskConsumer taskConsumer;
-
- TaskRunner(Traveller<SagaRequest> traveller, TaskConsumer taskConsumer) {
- this.traveller = traveller;
- this.taskConsumer = taskConsumer;
- }
-
- @Override
- public boolean hasNext() {
- return traveller.hasNext();
- }
-
- @Segment(name = "runTask", category = "application", library = "kamon")
- @Override
- public void run() {
- Collection<Node<SagaRequest>> nodes = traveller.nodes();
-
- // finish pending tasks from saga log at startup
- if (!nodes.isEmpty()) {
- taskConsumer.consume(nodes);
- nodes.clear();
- }
-
- while (traveller.hasNext()) {
- traveller.next();
- taskConsumer.consume(nodes);
- nodes.clear();
- }
- }
-
- @Override
- public void replay() {
- boolean played = false;
- Collection<Node<SagaRequest>> nodes = traveller.nodes();
-
- while (traveller.hasNext() && !played) {
- traveller.next();
- played = taskConsumer.replay(nodes);
- }
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/ToJsonFormat.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/ToJsonFormat.java
deleted file mode 100644
index cd6c449..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/ToJsonFormat.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-public interface ToJsonFormat {
-
- String toJson(SagaRequest request);
-
- String toJson(SagaRequest request, SagaResponse response);
-
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/Transaction.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/Transaction.java
deleted file mode 100644
index fafb845..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/Transaction.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-public interface Transaction extends Operation {
-
- Transaction SAGA_START_TRANSACTION = new Transaction() {
- };
-
- Transaction SAGA_END_TRANSACTION = new Transaction() {
- };
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/TransactionAbortedEvent.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/TransactionAbortedEvent.java
deleted file mode 100644
index b117c94..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/TransactionAbortedEvent.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-public class TransactionAbortedEvent extends SagaEvent {
-
- private final SagaResponse response;
-
- public TransactionAbortedEvent(String sagaId, SagaRequest payload, Exception exception) {
- super(sagaId, payload);
- this.response = new FailedSagaResponse(exception);
- }
-
- public TransactionAbortedEvent(String sagaId, SagaRequest payload, SagaResponse response) {
- super(sagaId, payload);
- this.response = response;
- }
-
- @Override
- public void gatherTo(EventContext sagaContext) {
- // remove from completed operations in order not to compensate it
- sagaContext.abortTransaction(payload(), response);
- }
-
- @Override
- public String json(ToJsonFormat toJsonFormat) {
- return toJsonFormat.toJson(payload(), response);
- }
-
- @Override
- public String toString() {
- return "TransactionAbortedEvent{id="
- + payload().id()
- + ", operation="
- + payload().compensation()
- + "}";
- }
-
- public SagaResponse response() {
- return response;
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/TransactionCompensatedEvent.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/TransactionCompensatedEvent.java
deleted file mode 100644
index d6ab298..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/TransactionCompensatedEvent.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-public class TransactionCompensatedEvent extends SagaEvent {
-
- private final SagaResponse response;
-
- public TransactionCompensatedEvent(String sagaId, SagaRequest request) {
- this(sagaId, request, SagaResponse.EMPTY_RESPONSE);
- }
-
- public TransactionCompensatedEvent(String sagaId, SagaRequest request, SagaResponse response) {
- super(sagaId, request);
- this.response = response;
- }
-
- @Override
- public void gatherTo(EventContext sagaContext) {
- sagaContext.compensateTransaction(payload(), response);
- }
-
- @Override
- public String json(ToJsonFormat toJsonFormat) {
- return toJsonFormat.toJson(payload(), response);
- }
-
- @Override
- public String toString() {
- return "TransactionCompensatedEvent{id="
- + payload().id()
- + ", sagaId=" + sagaId
- + ", operation="
- + payload().compensation()
- + "}";
- }
-
- public SagaResponse response() {
- return response;
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/TransactionEndedEvent.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/TransactionEndedEvent.java
deleted file mode 100644
index 603c542..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/TransactionEndedEvent.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-public class TransactionEndedEvent extends SagaEvent {
-
- private final SagaResponse response;
-
- public TransactionEndedEvent(String sagaId, SagaRequest request) {
- this(sagaId, request, SagaResponse.EMPTY_RESPONSE);
- }
-
- public TransactionEndedEvent(String sagaId, SagaRequest request, SagaResponse response) {
- super(sagaId, request);
- this.response = response;
- }
-
- @Override
- public void gatherTo(EventContext sagaContext) {
- sagaContext.endTransaction(payload(), response);
- }
-
- @Override
- public String toString() {
- return "TransactionEndedEvent{id="
- + payload().id()
- + ", sagaId=" + sagaId
- + ", operation="
- + payload().transaction()
- + "}";
- }
-
- @Override
- public String json(ToJsonFormat toJsonFormat) {
- return toJsonFormat.toJson(payload(), response);
- }
-
- public SagaResponse response() {
- return response;
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/TransactionFailedException.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/TransactionFailedException.java
deleted file mode 100644
index b55e01a..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/TransactionFailedException.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-public class TransactionFailedException extends RuntimeException {
-
- public TransactionFailedException(Throwable throwable) {
- super(throwable);
- }
-
- public TransactionFailedException(String cause) {
- super(cause);
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/TransactionStartedEvent.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/TransactionStartedEvent.java
deleted file mode 100644
index cc35589..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/TransactionStartedEvent.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-public class TransactionStartedEvent extends SagaEvent {
-
- public TransactionStartedEvent(String sagaId, SagaRequest transaction) {
- super(sagaId, transaction);
- }
-
- @Override
- public void gatherTo(EventContext sagaContext) {
- sagaContext.beginTransaction(payload());
- }
-
- @Override
- public String toString() {
- return "TransactionStartedEvent{id="
- + payload().id()
- + ", sagaId=" + sagaId
- + ", operation="
- + payload().transaction()
- + "}";
- }
-
- @Override
- public String json(ToJsonFormat toJsonFormat) {
- return toJsonFormat.toJson(payload());
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/TransactionTaskConsumer.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/TransactionTaskConsumer.java
deleted file mode 100644
index af2dc74..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/TransactionTaskConsumer.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-import org.apache.servicecomb.saga.core.dag.Node;
-import java.lang.invoke.MethodHandles;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.Callable;
-import java.util.concurrent.CompletionService;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
-
-import kamon.annotation.EnableKamon;
-import kamon.annotation.Segment;
-import kamon.annotation.Trace;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@EnableKamon
-class TransactionTaskConsumer implements TaskConsumer {
-
- private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
- private final Map<String, SagaTask> tasks;
- private final SagaContext sagaContext;
- private final CompletionService<Operation> executorService;
-
- TransactionTaskConsumer(
- Map<String, SagaTask> tasks,
- SagaContext sagaContext,
- CompletionService<Operation> executorService) {
-
- this.tasks = tasks;
- this.sagaContext = sagaContext;
- this.executorService = executorService;
- }
-
- @Segment(name = "consumeTask", category = "application", library = "kamon")
- @Override
- public void consume(Collection<Node<SagaRequest>> nodes) {
- List<Future<Operation>> futures = new ArrayList<>(nodes.size());
- for (Node<SagaRequest> node : nodes) {
- SagaRequest request = node.value();
- if (sagaContext.isChosenChild(request)) {
- futures.add(futureOf(request));
- }
- }
-
- for (int i = 0; i < futures.size(); i++) {
- try {
- executorService.take().get();
- } catch (ExecutionException e) {
- if (e.getCause() instanceof SagaStartFailedException) {
- throw ((SagaStartFailedException) e.getCause());
- }
- throw new TransactionFailedException(e.getCause());
- } catch (InterruptedException e) {
- // TODO: 7/29/2017 what shall we do when system is shutting down?
- throw new TransactionFailedException(e);
- }
- }
- }
-
- @Override
- public boolean replay(Collection<Node<SagaRequest>> nodes) {
- for (Iterator<Node<SagaRequest>> iterator = nodes.iterator(); iterator.hasNext(); ) {
- SagaRequest request = iterator.next().value();
- if (sagaContext.isTransactionCompleted(request)) {
- log.info("Skipped completed transaction id={} operation={} while replay", request.id(), request.transaction());
- iterator.remove();
- }
- }
- return !nodes.isEmpty();
- }
-
- @Segment(name = "submitCallable", category = "application", library = "kamon")
- private Future<Operation> futureOf(SagaRequest request) {
- return executorService.submit(new OperationCallable(tasks, request, sagaContext.responseOf(request.parents())));
- }
-
- @EnableKamon
- private static class OperationCallable implements Callable<Operation> {
-
- private final SagaRequest request;
- private final Map<String, SagaTask> tasks;
- private final SagaResponse parentResponse;
-
- private OperationCallable(
- Map<String, SagaTask> tasks,
- SagaRequest request,
- SagaResponse parentResponse) {
- this.request = request;
- this.tasks = tasks;
- this.parentResponse = parentResponse;
- }
-
- @Trace("runTransactionCallable")
- @Override
- public Operation call() throws Exception {
- tasks.get(request.task()).commit(request, parentResponse);
- return request.transaction();
- }
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/Transport.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/Transport.java
deleted file mode 100644
index 5679e0a..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/Transport.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-public interface Transport {
-
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/TransportFailedException.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/TransportFailedException.java
deleted file mode 100644
index e01a9d5..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/TransportFailedException.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-public class TransportFailedException extends RuntimeException {
- public TransportFailedException(String cause) {
- super(cause);
- }
-
- public TransportFailedException(String cause, Throwable e) {
- super(cause, e);
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/actors/ActorBasedSaga.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/actors/ActorBasedSaga.java
deleted file mode 100644
index bf60f98..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/actors/ActorBasedSaga.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core.actors;
-
-import java.util.concurrent.CompletableFuture;
-
-import org.apache.servicecomb.saga.core.EventContext;
-import org.apache.servicecomb.saga.core.EventStore;
-import org.apache.servicecomb.saga.core.NoOpSagaRequest;
-import org.apache.servicecomb.saga.core.Saga;
-import org.apache.servicecomb.saga.core.SagaResponse;
-import org.apache.servicecomb.saga.core.actors.messages.TransactMessage;
-import org.apache.servicecomb.saga.core.SagaEvent;
-
-import akka.actor.ActorRef;
-
-public class ActorBasedSaga implements Saga {
- private final ActorRef root;
- private final ActorRef completionCallback;
- private final CompletableFuture<SagaResponse> future;
- private final EventStore sagaLog;
- private final EventContext sagaContext;
-
- ActorBasedSaga(ActorRef root, ActorRef completionCallback, CompletableFuture<SagaResponse> future, EventStore sagaLog,
- EventContext sagaContext) {
- this.root = root;
- this.completionCallback = completionCallback;
- this.future = future;
- this.sagaLog = sagaLog;
- this.sagaContext = sagaContext;
- }
-
- @Override
- public SagaResponse run() {
- root.tell(new TransactMessage(NoOpSagaRequest.SAGA_START_REQUEST, SagaResponse.EMPTY_RESPONSE), completionCallback);
-
- return future.join();
- }
-
- @Override
- public void play() {
- gatherEvents(sagaLog);
- }
-
- private void gatherEvents(Iterable<SagaEvent> events) {
- for (SagaEvent event : events) {
- event.gatherTo(sagaContext);
- }
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/actors/ActorBasedSagaFactory.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/actors/ActorBasedSagaFactory.java
deleted file mode 100644
index 8ce22fa..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/actors/ActorBasedSagaFactory.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core.actors;
-
-import static akka.actor.ActorRef.noSender;
-
-import java.util.Set;
-import java.util.concurrent.CompletableFuture;
-
-import org.apache.servicecomb.saga.core.EventStore;
-import org.apache.servicecomb.saga.core.NoOpSagaRequest;
-import org.apache.servicecomb.saga.core.SagaResponse;
-import org.apache.servicecomb.saga.core.application.SagaFactory;
-import org.apache.servicecomb.saga.core.PersistentStore;
-import org.apache.servicecomb.saga.core.SagaDefinition;
-import org.apache.servicecomb.saga.core.SagaTaskFactory;
-import org.apache.servicecomb.saga.core.application.interpreter.FromJsonFormat;
-import akka.actor.ActorRef;
-import akka.actor.ActorSystem;
-import scala.concurrent.Await;
-import scala.concurrent.duration.Duration;
-
-public class ActorBasedSagaFactory implements SagaFactory {
- private final ActorSystem actorSystem = ActorSystem.create("saga");
- private final RequestActorBuilder actorBuilder;
- private final SagaTaskFactory sagaTaskFactory;
-
- public ActorBasedSagaFactory(int retryDelay,
- PersistentStore persistentStore,
- FromJsonFormat<Set<String>> childrenExtractor) {
-
- this.sagaTaskFactory = new SagaTaskFactory(retryDelay, persistentStore);
- this.actorBuilder = new RequestActorBuilder(actorSystem, childrenExtractor);
- }
-
- @Override
- public ActorBasedSaga createSaga(String requestJson, String sagaId, EventStore sagaLog, SagaDefinition definition) {
-
- CompletableFuture<SagaResponse> future = new CompletableFuture<>();
- ActorRef completionCallback = actorSystem.actorOf(CompletionCallbackActor.props(future));
- RequestActorContext context = actorBuilder.build(
- definition.requests(),
- sagaTaskFactory.sagaTasks(sagaId,
- requestJson,
- definition.policy(),
- sagaLog
- ),
- completionCallback);
-
- completionCallback.tell(context, noSender());
- return new ActorBasedSaga(
- context.actorOf(NoOpSagaRequest.SAGA_START_REQUEST.id()),
- completionCallback,
- future,
- sagaLog,
- new EventContextImpl(context));
- }
-
- @Override
- public boolean isTerminated() {
- return actorSystem.whenTerminated().isCompleted();
- }
-
- @Override
- public void terminate() throws Exception {
- Await.result(actorSystem.terminate(), Duration.Inf());
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/actors/CompletionCallbackActor.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/actors/CompletionCallbackActor.java
deleted file mode 100644
index 7cee4d3..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/actors/CompletionCallbackActor.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core.actors;
-
-import java.util.concurrent.CompletableFuture;
-
-import org.apache.servicecomb.saga.core.NoOpSagaRequest;
-import org.apache.servicecomb.saga.core.SagaResponse;
-import org.apache.servicecomb.saga.core.actors.messages.AbortMessage;
-import org.apache.servicecomb.saga.core.actors.messages.CompensateMessage;
-import org.apache.servicecomb.saga.core.actors.messages.FailMessage;
-import org.apache.servicecomb.saga.core.actors.messages.TransactMessage;
-import akka.actor.AbstractLoggingActor;
-import akka.actor.Props;
-
-class CompletionCallbackActor extends AbstractLoggingActor {
- private final CompletableFuture<SagaResponse> future;
-
- private CompletionCallbackActor(CompletableFuture<SagaResponse> future) {
- this.future = future;
- }
-
- static Props props(CompletableFuture<SagaResponse> future) {
- return Props.create(CompletionCallbackActor.class, () -> new CompletionCallbackActor(future));
- }
-
- @Override
- public Receive createReceive() {
- return receiveBuilder()
- .match(RequestActorContext.class, this::ready)
- .build();
- }
-
- private void ready(RequestActorContext context) {
- getContext().become(receiveBuilder()
- .match(CompensateMessage.class, message -> end(context, message.response()))
- .match(TransactMessage.class, message -> end(context, message.response()))
- .match(AbortMessage.class, message -> onAbort(context, message))
- .match(FailMessage.class, message -> end(context, message.response()))
- .build());
- }
-
- private void onAbort(RequestActorContext context, AbortMessage message) {
- log().info("saga actor: received abort message of {}", message.response());
- context.actorOf(NoOpSagaRequest.SAGA_END_REQUEST.id()).tell(new CompensateMessage(message.response()), self());
- }
-
- private void end(RequestActorContext context, SagaResponse response) {
- log().info("saga actor: received response {}", response);
- future.complete(response);
- context.forAll(actor -> getContext().stop(actor));
- getContext().stop(self());
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/actors/EventContextImpl.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/actors/EventContextImpl.java
deleted file mode 100644
index 21a2928..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/actors/EventContextImpl.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core.actors;
-
-import static akka.actor.ActorRef.noSender;
-
-import org.apache.servicecomb.saga.core.EventContext;
-import org.apache.servicecomb.saga.core.SagaRequest;
-import org.apache.servicecomb.saga.core.SagaResponse;
-import org.apache.servicecomb.saga.core.actors.messages.AbortRecoveryMessage;
-import org.apache.servicecomb.saga.core.actors.messages.CompensationRecoveryMessage;
-import org.apache.servicecomb.saga.core.actors.messages.TransactionRecoveryMessage;
-import org.apache.servicecomb.saga.core.actors.messages.Message;
-
-public class EventContextImpl implements EventContext {
- private final RequestActorContext context;
-
- EventContextImpl(RequestActorContext context) {
- this.context = context;
- }
-
- @Override
- public void beginTransaction(SagaRequest request) {
-
- }
-
- @Override
- public void endTransaction(SagaRequest request, SagaResponse response) {
- sendMessage(request, new TransactionRecoveryMessage(response));
- }
-
- @Override
- public void abortTransaction(SagaRequest request, SagaResponse response) {
- sendMessage(request, new AbortRecoveryMessage(response));
- }
-
- @Override
- public void compensateTransaction(SagaRequest request, SagaResponse response) {
- sendMessage(request, new CompensationRecoveryMessage());
- }
-
- private void sendMessage(SagaRequest request, Message message) {
- context.actorOf(request.id()).tell(message, noSender());
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/actors/RequestActor.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/actors/RequestActor.java
deleted file mode 100644
index 055174e..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/actors/RequestActor.java
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core.actors;
-
-import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.function.Consumer;
-import java.util.function.Supplier;
-
-import org.apache.servicecomb.saga.core.CompositeSagaResponse;
-import org.apache.servicecomb.saga.core.SagaRequest;
-import org.apache.servicecomb.saga.core.SagaResponse;
-import org.apache.servicecomb.saga.core.SagaStartFailedException;
-import org.apache.servicecomb.saga.core.SagaTask;
-import org.apache.servicecomb.saga.core.TransactionFailedException;
-import org.apache.servicecomb.saga.core.actors.messages.AbortMessage;
-import org.apache.servicecomb.saga.core.actors.messages.AbortRecoveryMessage;
-import org.apache.servicecomb.saga.core.actors.messages.CompensationRecoveryMessage;
-import org.apache.servicecomb.saga.core.actors.messages.FailMessage;
-import org.apache.servicecomb.saga.core.actors.messages.Message;
-import org.apache.servicecomb.saga.core.actors.messages.TransactMessage;
-import org.apache.servicecomb.saga.core.actors.messages.TransactionRecoveryMessage;
-import org.apache.servicecomb.saga.core.actors.messages.CompensateMessage;
-
-import akka.actor.AbstractLoggingActor;
-import akka.actor.ActorRef;
-import akka.actor.Props;
-import akka.japi.pf.ReceiveBuilder;
-
-public class RequestActor extends AbstractLoggingActor {
- private final RequestActorContext context;
- private final SagaTask task;
- private final SagaRequest request;
-
- private final List<SagaResponse> parentResponses;
- private final List<ActorRef> compensatedChildren;
-
- private final Receive transacted;
- private final Receive aborted;
-
- static Props props(
- RequestActorContext context,
- SagaTask task,
- SagaRequest request) {
- return Props.create(RequestActor.class, () -> new RequestActor(context, task, request));
- }
-
- private RequestActor(
- RequestActorContext context,
- SagaTask task,
- SagaRequest request) {
- this.context = context;
- this.task = task;
- this.request = request;
- this.parentResponses = new ArrayList<>(request.parents().length);
- this.compensatedChildren = new LinkedList<>();
-
- this.aborted = onReceive(ignored -> {
- }).build();
-
- this.transacted = onReceive(task::compensate)
- .match(CompensationRecoveryMessage.class, message -> getContext().become(aborted))
- .build();
- }
-
- @Override
- public Receive createReceive() {
- return receiveBuilder()
- .match(TransactMessage.class,
- message -> onTransaction(message, () -> task.commit(request, responseOf(parentResponses))))
- .match(TransactionRecoveryMessage.class, this::onTransactRecovery)
- .match(AbortRecoveryMessage.class, this::onAbortRecovery)
- .match(AbortMessage.class, this::onAbort)
- .build();
- }
-
- private void onAbort(AbortMessage message) {
- log().debug("{}: received abort message of {}", request.id(), message.response());
- sendToChildrenButSender(message);
- sendToParentsButSender(message);
-
- getContext().become(aborted);
- }
-
- private void sendToParentsButSender(AbortMessage message) {
- context.parentsOf(request)
- .stream()
- .filter(this::isNotSender)
- .forEach(actor -> actor.tell(message, self()));
- }
-
- private void sendToChildrenButSender(AbortMessage message) {
- context.childrenOf(request)
- .stream()
- .filter(this::isNotSender)
- .forEach(actor -> actor.tell(message, self()));
- }
-
- private boolean isNotSender(ActorRef actor) {
- return !actor.equals(sender());
- }
-
- private void onTransactRecovery(TransactionRecoveryMessage message) {
- getContext().become(receiveBuilder()
- .match(TransactMessage.class, m -> onTransaction(m, message::response))
- .match(CompensationRecoveryMessage.class, m -> getContext().become(aborted))
- .build()
- );
- }
-
- private void onAbortRecovery(AbortRecoveryMessage message) {
- getContext().become(
- receiveBuilder()
- .match(TransactMessage.class, m -> onAbort(new AbortMessage(message.response())))
- .build());
- }
-
- private void onTransaction(TransactMessage message, Supplier<SagaResponse> responseSupplier) {
- log().debug("{}: received transaction message of {}", request.id(), message.request());
- if (context.parentsOf(request).contains(sender())) {
- parentResponses.add(message.response());
- }
-
- if (parentResponses.size() == context.parentsOf(request).size()) {
- transact(responseSupplier);
- }
- }
-
- private void transact(Supplier<SagaResponse> responseSupplier) {
- try {
- if (isChosenChild(parentResponses)) {
- SagaResponse sagaResponse = responseSupplier.get();
- sendToChildren(new TransactMessage(request, sagaResponse));
- getContext().become(transacted);
- } else {
- sendToChildren(new TransactMessage(request, SagaResponse.NONE_RESPONSE));
- getContext().become(aborted);
- }
- } catch (SagaStartFailedException e) {
- sendToParents(new FailMessage(e));
- } catch (Exception e) {
- log().error("Failed to run operation {} with error {}", request.transaction(), e);
-
- Message abortMessage = new AbortMessage(new TransactionFailedException(e));
- sendToParents(abortMessage);
- sendToChildren(abortMessage);
- getContext().become(aborted);
- }
- }
-
- private void sendToParents(Message message) {
- context.parentsOf(request).forEach(actor -> actor.tell(message, self()));
- }
-
- private void sendToChildren(Message message) {
- context.childrenOf(request).forEach(actor -> actor.tell(message, self()));
- }
-
- private boolean isChosenChild(List<SagaResponse> parentResponses) {
- return request.parents().length == 0 || parentResponses.isEmpty() || parentResponses.stream()
- .map(context::chosenChildren)
- .anyMatch(chosenChildren -> chosenChildren.isEmpty() || chosenChildren.contains(request.id()));
- }
-
- private SagaResponse responseOf(List<SagaResponse> responseContexts) {
- if (responseContexts.isEmpty()) {
- return SagaResponse.EMPTY_RESPONSE;
- }
-
- if (responseContexts.size() == 1) {
- return responseContexts.get(0);
- }
- return new CompositeSagaResponse(responseContexts);
- }
-
- private ReceiveBuilder onReceive(Consumer<SagaRequest> requestConsumer) {
- return receiveBuilder()
- .match(CompensateMessage.class, message -> onCompensate(message, requestConsumer));
- }
-
- private void onCompensate(CompensateMessage message, Consumer<SagaRequest> requestConsumer) {
- log().debug("{}: received compensation message from {}", request.id(), sender());
- compensatedChildren.add(sender());
-
- if (compensatedChildren.size() == context.childrenOf(request).size()) {
- requestConsumer.accept(request);
- sendToParents(message);
- }
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/actors/RequestActorBuilder.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/actors/RequestActorBuilder.java
deleted file mode 100644
index 5004b4e..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/actors/RequestActorBuilder.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core.actors;
-
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.servicecomb.saga.core.NoOpSagaRequest;
-import org.apache.servicecomb.saga.core.SagaRequest;
-import org.apache.servicecomb.saga.core.SagaTask;
-import org.apache.servicecomb.saga.core.application.interpreter.FromJsonFormat;
-import akka.actor.ActorRef;
-import akka.actor.ActorSystem;
-import akka.actor.Props;
-
-public class RequestActorBuilder {
- private final ActorSystem actorSystem;
- private final FromJsonFormat<Set<String>> childrenExtractor;
-
- RequestActorBuilder(
- ActorSystem actorSystem,
- FromJsonFormat<Set<String>> childrenExtractor) {
-
- this.actorSystem = actorSystem;
- this.childrenExtractor = childrenExtractor;
- }
-
- public RequestActorContext build(SagaRequest[] requests, Map<String, SagaTask> tasks, ActorRef sagaActor) {
- RequestActorContext context = new RequestActorContext(childrenExtractor);
-
- ActorRef rootActor = rootActor(context, tasks);
- ActorRef leafActor = leafActor(context, tasks);
-
- createRequestActors(requests, tasks, context);
-
- linkActorsById(rootActor, requests, context);
- addLeafToChildless(leafActor, requests, context);
-
- context.addParent(NoOpSagaRequest.SAGA_START_REQUEST.id(), sagaActor);
- context.addChild(NoOpSagaRequest.SAGA_END_REQUEST.id(), sagaActor);
- return context;
- }
-
- private void linkActorsById(ActorRef rootActor, SagaRequest[] requests, RequestActorContext context) {
- for (SagaRequest request : requests) {
- if (isOrphan(request)) {
- context.addParent(request.id(), rootActor);
- context.addChild(NoOpSagaRequest.SAGA_START_REQUEST.id(), context.actorOf(request.id()));
- } else {
- for (String parent : request.parents()) {
- context.addParent(request.id(), context.actorOf(parent));
- context.addChild(parent, context.actorOf(request.id()));
- }
- }
- }
- }
-
- private boolean isOrphan(SagaRequest request) {
- return request.parents().length == 0;
- }
-
- private void createRequestActors(SagaRequest[] requests, Map<String, SagaTask> tasks, RequestActorContext context) {
- for (SagaRequest request : requests) {
- Props props = RequestActor.props(context, tasks.get(request.task()), request);
- context.addActor(request.id(), actorSystem.actorOf(props));
- }
- }
-
- private void addLeafToChildless(ActorRef leafActor, SagaRequest[] requests, RequestActorContext context) {
- for (SagaRequest request : requests) {
- if (context.childrenOf(request).isEmpty()) {
- context.addParent(NoOpSagaRequest.SAGA_END_REQUEST.id(), context.actorOf(request.id()));
- context.addChild(request.id(), leafActor);
- }
- }
- }
-
- private ActorRef rootActor(RequestActorContext context, Map<String, SagaTask> tasks) {
- Props root = RequestActor.props(context, tasks.get(
- NoOpSagaRequest.SAGA_START_REQUEST.task()), NoOpSagaRequest.SAGA_START_REQUEST);
- ActorRef actor = actorSystem.actorOf(root);
- context.addActor(NoOpSagaRequest.SAGA_START_REQUEST.id(), actor);
- return actor;
- }
-
- private ActorRef leafActor(RequestActorContext context, Map<String, SagaTask> tasks) {
- Props leaf = RequestActor.props(context, tasks.get(
- NoOpSagaRequest.SAGA_END_REQUEST.task()), NoOpSagaRequest.SAGA_END_REQUEST);
- ActorRef actor = actorSystem.actorOf(leaf);
- context.addActor(NoOpSagaRequest.SAGA_END_REQUEST.id(), actor);
- return actor;
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/actors/RequestActorContext.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/actors/RequestActorContext.java
deleted file mode 100644
index 2e3149d..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/actors/RequestActorContext.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core.actors;
-
-import static java.util.Collections.emptyList;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.function.Consumer;
-
-import org.apache.servicecomb.saga.core.SagaRequest;
-import org.apache.servicecomb.saga.core.SagaResponse;
-import org.apache.servicecomb.saga.core.application.interpreter.FromJsonFormat;
-import akka.actor.ActorRef;
-
-class RequestActorContext {
- private final Map<String, ActorRef> actors;
- private final Map<String, List<ActorRef>> parents;
- private final Map<String, List<ActorRef>> children;
- private final FromJsonFormat<Set<String>> childrenExtractor;
-
- RequestActorContext(
- FromJsonFormat<Set<String>> childrenExtractor) {
- this.actors = new HashMap<>();
- this.children = new HashMap<>();
- this.parents = new HashMap<>();
- this.childrenExtractor = childrenExtractor;
- }
-
- void addActor(String id, ActorRef actorRef) {
- actors.put(id, actorRef);
- }
-
- void addChild(String requestId, ActorRef ref) {
- children.computeIfAbsent(requestId, k -> new ArrayList<>()).add(ref);
- }
-
- void addParent(String requestId, ActorRef ref) {
- parents.computeIfAbsent(requestId, k -> new ArrayList<>()).add(ref);
- }
-
- ActorRef actorOf(String id) {
- return actors.get(id);
- }
-
- Collection<ActorRef> parentsOf(SagaRequest request) {
- return parents.getOrDefault(request.id(), emptyList());
- }
-
- Collection<ActorRef> childrenOf(SagaRequest request) {
- return children.getOrDefault(request.id(), emptyList());
- }
-
- void forAll(Consumer<ActorRef> consumer) {
- actors.values()
- .stream()
- .forEach(consumer);
- }
-
- Set<String> chosenChildren(SagaResponse response) {
- return childrenExtractor.fromJson(response.body());
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/actors/messages/AbortMessage.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/actors/messages/AbortMessage.java
deleted file mode 100644
index f23a079..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/actors/messages/AbortMessage.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core.actors.messages;
-
-import org.apache.servicecomb.saga.core.FailedSagaResponse;
-import org.apache.servicecomb.saga.core.SagaResponse;
-
-public class AbortMessage implements Message {
- private final SagaResponse response;
-
- public AbortMessage(Throwable e) {
- response = new FailedSagaResponse(e);
- }
-
- public AbortMessage(SagaResponse response) {
- this.response = response;
- }
-
- public SagaResponse response() {
- return response;
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/actors/messages/AbortRecoveryMessage.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/actors/messages/AbortRecoveryMessage.java
deleted file mode 100644
index 951157d..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/actors/messages/AbortRecoveryMessage.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core.actors.messages;
-
-import org.apache.servicecomb.saga.core.SagaResponse;
-
-public class AbortRecoveryMessage implements Message {
-
- private final SagaResponse response;
-
- public AbortRecoveryMessage(SagaResponse response) {
- this.response = response;
- }
-
- public SagaResponse response() {
- return response;
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/actors/messages/CompensateMessage.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/actors/messages/CompensateMessage.java
deleted file mode 100644
index 5fd0701..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/actors/messages/CompensateMessage.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core.actors.messages;
-
-import org.apache.servicecomb.saga.core.SagaResponse;
-
-public class CompensateMessage implements Message {
- private final SagaResponse response;
-
- public CompensateMessage(SagaResponse response) {
- this.response = response;
- }
-
- public SagaResponse response() {
- return response;
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/actors/messages/CompensationRecoveryMessage.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/actors/messages/CompensationRecoveryMessage.java
deleted file mode 100644
index 421a092..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/actors/messages/CompensationRecoveryMessage.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core.actors.messages;
-
-public class CompensationRecoveryMessage implements Message {
-
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/actors/messages/FailMessage.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/actors/messages/FailMessage.java
deleted file mode 100644
index 7a80ecb..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/actors/messages/FailMessage.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core.actors.messages;
-
-import org.apache.servicecomb.saga.core.FailedSagaResponse;
-import org.apache.servicecomb.saga.core.SagaResponse;
-
-public class FailMessage implements Message {
- private final SagaResponse response;
-
- public FailMessage(Throwable e) {
- response = new FailedSagaResponse(e);
- }
-
- public SagaResponse response() {
- return response;
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/actors/messages/Message.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/actors/messages/Message.java
deleted file mode 100644
index 3ed8187..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/actors/messages/Message.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core.actors.messages;
-
-public interface Message {
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/actors/messages/TransactMessage.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/actors/messages/TransactMessage.java
deleted file mode 100644
index e4c57a2..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/actors/messages/TransactMessage.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core.actors.messages;
-
-import org.apache.servicecomb.saga.core.SagaRequest;
-import org.apache.servicecomb.saga.core.SagaResponse;
-
-public class TransactMessage implements Message {
- private final SagaRequest request;
- private final SagaResponse response;
-
- public TransactMessage(SagaRequest request, SagaResponse response) {
- this.request = request;
- this.response = response;
- }
-
- public SagaRequest request() {
- return request;
- }
-
- public SagaResponse response() {
- return response;
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/actors/messages/TransactionRecoveryMessage.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/actors/messages/TransactionRecoveryMessage.java
deleted file mode 100644
index 26ba05b..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/actors/messages/TransactionRecoveryMessage.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core.actors.messages;
-
-import org.apache.servicecomb.saga.core.SagaResponse;
-
-public class TransactionRecoveryMessage implements Message {
- private final SagaResponse response;
-
- public TransactionRecoveryMessage(SagaResponse response) {
- this.response = response;
- }
-
- public SagaResponse response() {
- return response;
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/application/SagaExecutionComponent.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/application/SagaExecutionComponent.java
deleted file mode 100644
index 7a600d7..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/application/SagaExecutionComponent.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core.application;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.UUID;
-
-import org.apache.servicecomb.saga.core.EventEnvelope;
-import org.apache.servicecomb.saga.core.EventStore;
-import org.apache.servicecomb.saga.core.Saga;
-import org.apache.servicecomb.saga.core.SagaResponse;
-import org.apache.servicecomb.saga.core.ToJsonFormat;
-import org.apache.servicecomb.saga.core.PersistentStore;
-import org.apache.servicecomb.saga.core.SagaDefinition;
-import org.apache.servicecomb.saga.core.SagaEvent;
-import org.apache.servicecomb.saga.core.application.interpreter.FromJsonFormat;
-import org.apache.servicecomb.saga.infrastructure.EmbeddedEventStore;
-import kamon.annotation.EnableKamon;
-import kamon.annotation.Segment;
-
-@EnableKamon
-public class SagaExecutionComponent {
-
- private final PersistentStore persistentStore;
- private final FromJsonFormat<SagaDefinition> fromJsonFormat;
- private final ToJsonFormat toJsonFormat;
- private final SagaFactory sagaFactory;
-
- public SagaExecutionComponent(
- PersistentStore persistentStore,
- FromJsonFormat<SagaDefinition> fromJsonFormat,
- ToJsonFormat toJsonFormat,
- SagaFactory sagaFactory) {
- this.persistentStore = persistentStore;
- this.fromJsonFormat = fromJsonFormat;
- this.toJsonFormat = toJsonFormat;
- this.sagaFactory = sagaFactory;
- }
-
- @Segment(name = "runSagaExecutionComponent", category = "application", library = "kamon")
- public SagaResponse run(String requestJson) {
- String sagaId = UUID.randomUUID().toString();
- EventStore sagaLog = new EmbeddedEventStore();
- SagaDefinition definition = fromJsonFormat.fromJson(requestJson);
- Saga saga = sagaFactory.createSaga(requestJson, sagaId, sagaLog, definition);
- return saga.run();
- }
-
- public void reanimate() {
- Map<String, List<EventEnvelope>> pendingSagaEvents = persistentStore.findPendingSagaEvents();
-
- for (Entry<String, List<EventEnvelope>> entry : pendingSagaEvents.entrySet()) {
- EventStore eventStore = new EmbeddedEventStore();
- eventStore.populate(entry.getValue());
- SagaEvent event = entry.getValue().iterator().next().event;
-
- String requestJson = event.json(toJsonFormat);
- SagaDefinition definition = fromJsonFormat.fromJson(requestJson);
-
- Saga saga = sagaFactory.createSaga(requestJson, event.sagaId, eventStore, definition);
-
- saga.play();
- saga.run();
- }
- }
-
- public void terminate() throws Exception {
- sagaFactory.terminate();
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/application/SagaFactory.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/application/SagaFactory.java
deleted file mode 100644
index b60b5e7..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/application/SagaFactory.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core.application;
-
-import org.apache.servicecomb.saga.core.EventStore;
-import org.apache.servicecomb.saga.core.Saga;
-import org.apache.servicecomb.saga.core.SagaDefinition;
-
-public interface SagaFactory {
- Saga createSaga(String requestJson, String sagaId, EventStore sagaLog, SagaDefinition definition);
-
- boolean isTerminated();
-
- void terminate() throws Exception;
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/application/interpreter/FromJsonFormat.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/application/interpreter/FromJsonFormat.java
deleted file mode 100644
index ccfb408..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/application/interpreter/FromJsonFormat.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core.application.interpreter;
-
-public interface FromJsonFormat<T> {
-
- T fromJson(String requestJson);
-
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/application/interpreter/RestRequestChecker.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/application/interpreter/RestRequestChecker.java
deleted file mode 100644
index 7a65e48..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/application/interpreter/RestRequestChecker.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core.application.interpreter;
-
-import static java.util.Arrays.asList;
-
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-public class RestRequestChecker {
-
- private static final Set<String> validMethods = new HashSet<>(asList(
- "GET",
- "POST",
- "PUT",
- "DELETE"
- ));
-
- private RestRequestChecker() {
- }
-
- public static void checkParameters(String method, Map<String, Map<String, String>> params) {
- if (method == null || !validMethods.contains(method.toUpperCase())) {
- throw new IllegalArgumentException("Unsupported method " + method);
- }
-
- if (isDeleteOrGet(method) && hasBody(params)) {
- throw new IllegalArgumentException("GET & DELETE request cannot enclose a body");
- }
- }
-
- private static boolean isDeleteOrGet(String method) {
- return "GET".equalsIgnoreCase(method) || "DELETE".equalsIgnoreCase(method);
- }
-
- private static boolean hasBody(Map<String, Map<String, String>> params) {
- return params != null && (params.containsKey("form") || params.containsKey("json"));
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/dag/ByLevelTraveller.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/dag/ByLevelTraveller.java
deleted file mode 100644
index 22bc874..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/dag/ByLevelTraveller.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core.dag;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedHashSet;
-import java.util.LinkedList;
-import java.util.Map;
-import java.util.Queue;
-import java.util.Set;
-import kamon.annotation.EnableKamon;
-import kamon.annotation.Segment;
-
-@EnableKamon
-public class ByLevelTraveller<T> implements Traveller<T> {
-
- private final Collection<Node<T>> nodes;
- private final Collection<Node<T>> nodesBuffer;
-
- private final Queue<Node<T>> nodesWithoutParent = new LinkedList<>();
- private final Map<Long, Set<Node<T>>> nodeParents = new HashMap<>();
- private final TraversalDirection<T> traversalDirection;
-
-
- public ByLevelTraveller(SingleLeafDirectedAcyclicGraph<T> dag, TraversalDirection<T> traversalDirection) {
- this.nodes = new LinkedHashSet<>();
- this.nodesBuffer = new LinkedList<>();
- this.traversalDirection = traversalDirection;
-
- nodesWithoutParent.offer(traversalDirection.root(dag));
- }
-
- @Segment(name = "travelNext", category = "application", library = "kamon")
- @Override
- public void next() {
- nodes.addAll(nodesBuffer);
- nodesBuffer.clear();
- boolean buffered = false;
-
- while (!nodesWithoutParent.isEmpty() && !buffered) {
- Node<T> node = nodesWithoutParent.poll();
- nodes.add(node);
-
- for (Node<T> child : traversalDirection.children(node)) {
- nodeParents.computeIfAbsent(child.id(), id -> new HashSet<>(traversalDirection.parents(child)));
- nodeParents.get(child.id()).remove(node);
-
- if (nodeParents.get(child.id()).isEmpty()) {
- nodesWithoutParent.offer(child);
- nodesBuffer.add(child);
- buffered = true;
- }
- }
- }
- }
-
- @Override
- public boolean hasNext() {
- return !nodesWithoutParent.isEmpty();
- }
-
- @Override
- public Collection<Node<T>> nodes() {
- return nodes;
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/dag/FromLeafTraversalDirection.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/dag/FromLeafTraversalDirection.java
deleted file mode 100644
index d97c40f..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/dag/FromLeafTraversalDirection.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core.dag;
-
-import java.util.Set;
-
-public class FromLeafTraversalDirection<T> implements TraversalDirection<T> {
-
- @Override
- public Node<T> root(SingleLeafDirectedAcyclicGraph<T> dag) {
- return dag.leaf();
- }
-
- @Override
- public Set<Node<T>> parents(Node<T> node) {
- return node.children();
- }
-
- @Override
- public Set<Node<T>> children(Node<T> node) {
- return node.parents();
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/dag/FromRootTraversalDirection.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/dag/FromRootTraversalDirection.java
deleted file mode 100644
index 8c664ac..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/dag/FromRootTraversalDirection.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core.dag;
-
-import java.util.Set;
-
-public class FromRootTraversalDirection<T> implements TraversalDirection<T> {
-
- @Override
- public Node<T> root(SingleLeafDirectedAcyclicGraph<T> dag) {
- return dag.root();
- }
-
- @Override
- public Set<Node<T>> parents(Node<T> node) {
- return node.parents();
- }
-
- @Override
- public Set<Node<T>> children(Node<T> node) {
- return node.children();
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/dag/GraphBasedSagaFactory.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/dag/GraphBasedSagaFactory.java
deleted file mode 100644
index 2048383..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/dag/GraphBasedSagaFactory.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core.dag;
-
-import java.util.Set;
-import java.util.concurrent.Executor;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import org.apache.servicecomb.saga.core.EventStore;
-import org.apache.servicecomb.saga.core.GraphBasedSaga;
-import org.apache.servicecomb.saga.core.Saga;
-import org.apache.servicecomb.saga.core.SagaContext;
-import org.apache.servicecomb.saga.core.SagaContextImpl;
-import org.apache.servicecomb.saga.core.application.SagaFactory;
-import org.apache.servicecomb.saga.infrastructure.ContextAwareEventStore;
-import org.apache.servicecomb.saga.core.PersistentStore;
-import org.apache.servicecomb.saga.core.SagaDefinition;
-import org.apache.servicecomb.saga.core.SagaTaskFactory;
-import org.apache.servicecomb.saga.core.application.interpreter.FromJsonFormat;
-
-public class GraphBasedSagaFactory implements SagaFactory {
- private final AtomicBoolean isRunning = new AtomicBoolean(true);
- private final FromJsonFormat<Set<String>> childrenExtractor;
- private final Executor executorService;
- private final GraphBuilder graphBuilder;
- private final SagaTaskFactory sagaTaskFactory;
-
- public GraphBasedSagaFactory(int retryDelay,
- PersistentStore persistentStore,
- FromJsonFormat<Set<String>> childrenExtractor,
- ExecutorService executorService) {
-
- this.childrenExtractor = childrenExtractor;
- this.executorService = executorService;
- this.sagaTaskFactory = new SagaTaskFactory(retryDelay, persistentStore);
- this.graphBuilder = new GraphBuilder(new GraphCycleDetectorImpl<>());
- }
-
- @Override
- public Saga createSaga(String requestJson, String sagaId, EventStore sagaLog, SagaDefinition definition) {
- SagaContext sagaContext = new SagaContextImpl(childrenExtractor);
-
- return new GraphBasedSaga(
- sagaLog,
- executorService,
- sagaTaskFactory.sagaTasks(sagaId,
- requestJson,
- definition.policy(),
- new ContextAwareEventStore(sagaLog, sagaContext)
- ),
- sagaContext,
- graphBuilder.build(definition.requests()));
- }
-
- @Override
- public boolean isTerminated() {
- return !isRunning.get();
- }
-
- @Override
- public void terminate() throws Exception {
- isRunning.compareAndSet(true, false);
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/dag/GraphBuilder.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/dag/GraphBuilder.java
deleted file mode 100644
index 578cbb9..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/dag/GraphBuilder.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core.dag;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.servicecomb.saga.core.NoOpSagaRequest;
-import org.apache.servicecomb.saga.core.SagaException;
-import org.apache.servicecomb.saga.core.SagaRequest;
-
-import kamon.annotation.EnableKamon;
-import kamon.annotation.Segment;
-
-@EnableKamon
-public class GraphBuilder {
-
- private final GraphCycleDetector<SagaRequest> detector;
-
- public GraphBuilder(GraphCycleDetector<SagaRequest> detector) {
- this.detector = detector;
- }
-
- @Segment(name = "buildGraph", category = "application", library = "kamon")
- public SingleLeafDirectedAcyclicGraph<SagaRequest> build(SagaRequest[] sagaRequests) {
- Map<String, Node<SagaRequest>> requestNodes = requestsToNodes(sagaRequests);
-
- SingleLeafDirectedAcyclicGraph<SagaRequest> graph = linkNodesToGraph(sagaRequests, requestNodes);
- detectCycle(graph);
- return graph;
- }
-
- private SingleLeafDirectedAcyclicGraph<SagaRequest> linkNodesToGraph(
- SagaRequest[] sagaRequests,
- Map<String, Node<SagaRequest>> requestNodes) {
-
- Node<SagaRequest> root = rootNode(0);
- Node<SagaRequest> leaf = leafNode(sagaRequests.length + 1);
-
- for (SagaRequest sagaRequest : sagaRequests) {
- if (isOrphan(sagaRequest)) {
- root.addChild(requestNodes.get(sagaRequest.id()));
- } else {
- for (String parent : sagaRequest.parents()) {
- requestNodes.get(parent).addChild(requestNodes.get(sagaRequest.id()));
- }
- }
- }
-
- requestNodes.values().stream()
- .filter((node) -> node.children().isEmpty())
- .forEach(node -> node.addChild(leaf));
-
- return new SingleLeafDirectedAcyclicGraph<>(root, leaf);
- }
-
- private Node<SagaRequest> rootNode(int id) {
- return new Node<>(
- id,
- NoOpSagaRequest.SAGA_START_REQUEST);
- }
-
- private Node<SagaRequest> leafNode(int id) {
- return new Node<>(
- id,
- NoOpSagaRequest.SAGA_END_REQUEST);
- }
-
- private boolean isOrphan(SagaRequest sagaRequest) {
- return sagaRequest.parents().length == 0;
- }
-
- private Map<String, Node<SagaRequest>> requestsToNodes(SagaRequest[] sagaRequests) {
- long index = 1;
- Map<String, Node<SagaRequest>> requestMap = new HashMap<>();
- for (SagaRequest sagaRequest : sagaRequests) {
- if (requestMap.containsKey(sagaRequest.id())) {
- // TODO: 8/20/2017 add random id if user didn't provide one
- throw new SagaException("Failed to interpret requests with duplicate request id: " + sagaRequest.id());
- }
- requestMap.put(sagaRequest.id(), new Node<>(index++, sagaRequest));
- }
- return requestMap;
- }
-
- private void detectCycle(SingleLeafDirectedAcyclicGraph<SagaRequest> graph) {
- Set<Node<SagaRequest>> jointNodes = detector.cycleJoints(graph);
-
- if (!jointNodes.isEmpty()) {
- throw new SagaException("Cycle detected in the request graph at nodes " + jointNodes);
- }
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/dag/GraphCycleDetector.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/dag/GraphCycleDetector.java
deleted file mode 100644
index 9b12bc8..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/dag/GraphCycleDetector.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core.dag;
-
-import java.util.Set;
-
-public interface GraphCycleDetector<T> {
-
- Set<Node<T>> cycleJoints(SingleLeafDirectedAcyclicGraph<T> graph);
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/dag/GraphCycleDetectorImpl.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/dag/GraphCycleDetectorImpl.java
deleted file mode 100644
index 6011a98..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/dag/GraphCycleDetectorImpl.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core.dag;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Queue;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-/**
- * Cycle detection is based on topological sort with Kahn's algorithm.
- *
- * @see <a href="https://en.wikipedia.org/wiki/Topological_sorting">Topological Sorting</a>
- */
-public class GraphCycleDetectorImpl<T> implements GraphCycleDetector<T> {
-
- @Override
- public Set<Node<T>> cycleJoints(SingleLeafDirectedAcyclicGraph<T> graph) {
- Queue<Node<T>> orphanNodes = new LinkedList<>();
- Map<Node<T>, Set<Node<T>>> nodeParents = new HashMap<>();
-
- orphanNodes.add(graph.root());
-
- traverse(orphanNodes, nodeParents);
-
- return unvisitedNodes(nodeParents);
- }
-
- private void traverse(Queue<Node<T>> orphanNodes, Map<Node<T>, Set<Node<T>>> nodeParents) {
- while (!orphanNodes.isEmpty()) {
- Node<T> node = orphanNodes.poll();
-
- node.children().forEach(child -> {
- nodeParents.computeIfAbsent(child, n -> new HashSet<>(child.parents()))
- .remove(node);
-
- if (nodeParents.get(child).isEmpty()) {
- orphanNodes.add(child);
- }
- });
- }
- }
-
- private Set<Node<T>> unvisitedNodes(Map<Node<T>, Set<Node<T>>> nodeParents) {
- return nodeParents.entrySet()
- .parallelStream()
- .filter(parents -> !parents.getValue().isEmpty())
- .map(Entry::getKey)
- .collect(Collectors.toSet());
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/dag/Node.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/dag/Node.java
deleted file mode 100644
index 0b3be0a..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/dag/Node.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core.dag;
-
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Objects;
-import java.util.Set;
-
-public class Node<T> {
- private final long id;
- private final T value;
- private final Set<Node<T>> children = new HashSet<>();
- private final Set<Node<T>> parents = new HashSet<>();
-
- public Node(long id, T value) {
- this.id = id;
- this.value = value;
- }
-
- long id() {
- return id;
- }
-
- public T value() {
- return value;
- }
-
- Set<Node<T>> parents() {
- return parents;
- }
-
- public Set<Node<T>> children() {
- return children;
- }
-
- public void addChild(Node<T> node) {
- children.add(node);
- node.parents.add(this);
- }
-
- public void addChildren(Collection<Node<T>> nodes) {
- children.addAll(nodes);
- nodes.forEach(node -> node.parents.add(this));
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
- Node<?> node = (Node<?>) o;
- return id == node.id;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(id);
- }
-
- @Override
- public String toString() {
- return "Node{" +
- "id=" + id +
- ", value=" + value +
- '}';
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/dag/SingleLeafDirectedAcyclicGraph.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/dag/SingleLeafDirectedAcyclicGraph.java
deleted file mode 100644
index cf0d19b..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/dag/SingleLeafDirectedAcyclicGraph.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core.dag;
-
-public class SingleLeafDirectedAcyclicGraph<T> {
-
- private final Node<T> root;
- private final Node<T> leaf;
-
- public SingleLeafDirectedAcyclicGraph(Node<T> root, Node<T> leaf) {
-
- this.root = root;
- this.leaf = leaf;
- }
-
- public Node<T> root() {
- return root;
- }
-
- Node<T> leaf() {
- return leaf;
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/dag/Traveller.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/dag/Traveller.java
deleted file mode 100644
index e44848b..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/dag/Traveller.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core.dag;
-
-import java.util.Collection;
-
-public interface Traveller<T> {
-
- void next();
-
- boolean hasNext();
-
- Collection<Node<T>> nodes();
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/core/dag/TraversalDirection.java b/saga-core/src/main/java/org/apache/servicecomb/saga/core/dag/TraversalDirection.java
deleted file mode 100644
index 22f7343..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/core/dag/TraversalDirection.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core.dag;
-
-import java.util.Set;
-
-public interface TraversalDirection<T> {
-
- Node<T> root(SingleLeafDirectedAcyclicGraph<T> dag);
-
- Set<Node<T>> parents(Node<T> node);
-
- Set<Node<T>> children(Node<T> node);
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/infrastructure/ContextAwareEventStore.java b/saga-core/src/main/java/org/apache/servicecomb/saga/infrastructure/ContextAwareEventStore.java
deleted file mode 100644
index 40fa71d..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/infrastructure/ContextAwareEventStore.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.infrastructure;
-
-import java.util.Iterator;
-
-import org.apache.servicecomb.saga.core.EventEnvelope;
-import org.apache.servicecomb.saga.core.EventStore;
-import org.apache.servicecomb.saga.core.SagaContext;
-import org.apache.servicecomb.saga.core.SagaEvent;
-
-public class ContextAwareEventStore implements EventStore {
- private final EventStore eventStore;
- private final SagaContext sagaContext;
-
- public ContextAwareEventStore(EventStore eventStore, SagaContext sagaContext) {
- this.eventStore = eventStore;
- this.sagaContext = sagaContext;
- }
-
- @Override
- public void offer(SagaEvent sagaEvent) {
- sagaEvent.gatherTo(sagaContext);
- eventStore.offer(sagaEvent);
- }
-
- @Override
- public void populate(Iterable<EventEnvelope> events) {
- eventStore.populate(events);
- }
-
- @Override
- public long size() {
- return eventStore.size();
- }
-
- @Override
- public Iterator<SagaEvent> iterator() {
- return eventStore.iterator();
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/infrastructure/EmbeddedEventStore.java b/saga-core/src/main/java/org/apache/servicecomb/saga/infrastructure/EmbeddedEventStore.java
deleted file mode 100644
index d342264..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/infrastructure/EmbeddedEventStore.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.infrastructure;
-
-import java.lang.invoke.MethodHandles;
-import java.util.Iterator;
-import java.util.Queue;
-import java.util.concurrent.LinkedBlockingQueue;
-
-import org.apache.servicecomb.saga.core.EventEnvelope;
-import org.apache.servicecomb.saga.core.EventStore;
-import org.apache.servicecomb.saga.core.SagaEvent;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class EmbeddedEventStore implements EventStore {
- private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
- private final Queue<SagaEvent> events = new LinkedBlockingQueue<>();
-
- @Override
- public void offer(SagaEvent sagaEvent) {
- events.offer(sagaEvent);
- log.info("Added event {}", sagaEvent);
- }
-
- @Override
- public void populate(Iterable<EventEnvelope> events) {
- for (EventEnvelope event : events) {
- this.events.offer(event.event);
- log.info("Populated event {}", event);
- }
- }
-
- @Override
- public long size() {
- return events.size();
- }
-
- @Override
- public Iterator<SagaEvent> iterator() {
- return events.iterator();
- }
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/transports/RestTransport.java b/saga-core/src/main/java/org/apache/servicecomb/saga/transports/RestTransport.java
deleted file mode 100644
index 3d5bda3..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/transports/RestTransport.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.transports;
-
-import org.apache.servicecomb.saga.core.SagaResponse;
-import org.apache.servicecomb.saga.core.Transport;
-import java.util.Map;
-
-public interface RestTransport extends Transport {
-
- SagaResponse with(String address, String path, String method, Map<String, Map<String, String>> params);
-}
diff --git a/saga-core/src/main/java/org/apache/servicecomb/saga/transports/TransportFactory.java b/saga-core/src/main/java/org/apache/servicecomb/saga/transports/TransportFactory.java
deleted file mode 100644
index b34b5bd..0000000
--- a/saga-core/src/main/java/org/apache/servicecomb/saga/transports/TransportFactory.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.transports;
-
-public interface TransportFactory {
-
- RestTransport restTransport();
-}
diff --git a/saga-core/src/test/java/org/apache/servicecomb/saga/core/BackwardRecoveryTest.java b/saga-core/src/test/java/org/apache/servicecomb/saga/core/BackwardRecoveryTest.java
deleted file mode 100644
index 4f03992..0000000
--- a/saga-core/src/test/java/org/apache/servicecomb/saga/core/BackwardRecoveryTest.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-import static com.seanyinx.github.unit.scaffolding.AssertUtils.expectFailing;
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import org.junit.Before;
-import org.junit.Test;
-
-public class BackwardRecoveryTest {
-
- private final String serviceName = "aaa";
- private final Transaction transaction = mock(Transaction.class);
- private final SagaTask sagaTask = mock(SagaTask.class);
- private final SagaRequest sagaRequest = mock(SagaRequest.class);
- private final SagaResponse parentResponse = mock(SagaResponse.class);
- private final BackwardRecovery backwardRecovery = new BackwardRecovery();
- private final RuntimeException exception = new RuntimeException("oops");
-
- @Before
- public void setUp() throws Exception {
- when(sagaRequest.serviceName()).thenReturn(serviceName);
- when(sagaRequest.transaction()).thenReturn(transaction);
- }
-
- @Test
- public void blowsUpWhenTaskIsNotCommitted() {
- doThrow(exception).when(transaction).send(serviceName, parentResponse);
-
- try {
- backwardRecovery.apply(sagaTask, sagaRequest, parentResponse);
- expectFailing(RuntimeException.class);
- } catch (RuntimeException ignored) {
- }
-
- verify(sagaTask).abort(sagaRequest, exception);
- }
-}
diff --git a/saga-core/src/test/java/org/apache/servicecomb/saga/core/CompensationImpl.java b/saga-core/src/test/java/org/apache/servicecomb/saga/core/CompensationImpl.java
deleted file mode 100644
index c974bc4..0000000
--- a/saga-core/src/test/java/org/apache/servicecomb/saga/core/CompensationImpl.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-import java.util.Map;
-
-public class CompensationImpl extends RestOperation implements Compensation {
-
- public CompensationImpl(String path, String method, Map<String, Map<String, String>> params) {
- super(path, method, params);
- }
-}
diff --git a/saga-core/src/test/java/org/apache/servicecomb/saga/core/CompositeSagaLogTest.java b/saga-core/src/test/java/org/apache/servicecomb/saga/core/CompositeSagaLogTest.java
deleted file mode 100644
index c7dea51..0000000
--- a/saga-core/src/test/java/org/apache/servicecomb/saga/core/CompositeSagaLogTest.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-import static com.seanyinx.github.unit.scaffolding.AssertUtils.expectFailing;
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-
-import org.junit.Test;
-
-public class CompositeSagaLogTest {
-
- private final SagaRequest request = mock(SagaRequest.class);
- private final DummyEvent sagaEvent = new DummyEvent(request);
- private final SagaLog embedded = mock(SagaLog.class);
- private final SagaLog persistent = mock(SagaLog.class);
-
- private final SagaLog compositeSagaLog = new CompositeSagaLog(embedded, persistent);
-
- @Test
- public void addsLogsToEmbeddedOnlyAfterPersisted() {
- doThrow(RuntimeException.class).when(persistent).offer(sagaEvent);
-
- try {
- compositeSagaLog.offer(sagaEvent);
- expectFailing(RuntimeException.class);
- } catch (RuntimeException ignored) {
- }
-
- verify(embedded, never()).offer(sagaEvent);
- }
-}
diff --git a/saga-core/src/test/java/org/apache/servicecomb/saga/core/CompositeSagaResponseTest.java b/saga-core/src/test/java/org/apache/servicecomb/saga/core/CompositeSagaResponseTest.java
deleted file mode 100644
index be4b9f4..0000000
--- a/saga-core/src/test/java/org/apache/servicecomb/saga/core/CompositeSagaResponseTest.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-import static java.util.Arrays.asList;
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
-import static org.mockito.Mockito.when;
-
-import org.junit.Test;
-import org.mockito.Mockito;
-
-public class CompositeSagaResponseTest {
-
- private final SagaResponse response1 = Mockito.mock(SagaResponse.class);
- private final SagaResponse response2 = Mockito.mock(SagaResponse.class);
-
- private final SagaResponse compositeSagaResponse = new CompositeSagaResponse(asList(response1, response2));
-
- @Test
- public void succeededOnlyWhenAllAreSuccessful() throws Exception {
- when(response1.succeeded()).thenReturn(true);
- when(response2.succeeded()).thenReturn(true);
-
- assertThat(compositeSagaResponse.succeeded(), is(true));
- }
-
- @Test
- public void failedWhenAnyIsNotSuccessful() throws Exception {
- when(response1.succeeded()).thenReturn(true);
- when(response2.succeeded()).thenReturn(false);
-
- assertThat(compositeSagaResponse.succeeded(), is(false));
- }
-
- @Test
- public void bodyCombinesAllResponseBodies() throws Exception {
- when(response1.body()).thenReturn("{\n"
- + " \"status\": 500,\n"
- + " \"body\" : \"oops\"\n"
- + "}\n");
-
- when(response2.body()).thenReturn("{\n"
- + " \"status\": 200,\n"
- + " \"body\" : \"blah\"\n"
- + "}\n");
-
- assertThat(compositeSagaResponse.body(), is("[{\n"
- + " \"status\": 500,\n"
- + " \"body\" : \"oops\"\n"
- + "}\n"
- + ", {\n"
- + " \"status\": 200,\n"
- + " \"body\" : \"blah\"\n"
- + "}\n"
- + "]"));
- }
-}
diff --git a/saga-core/src/test/java/org/apache/servicecomb/saga/core/DummyEvent.java b/saga-core/src/test/java/org/apache/servicecomb/saga/core/DummyEvent.java
deleted file mode 100644
index c775afe..0000000
--- a/saga-core/src/test/java/org/apache/servicecomb/saga/core/DummyEvent.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-public class DummyEvent extends SagaEvent {
-
- DummyEvent(SagaRequest payload) {
- super("0", payload);
- }
-
- @Override
- public void gatherTo(EventContext sagaContext) {
-
- }
-
-}
diff --git a/saga-core/src/test/java/org/apache/servicecomb/saga/core/FallbackPolicyTest.java b/saga-core/src/test/java/org/apache/servicecomb/saga/core/FallbackPolicyTest.java
deleted file mode 100644
index a2d1f32..0000000
--- a/saga-core/src/test/java/org/apache/servicecomb/saga/core/FallbackPolicyTest.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-import static com.seanyinx.github.unit.scaffolding.Randomness.uniquify;
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mockito;
-
-public class FallbackPolicyTest {
-
- private final int numberOfRetries = 3;
- private final String address = uniquify("address");
-
- private final SagaResponse success = Mockito.mock(SagaResponse.class);
- private final SagaResponse failure = Mockito.mock(SagaResponse.class);
- private final Fallback fallback = Mockito.mock(Fallback.class);
- private final Compensation compensation = Mockito.mock(Compensation.class);
- private final FallbackPolicy fallbackPolicy = new FallbackPolicy(100);
-
- @SuppressWarnings("ThrowableInstanceNeverThrown")
- private final RuntimeException exception = new RuntimeException("oops");
-
- @Before
- public void setUp() throws Exception {
- when(compensation.retries()).thenReturn(numberOfRetries);
- when(fallback.send(address)).thenReturn(failure);
- }
-
- @Test
- public void retriesTransportForSpecifiedTimes() {
- when(compensation.send(address))
- .thenThrow(exception)
- .thenThrow(exception)
- .thenReturn(success);
-
- SagaResponse response = fallbackPolicy.apply(address, compensation, fallback);
-
- assertThat(response, is(success));
- verify(compensation, times(3)).send(address);
- }
-
- @Test
- public void fallbackIfTransportFailedWithRetry() {
- when(compensation.send(address)).thenThrow(exception);
-
- SagaResponse response = fallbackPolicy.apply(address, compensation, fallback);
- assertThat(response, is(failure));
-
- verify(compensation, times(numberOfRetries + 1)).send(address);
- verify(fallback).send(address);
- }
-
- @Test
- public void retryUntilSuccessIfNumberOfRetriesIsNegative() throws InterruptedException {
- reset(compensation);
- when(compensation.retries()).thenReturn(-1);
- when(compensation.send(address))
- .thenThrow(exception, exception, exception, exception, exception)
- .thenReturn(success);
-
- SagaResponse response = fallbackPolicy.apply(address, compensation, fallback);
-
- assertThat(response, is(success));
- verify(fallback, never()).send(anyString());
- }
-}
diff --git a/saga-core/src/test/java/org/apache/servicecomb/saga/core/ForwardRecoveryTest.java b/saga-core/src/test/java/org/apache/servicecomb/saga/core/ForwardRecoveryTest.java
deleted file mode 100644
index e765170..0000000
--- a/saga-core/src/test/java/org/apache/servicecomb/saga/core/ForwardRecoveryTest.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import org.junit.Before;
-import org.junit.Test;
-
-public class ForwardRecoveryTest {
-
- private final SagaTask sagaTask = mock(SagaTask.class);
-
- private final Transaction transaction = mock(Transaction.class);
- private final SagaRequest sagaRequest = mock(SagaRequest.class);
- private final SagaResponse parentResponse = mock(SagaResponse.class);
-
- private final ForwardRecovery forwardRecovery = new ForwardRecovery();
-
- private final String serviceName = "aaa";
-
- @Before
- public void setUp() throws Exception {
- when(sagaRequest.serviceName()).thenReturn(serviceName);
- when(sagaRequest.transaction()).thenReturn(transaction);
- when(sagaRequest.failRetryDelayMilliseconds()).thenReturn(300);
- }
-
- @Test
- public void blowsUpWhenTaskIsNotCommittedWithFailRetryDelaySeconds() throws Exception {
- doThrow(Exception.class).when(transaction).send(serviceName, parentResponse);
-
- Thread t = new Thread(() -> forwardRecovery.apply(sagaTask, sagaRequest, parentResponse));
- t.start();
- Thread.sleep(400);
- t.interrupt();
-
- verify(transaction, times(2)).send(serviceName, parentResponse);
- }
-}
diff --git a/saga-core/src/test/java/org/apache/servicecomb/saga/core/LongIdGeneratorTest.java b/saga-core/src/test/java/org/apache/servicecomb/saga/core/LongIdGeneratorTest.java
deleted file mode 100644
index 775866b..0000000
--- a/saga-core/src/test/java/org/apache/servicecomb/saga/core/LongIdGeneratorTest.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
-
-import org.junit.Test;
-
-public class LongIdGeneratorTest {
-
-
- private final LongIdGenerator generator = new LongIdGenerator();
-
- @Test
- public void generatesLongInSequence() {
- for (long index = 0; index < 10; index++) {
- assertThat(generator.nextId(), is(index + 1));
- }
- }
-}
diff --git a/saga-core/src/test/java/org/apache/servicecomb/saga/core/RestOperationTest.java b/saga-core/src/test/java/org/apache/servicecomb/saga/core/RestOperationTest.java
deleted file mode 100644
index 7f1990d..0000000
--- a/saga-core/src/test/java/org/apache/servicecomb/saga/core/RestOperationTest.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-import static com.seanyinx.github.unit.scaffolding.AssertUtils.expectFailing;
-import static java.util.Collections.emptyMap;
-import static java.util.Collections.singletonMap;
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
-
-import org.junit.Test;
-
-public class RestOperationTest {
-
- @Test
- public void blowsUpWhenGetMethodWithForm() {
- try {
- new RestOperation("blah", "GET", singletonMap("form", emptyMap()));
- expectFailing(IllegalArgumentException.class);
- } catch (IllegalArgumentException e) {
- assertThat(e.getMessage(), is("GET & DELETE request cannot enclose a body"));
- }
- }
-
- @Test
- public void blowsUpWhenGetMethodWithJson() {
- try {
- new RestOperation("blah", "GET", singletonMap("json", emptyMap()));
- expectFailing(IllegalArgumentException.class);
- } catch (IllegalArgumentException e) {
- assertThat(e.getMessage(), is("GET & DELETE request cannot enclose a body"));
- }
- }
-
- @Test
- public void blowsUpWhenDeleteMethodWithForm() {
- try {
- new RestOperation("blah", "DELETE", singletonMap("form", emptyMap()));
- expectFailing(IllegalArgumentException.class);
- } catch (IllegalArgumentException e) {
- assertThat(e.getMessage(), is("GET & DELETE request cannot enclose a body"));
- }
- }
-
- @Test
- public void blowsUpWhenDeleteMethodWithJson() {
- try {
- new RestOperation("blah", "DELETE", singletonMap("json", emptyMap()));
- expectFailing(IllegalArgumentException.class);
- } catch (IllegalArgumentException e) {
- assertThat(e.getMessage(), is("GET & DELETE request cannot enclose a body"));
- }
- }
-
- @Test
- public void blowsUpWhenMethodIsNotSupported() {
- try {
- new RestOperation("blah", "foo", emptyMap());
- expectFailing(IllegalArgumentException.class);
- } catch (IllegalArgumentException e) {
- assertThat(e.getMessage(), is("Unsupported method foo"));
- }
- }
-
- @Test
- public void blowsUpWhenMethodIsNull() {
- try {
- new RestOperation("blah", null, emptyMap());
- expectFailing(IllegalArgumentException.class);
- } catch (IllegalArgumentException e) {
- assertThat(e.getMessage(), is("Unsupported method null"));
- }
- }
-}
diff --git a/saga-core/src/test/java/org/apache/servicecomb/saga/core/RetrySagaLogTest.java b/saga-core/src/test/java/org/apache/servicecomb/saga/core/RetrySagaLogTest.java
deleted file mode 100644
index 6da8f16..0000000
--- a/saga-core/src/test/java/org/apache/servicecomb/saga/core/RetrySagaLogTest.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-
-import static org.awaitility.Awaitility.await;
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-
-import org.junit.Test;
-
-import org.apache.servicecomb.saga.core.SagaTaskFactory.RetrySagaLog;
-
-public class RetrySagaLogTest {
-
- private final PersistentStore persistentStore = mock(PersistentStore.class);
- private final SagaRequest sagaRequest = mock(SagaRequest.class);
- private final SagaEvent dummyEvent = new DummyEvent(sagaRequest);
- private final RetrySagaLog retrySagaLog = new RetrySagaLog(persistentStore, 100);
-
- private volatile boolean interrupted = false;
-
- @Test
- public void retryUntilSuccessWhenEventIsNotPersisted() throws InterruptedException {
- doThrow(RuntimeException.class).
- doThrow(RuntimeException.class).
- doThrow(RuntimeException.class).
- doThrow(RuntimeException.class).
- doThrow(RuntimeException.class).
- doNothing().
- when(persistentStore).offer(dummyEvent);
-
- retrySagaLog.offer(dummyEvent);
-
- verify(persistentStore, times(6)).offer(dummyEvent);
- }
-
- @Test
- public void exitOnInterruption() throws InterruptedException {
- ExecutorService executor = Executors.newSingleThreadExecutor();
-
- Future<?> future = executor.submit(() -> {
- doThrow(RuntimeException.class).when(persistentStore).offer(dummyEvent);
-
- retrySagaLog.offer(dummyEvent);
- interrupted = true;
- });
-
- Thread.sleep(500);
-
- assertThat(future.cancel(true), is(true));
-
- await().atMost(2, TimeUnit.SECONDS).until(() -> interrupted);
- executor.shutdown();
- }
-}
diff --git a/saga-core/src/test/java/org/apache/servicecomb/saga/core/SagaEndTaskTest.java b/saga-core/src/test/java/org/apache/servicecomb/saga/core/SagaEndTaskTest.java
deleted file mode 100644
index 22f5fa1..0000000
--- a/saga-core/src/test/java/org/apache/servicecomb/saga/core/SagaEndTaskTest.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertThat;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.mock;
-
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-
-public class SagaEndTaskTest {
- private final SagaRequest request = mock(SagaRequest.class);
- private final SagaLog sagaLog = mock(SagaLog.class);
-
- private final String sagaId = "0";
- private final SagaEndTask sagaEndTask = new SagaEndTask(sagaId, sagaLog);
-
- @Test
- public void emptyResponseOnSuccessfulEventPersistence() throws Exception {
- ArgumentCaptor<SagaEndedEvent> argumentCaptor = ArgumentCaptor.forClass(SagaEndedEvent.class);
- doNothing().when(sagaLog).offer(argumentCaptor.capture());
-
- sagaEndTask.commit(request, SagaResponse.EMPTY_RESPONSE);
-
- SagaEndedEvent event = argumentCaptor.getValue();
- assertThat(event.sagaId, is(sagaId));
- assertThat(event.json(null), is("{}"));
- assertThat(event.payload(), is(request));
- }
-}
diff --git a/saga-core/src/test/java/org/apache/servicecomb/saga/core/SagaEventMatcher.java b/saga-core/src/test/java/org/apache/servicecomb/saga/core/SagaEventMatcher.java
deleted file mode 100644
index 7e8289c..0000000
--- a/saga-core/src/test/java/org/apache/servicecomb/saga/core/SagaEventMatcher.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-import java.util.Objects;
-
-import org.hamcrest.Description;
-import org.hamcrest.Matcher;
-import org.hamcrest.TypeSafeMatcher;
-
-public class SagaEventMatcher extends TypeSafeMatcher<SagaEvent> {
-
- private final String sagaId;
- private final Operation operation;
- private final Class<?> aClass;
-
- public static Matcher<SagaEvent> eventWith(String sagaId, Operation operation, Class<?> aClass) {
- return new SagaEventMatcher(sagaId, operation, aClass);
- }
-
- static Matcher<SagaEvent> eventWith(Operation operation, Class<?> aClass) {
- return eventWith("0", operation, aClass);
- }
-
- private SagaEventMatcher(String sagaId, Operation operation, Class<?> aClass) {
- this.sagaId = sagaId;
- this.operation = operation;
- this.aClass = aClass;
- }
-
- @Override
- protected void describeMismatchSafely(SagaEvent item, Description description) {
- description
- .appendText("SagaEvent {sagaId=" + item.sagaId + ", operation=" + operation(item) + ", class=" + item.getClass());
- }
-
- @Override
- protected boolean matchesSafely(SagaEvent envelope) {
- return Objects.equals(envelope.sagaId, sagaId)
- && operation(envelope).equals(operation)
- && envelope.getClass().equals(aClass);
- }
-
- @Override
- public void describeTo(Description description) {
- description
- .appendText("SagaEvent {sagaId=" + sagaId + ", operation=" + operation + ", class=" + aClass.getCanonicalName());
- }
-
- private Operation operation(SagaEvent envelope) {
- return operation instanceof Compensation ? envelope.payload().compensation() : envelope.payload().transaction();
- }
-}
diff --git a/saga-core/src/test/java/org/apache/servicecomb/saga/core/SagaExecutionComponentTestBase.java b/saga-core/src/test/java/org/apache/servicecomb/saga/core/SagaExecutionComponentTestBase.java
deleted file mode 100644
index b9e893f..0000000
--- a/saga-core/src/test/java/org/apache/servicecomb/saga/core/SagaExecutionComponentTestBase.java
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-import static org.apache.servicecomb.saga.core.Operation.TYPE_REST;
-import static java.util.Collections.emptyMap;
-import static java.util.Collections.singletonList;
-import static java.util.Collections.singletonMap;
-import static java.util.concurrent.TimeUnit.SECONDS;
-import static org.awaitility.Awaitility.waitAtMost;
-import static org.hamcrest.Matchers.containsInAnyOrder;
-import static org.hamcrest.collection.IsIterableContainingInOrder.contains;
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
-import static org.mockito.Mockito.when;
-
-import java.io.IOException;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.CompletableFuture;
-
-import org.apache.servicecomb.saga.core.application.SagaFactory;
-import org.hamcrest.Description;
-import org.hamcrest.Matcher;
-import org.hamcrest.TypeSafeMatcher;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mockito;
-
-import org.apache.servicecomb.saga.core.application.SagaExecutionComponent;
-import org.apache.servicecomb.saga.core.application.interpreter.FromJsonFormat;
-import org.apache.servicecomb.saga.infrastructure.EmbeddedEventStore;
-
-@SuppressWarnings("unchecked")
-public abstract class SagaExecutionComponentTestBase {
- private static final String requestJson = "[\n"
- + " {\n"
- + " \"id\": \"request-1\",\n"
- + " \"serviceName\": \"aaa\",\n"
- + " \"transaction\": {\n"
- + " \"method\": \"post\",\n"
- + " \"path\": \"/rest/as\"\n"
- + " },\n"
- + " \"compensation\": {\n"
- + " \"method\": \"delete\",\n"
- + " \"path\": \"/rest/as\"\n"
- + " }\n"
- + " }\n"
- + "]\n";
-
- private static final String sagaJson = "{\n"
- + " \"policy\": \"ForwardRecovery\",\n"
- + " \"requests\": " + requestJson + "\n"
- + "}";
-
- private static final String anotherRequestJson = "[\n"
- + " {\n"
- + " \"id\": \"request-2\",\n"
- + " \"serviceName\": \"bbb\",\n"
- + " \"transaction\": {\n"
- + " \"method\": \"post\",\n"
- + " \"path\": \"/rest/bs\"\n"
- + " },\n"
- + " \"compensation\": {\n"
- + " \"method\": \"delete\",\n"
- + " \"path\": \"/rest/bs\"\n"
- + " }\n"
- + " }\n"
- + "]\n";
-
- private static final String anotherSagaJson = "{\n"
- + " \"policy\": \"ForwardRecovery\",\n"
- + " \"requests\": " + anotherRequestJson + "\n"
- + "}";
-
- private final SagaRequest request1 = new SagaRequestImpl(
- "request-1",
- "aaa",
- TYPE_REST,
- new TransactionImpl("/rest/as", "post", emptyMap()),
- new CompensationImpl("/rest/as", "delete", emptyMap())
- );
-
- private final SagaRequest request2 = new SagaRequestImpl(
- "request-2",
- "bbb",
- TYPE_REST,
- new TransactionImpl("/rest/bs", "post", emptyMap()),
- new CompensationImpl("/rest/bs", "delete", emptyMap())
- );
-
- private final SagaDefinition definition1 = new SagaDefinition() {
- @Override
- public RecoveryPolicy policy() {
- return new ForwardRecovery();
- }
-
- @Override
- public SagaRequest[] requests() {
- return new SagaRequest[]{request1};
- }
- };
-
- private final SagaDefinition definition2 = new SagaDefinition() {
- @Override
- public RecoveryPolicy policy() {
- return new BackwardRecovery();
- }
-
- @Override
- public SagaRequest[] requests() {
- return new SagaRequest[]{request2};
- }
- };
-
- private final FromJsonFormat<SagaDefinition> fromJsonFormat = Mockito.mock(FromJsonFormat.class);
- private final EmbeddedPersistentStore eventStore = new EmbeddedPersistentStore();
-
- private final SagaExecutionComponent coordinator = new SagaExecutionComponent(
- eventStore,
- fromJsonFormat,
- null,
- sagaFactory(eventStore)
- );
-
- private final String sagaId = "1";
-
- @Before
- public void setUp() throws Exception {
- when(fromJsonFormat.fromJson(sagaJson)).thenReturn(definition1);
- when(fromJsonFormat.fromJson(anotherSagaJson)).thenReturn(definition2);
- }
-
- @Test
- public void recoverSagaWithEventsFromEventStore() throws IOException {
- eventStore.offer(new SagaStartedEvent(sagaId, sagaJson, NoOpSagaRequest.SAGA_START_REQUEST));
- coordinator.reanimate();
-
- assertThat(eventStore, contains(
- eventWith(NoOpSagaRequest.SAGA_START_REQUEST, SagaStartedEvent.class),
- eventWith(request1, TransactionStartedEvent.class),
- eventWith(request1, TransactionEndedEvent.class),
- eventWith(NoOpSagaRequest.SAGA_END_REQUEST, SagaEndedEvent.class)
- ));
- }
-
- @Test
- public void runSagaWithEventStore() throws IOException {
- SagaResponse response = coordinator.run(sagaJson);
-
- assertThat(response, is(SagaResponse.EMPTY_RESPONSE));
- assertThat(eventStore, contains(
- eventWith(NoOpSagaRequest.SAGA_START_REQUEST, SagaStartedEvent.class),
- eventWith(request1, TransactionStartedEvent.class),
- eventWith(request1, TransactionEndedEvent.class),
- eventWith(NoOpSagaRequest.SAGA_END_REQUEST, SagaEndedEvent.class)
- ));
- }
-
- @Test
- public void processRequestsInParallel() {
- CompletableFuture.runAsync(() -> coordinator.run(sagaJson));
- CompletableFuture.runAsync(() -> coordinator.run(anotherSagaJson));
-
- waitAtMost(2, SECONDS).until(() -> eventStore.size() == 8);
-
- assertThat(eventStore, containsInAnyOrder(
- eventWith(NoOpSagaRequest.SAGA_START_REQUEST, SagaStartedEvent.class),
- eventWith(request1, TransactionStartedEvent.class),
- eventWith(request1, TransactionEndedEvent.class),
- eventWith(NoOpSagaRequest.SAGA_END_REQUEST, SagaEndedEvent.class),
- eventWith(NoOpSagaRequest.SAGA_START_REQUEST, SagaStartedEvent.class),
- eventWith(request2, TransactionStartedEvent.class),
- eventWith(request2, TransactionEndedEvent.class),
- eventWith(NoOpSagaRequest.SAGA_END_REQUEST, SagaEndedEvent.class)
- ));
- }
-
- @Test
- public void runSagaAfterRecovery() throws IOException {
- eventStore.offer(new SagaStartedEvent(sagaId, sagaJson, NoOpSagaRequest.SAGA_START_REQUEST));
- coordinator.reanimate();
-
- coordinator.run(anotherSagaJson);
-
- assertThat(eventStore, contains(
- eventWith(NoOpSagaRequest.SAGA_START_REQUEST, SagaStartedEvent.class),
- eventWith(request1, TransactionStartedEvent.class),
- eventWith(request1, TransactionEndedEvent.class),
- eventWith(NoOpSagaRequest.SAGA_END_REQUEST, SagaEndedEvent.class),
- eventWith(NoOpSagaRequest.SAGA_START_REQUEST, SagaStartedEvent.class),
- eventWith(request2, TransactionStartedEvent.class),
- eventWith(request2, TransactionEndedEvent.class),
- eventWith(NoOpSagaRequest.SAGA_END_REQUEST, SagaEndedEvent.class)
- ));
- }
-
- private Matcher<SagaEvent> eventWith(
- SagaRequest sagaRequest,
- Class<?> type) {
-
- return new TypeSafeMatcher<SagaEvent>() {
- @Override
- protected boolean matchesSafely(SagaEvent event) {
- SagaRequest request = event.payload();
- return sagaRequest.equals(request)
- && event.getClass().equals(type);
- }
-
- @Override
- protected void describeMismatchSafely(SagaEvent item, Description mismatchDescription) {
- SagaRequest request = item.payload();
- mismatchDescription.appendText(
- "SagaEvent {" + request + "}");
- }
-
- @Override
- public void describeTo(Description description) {
- description.appendText(
- "SagaEvent {" + sagaRequest + "}");
- }
- };
- }
-
- private class EmbeddedPersistentStore extends EmbeddedEventStore implements PersistentStore {
-
- @Override
- public Map<String, List<EventEnvelope>> findPendingSagaEvents() {
- return singletonMap(sagaId, singletonList(
- new EventEnvelope(1L, new SagaStartedEvent(sagaId, sagaJson, NoOpSagaRequest.SAGA_START_REQUEST))));
- }
- }
-
- protected abstract SagaFactory sagaFactory(PersistentStore eventStore);
-}
diff --git a/saga-core/src/test/java/org/apache/servicecomb/saga/core/SagaIntegrationTest.java b/saga-core/src/test/java/org/apache/servicecomb/saga/core/SagaIntegrationTest.java
deleted file mode 100644
index d005ee7..0000000
--- a/saga-core/src/test/java/org/apache/servicecomb/saga/core/SagaIntegrationTest.java
+++ /dev/null
@@ -1,687 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-import static com.seanyinx.github.unit.scaffolding.AssertUtils.expectFailing;
-import static org.apache.servicecomb.saga.core.Compensation.SAGA_START_COMPENSATION;
-import static org.apache.servicecomb.saga.core.Operation.TYPE_REST;
-import static org.apache.servicecomb.saga.core.SagaEventMatcher.eventWith;
-import static org.apache.servicecomb.saga.core.SagaResponse.EMPTY_RESPONSE;
-import static org.apache.servicecomb.saga.core.SagaResponse.NONE_RESPONSE;
-import static org.apache.servicecomb.saga.core.SagaTask.SAGA_END_TASK;
-import static org.apache.servicecomb.saga.core.SagaTask.SAGA_REQUEST_TASK;
-import static org.apache.servicecomb.saga.core.SagaTask.SAGA_START_TASK;
-import static org.apache.servicecomb.saga.core.Transaction.SAGA_END_TRANSACTION;
-import static org.apache.servicecomb.saga.core.Transaction.SAGA_START_TRANSACTION;
-import static java.util.Arrays.asList;
-import static java.util.Collections.emptySet;
-import static java.util.Collections.singletonList;
-import static org.hamcrest.Matchers.anyOf;
-import static org.hamcrest.Matchers.is;
-import static org.hamcrest.collection.IsIterableContainingInOrder.contains;
-import static org.junit.Assert.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.Callable;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.CyclicBarrier;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.stubbing.Answer;
-
-import com.seanyinx.github.unit.scaffolding.Randomness;
-
-import org.apache.servicecomb.saga.core.application.interpreter.FromJsonFormat;
-import org.apache.servicecomb.saga.core.dag.Node;
-import org.apache.servicecomb.saga.core.dag.SingleLeafDirectedAcyclicGraph;
-import org.apache.servicecomb.saga.infrastructure.ContextAwareEventStore;
-import org.apache.servicecomb.saga.infrastructure.EmbeddedEventStore;
-
-@SuppressWarnings("unchecked")
-public class SagaIntegrationTest {
- private static final String sagaId = Randomness.uniquify("sagaId");
-
- private final FromJsonFormat<Set<String>> childrenExtractor = mock(FromJsonFormat.class);
- private final SagaContext sagaContext = new SagaContextImpl(childrenExtractor);
- private final IdGenerator<Long> idGenerator = new LongIdGenerator();
- private final EventStore eventStore = new EmbeddedEventStore();
- private final ContextAwareEventStore sagaLog = new ContextAwareEventStore(eventStore, sagaContext);
-
- private final Transaction transaction1 = mock(Transaction.class, "transaction1");
- private final Transaction transaction2 = mock(Transaction.class, "transaction2");
- private final Transaction transaction3 = mock(Transaction.class, "transaction3");
- private final Transaction transaction4 = mock(Transaction.class, "transaction4");
-
- private final Compensation compensation1 = mock(Compensation.class, "compensation1");
- private final Compensation compensation2 = mock(Compensation.class, "compensation2");
- private final Compensation compensation3 = mock(Compensation.class, "compensation3");
- private final Compensation compensation4 = mock(Compensation.class, "compensation4");
-
- private final Fallback fallback1 = mock(Fallback.class, "fallback1");
-
- private final String requestJson = "{}";
- private final SagaRequest request1 = request("request1", "service1", transaction1, compensation1, fallback1);
- private final SagaRequest request2 = request("request2", "service2", transaction2, compensation2, request1.id());
- private final SagaRequest request3 = request("request3", "service3", transaction3, compensation3, request1.id());
- private final SagaRequest request4 = request("request4", "service4", transaction4, compensation4, request3.id());
-
- private final SagaResponse transactionResponse1 = new SuccessfulSagaResponse("transaction1");
- private final SagaResponse transactionResponse2 = new SuccessfulSagaResponse("transaction2");
- private final SagaResponse transactionResponse3 = new SuccessfulSagaResponse("transaction3");
- private final SagaResponse compensationResponse1 = new SuccessfulSagaResponse("compensation1");
- private final SagaResponse compensationResponse2 = new SuccessfulSagaResponse("compensation2");
- private final SagaResponse compensationResponse3 = new SuccessfulSagaResponse("compensation3");
-
- @SuppressWarnings("ThrowableInstanceNeverThrown")
- private final RuntimeException exception = new RuntimeException("oops");
-
- private final Node<SagaRequest> node1 = new Node<>(1, request1);
- private final Node<SagaRequest> node2 = new Node<>(2, request2);
- private final Node<SagaRequest> node3 = new Node<>(3, request3);
- private final Node<SagaRequest> node4 = new Node<>(4, request4);
- private final Node<SagaRequest> root = new Node<>(0, NoOpSagaRequest.SAGA_START_REQUEST);
- private final Node<SagaRequest> leaf = new Node<>(5, NoOpSagaRequest.SAGA_END_REQUEST);
- private final SingleLeafDirectedAcyclicGraph<SagaRequest> sagaTaskGraph = new SingleLeafDirectedAcyclicGraph<>(root, leaf);
-
- private Saga saga;
- private final Map<String, SagaTask> tasks = new HashMap<>();
-
- // root - node1 - node2 - leaf
- @Before
- public void setUp() throws Exception {
- when(childrenExtractor.fromJson(anyString())).thenReturn(emptySet());
- when(childrenExtractor.fromJson(NONE_RESPONSE.body())).thenReturn(setOf("none"));
-
- when(transaction1.send(request1.serviceName(), EMPTY_RESPONSE)).thenReturn(transactionResponse1);
- when(transaction2.send(request2.serviceName(), transactionResponse1)).thenReturn(transactionResponse2);
- when(transaction3.send(request3.serviceName(), transactionResponse1)).thenReturn(transactionResponse3);
-
- when(compensation1.send(request1.serviceName(), compensationResponse2)).thenReturn(compensationResponse1);
- when(compensation2.send(request2.serviceName(), compensationResponse3)).thenReturn(compensationResponse2);
- when(compensation3.send(request3.serviceName(), EMPTY_RESPONSE)).thenReturn(compensationResponse3);
-
- root.addChild(node1);
- node1.addChild(node2);
- node2.addChild(leaf);
-
- SagaStartTask sagaStartTask = new SagaStartTask(sagaId, requestJson, sagaLog);
- SagaEndTask sagaEndTask = new SagaEndTask(sagaId, sagaLog);
- RequestProcessTask processTask = requestProcessTask(new BackwardRecovery());
-
- tasks.put(SAGA_START_TASK, sagaStartTask);
- tasks.put(SAGA_REQUEST_TASK, processTask);
- tasks.put(SAGA_END_TASK, sagaEndTask);
-
- saga = new GraphBasedSaga(eventStore, tasks, sagaContext, sagaTaskGraph);
- }
-
- @Test
- public void transactionsAreRunSuccessfully() {
- saga.run();
-
- assertThat(eventStore, contains(
- eventWith(sagaId, SAGA_START_TRANSACTION, SagaStartedEvent.class),
- eventWith(sagaId, transaction1, TransactionStartedEvent.class),
- eventWith(sagaId, transaction1, TransactionEndedEvent.class),
- eventWith(sagaId, transaction2, TransactionStartedEvent.class),
- eventWith(sagaId, transaction2, TransactionEndedEvent.class),
- eventWith(sagaId, SAGA_END_TRANSACTION, SagaEndedEvent.class)
- ));
-
- verify(transaction1).send(request1.serviceName(), EMPTY_RESPONSE);
- verify(transaction2).send(request2.serviceName(), transactionResponse1);
-
- verify(compensation1, never()).send(request1.serviceName());
- verify(compensation2, never()).send(request2.serviceName());
- }
-
- // root - node1 - node2 - leaf
- // \_ node3 _/
- @Test
- public void compensateCommittedTransactionsOnFailure() {
- addExtraChildToNode1();
-
- // barrier to make sure the two transactions starts at the same time
- CyclicBarrier barrier = new CyclicBarrier(2);
- when(transaction2.send(request2.serviceName(), transactionResponse1))
- .thenAnswer(
- withAnswer(() -> {
- barrier.await();
- Thread.sleep(100);
- throw exception;
- }));
-
- when(transaction3.send(request3.serviceName(), transactionResponse1))
- .thenAnswer(
- withAnswer(() -> {
- barrier.await();
- return transactionResponse3;
- }));
-
- saga.run();
-
- assertThat(eventStore, contains(
- eventWith(sagaId, SAGA_START_TRANSACTION, SagaStartedEvent.class),
- eventWith(sagaId, transaction1, TransactionStartedEvent.class),
- eventWith(sagaId, transaction1, TransactionEndedEvent.class),
- anyOf(eventWith(sagaId, transaction2, TransactionStartedEvent.class), eventWith(sagaId, transaction3, TransactionStartedEvent.class)),
- anyOf(eventWith(sagaId, transaction2, TransactionStartedEvent.class), eventWith(sagaId, transaction3, TransactionStartedEvent.class)),
- eventWith(sagaId, transaction3, TransactionEndedEvent.class),
- eventWith(sagaId, transaction2, TransactionAbortedEvent.class),
- eventWith(sagaId, compensation3, TransactionCompensatedEvent.class),
- eventWith(sagaId, compensation1, TransactionCompensatedEvent.class),
- eventWith(sagaId, SAGA_START_COMPENSATION, SagaEndedEvent.class)));
-
- verify(transaction1).send(request1.serviceName(), EMPTY_RESPONSE);
- verify(transaction2).send(request2.serviceName(), transactionResponse1);
- verify(transaction3).send(request3.serviceName(), transactionResponse1);
-
- verify(compensation1).send(request1.serviceName());
- verify(compensation2, never()).send(request2.serviceName());
- verify(compensation3).send(request3.serviceName());
- }
-
- @Test
- public void skipIgnoredTransaction() throws Exception {
- addExtraChildToNode1();
-
- when(childrenExtractor.fromJson(transactionResponse1.body())).thenReturn(setOf(request3.id()));
-
- saga.run();
-
- assertThat(eventStore, contains(
- eventWith(sagaId, SAGA_START_TRANSACTION, SagaStartedEvent.class),
- eventWith(sagaId, transaction1, TransactionStartedEvent.class),
- eventWith(sagaId, transaction1, TransactionEndedEvent.class),
- eventWith(sagaId, transaction3, TransactionStartedEvent.class),
- eventWith(sagaId, transaction3, TransactionEndedEvent.class),
- eventWith(sagaId, SAGA_END_TRANSACTION, SagaEndedEvent.class)
- ));
-
- verify(transaction1).send(request1.serviceName(), EMPTY_RESPONSE);
- verify(transaction3).send(request3.serviceName(), transactionResponse1);
- verify(transaction2, never()).send(anyString(), any(SagaResponse.class));
-
- verify(compensation1, never()).send(request1.serviceName());
- verify(compensation2, never()).send(request2.serviceName());
- verify(compensation3, never()).send(request3.serviceName());
- }
-
- @Test
- public void skipAllIgnoredTransactions() throws Exception {
- node1.addChild(node3);
- node3.addChild(node4);
- node4.addChild(leaf);
-
- when(childrenExtractor.fromJson(transactionResponse1.body())).thenReturn(setOf("none"));
-
- saga.run();
-
- assertThat(eventStore, contains(
- eventWith(sagaId, SAGA_START_TRANSACTION, SagaStartedEvent.class),
- eventWith(sagaId, transaction1, TransactionStartedEvent.class),
- eventWith(sagaId, transaction1, TransactionEndedEvent.class),
- eventWith(sagaId, SAGA_END_TRANSACTION, SagaEndedEvent.class)
- ));
-
- verify(transaction1).send(request1.serviceName(), EMPTY_RESPONSE);
- verify(transaction2, never()).send(anyString(), any(SagaResponse.class));
- verify(transaction3, never()).send(anyString(), any(SagaResponse.class));
- verify(transaction4, never()).send(anyString(), any(SagaResponse.class));
-
- verify(compensation1, never()).send(request1.serviceName());
- verify(compensation2, never()).send(request2.serviceName());
- verify(compensation3, never()).send(request3.serviceName());
- verify(compensation4, never()).send(request4.serviceName());
- }
-
- @Test
- public void doNotCompensateIgnoredTransactions() throws Exception {
- node1.addChild(node3);
- node3.addChild(node4);
- node4.addChild(leaf);
-
- when(childrenExtractor.fromJson(transactionResponse1.body())).thenReturn(setOf(request3.id()));
-
- when(transaction4.send(request4.serviceName(), transactionResponse3)).thenThrow(exception);
-
- saga.run();
-
- assertThat(eventStore, contains(
- eventWith(sagaId, SAGA_START_TRANSACTION, SagaStartedEvent.class),
- eventWith(sagaId, transaction1, TransactionStartedEvent.class),
- eventWith(sagaId, transaction1, TransactionEndedEvent.class),
- eventWith(sagaId, transaction3, TransactionStartedEvent.class),
- eventWith(sagaId, transaction3, TransactionEndedEvent.class),
- eventWith(sagaId, transaction4, TransactionStartedEvent.class),
- eventWith(sagaId, transaction4, TransactionAbortedEvent.class),
- eventWith(sagaId, transaction3, TransactionCompensatedEvent.class),
- eventWith(sagaId, transaction1, TransactionCompensatedEvent.class),
- eventWith(sagaId, SAGA_START_COMPENSATION, SagaEndedEvent.class)
- ));
-
- verify(transaction1).send(request1.serviceName(), EMPTY_RESPONSE);
- verify(transaction3).send(request3.serviceName(), transactionResponse1);
- verify(transaction4).send(request4.serviceName(), transactionResponse3);
- verify(transaction2, never()).send(anyString(), any(SagaResponse.class));
-
- verify(compensation1).send(request1.serviceName());
- verify(compensation3).send(request3.serviceName());
- verify(compensation2, never()).send(request2.serviceName());
- verify(compensation4, never()).send(request4.serviceName());
- }
-
- // root - node1 - node2 - leaf
- // \_ node3 _/
- @Test
- public void redoHangingTransactionsOnFailure() throws InterruptedException {
- addExtraChildToNode1();
-
- // barrier to make sure the two transactions starts at the same time
- CyclicBarrier barrier = new CyclicBarrier(2);
- when(transaction3.send(request3.serviceName(), transactionResponse1))
- .thenAnswer(withAnswer(() -> {
- barrier.await();
- throw exception;
- }));
-
- CountDownLatch latch = new CountDownLatch(1);
-
- when(transaction2.send(request2.serviceName(), transactionResponse1))
- .thenAnswer(withAnswer(() -> {
- barrier.await();
- latch.await();
- return transactionResponse2;
- })).thenReturn(transactionResponse2);
-
- saga.run();
-
- // the ordering of events may not be consistence due to concurrent processing of requests
- assertThat(eventStore, contains(
- eventWith(sagaId, SAGA_START_TRANSACTION, SagaStartedEvent.class),
- eventWith(sagaId, transaction1, TransactionStartedEvent.class),
- eventWith(sagaId, transaction1, TransactionEndedEvent.class),
- anyOf(
- eventWith(sagaId, transaction2, TransactionStartedEvent.class),
- eventWith(sagaId, transaction3, TransactionStartedEvent.class)),
- anyOf(
- eventWith(sagaId, transaction3, TransactionStartedEvent.class),
- eventWith(sagaId, transaction2, TransactionStartedEvent.class)),
- eventWith(sagaId, transaction3, TransactionAbortedEvent.class),
- eventWith(sagaId, transaction2, TransactionStartedEvent.class),
- eventWith(sagaId, transaction2, TransactionEndedEvent.class),
- eventWith(sagaId, compensation2, TransactionCompensatedEvent.class),
- eventWith(sagaId, compensation1, TransactionCompensatedEvent.class),
- eventWith(sagaId, SAGA_START_COMPENSATION, SagaEndedEvent.class)));
-
- verify(transaction1).send(request1.serviceName(), EMPTY_RESPONSE);
- verify(transaction2, times(2)).send(request2.serviceName(), transactionResponse1);
- verify(transaction3).send(request3.serviceName(), transactionResponse1);
-
- verify(compensation1).send(request1.serviceName());
- verify(compensation2).send(request2.serviceName());
- verify(compensation3, never()).send(request3.serviceName());
-
- latch.countDown();
- }
-
- @Test
- public void retriesFailedTransactionTillSuccess() {
- RequestProcessTask processTask = requestProcessTask(new ForwardRecovery());
- tasks.put(SAGA_REQUEST_TASK, processTask);
-
- when(transaction2.send(request2.serviceName(), transactionResponse1))
- .thenThrow(exception).thenThrow(exception).thenReturn(transactionResponse2);
-
- saga.run();
-
- assertThat(eventStore, contains(
- eventWith(sagaId, SAGA_START_TRANSACTION, SagaStartedEvent.class),
- eventWith(sagaId, transaction1, TransactionStartedEvent.class),
- eventWith(sagaId, transaction1, TransactionEndedEvent.class),
- eventWith(sagaId, transaction2, TransactionStartedEvent.class),
- eventWith(sagaId, transaction2, TransactionEndedEvent.class),
- eventWith(sagaId, SAGA_END_TRANSACTION, SagaEndedEvent.class)
- ));
-
- verify(transaction1).send(request1.serviceName(), EMPTY_RESPONSE);
- verify(transaction2, times(3)).send(request2.serviceName(), transactionResponse1);
-
- verify(compensation1, never()).send(anyString(), any(SagaResponse.class));
- verify(compensation2, never()).send(anyString(), any(SagaResponse.class));
- }
-
- @Test
- public void fallbackWhenCompensationFailed() {
- int retries = 3;
-
- when(transaction2.send(request2.serviceName(), transactionResponse1)).thenThrow(exception);
- when(compensation1.send(request1.serviceName())).thenThrow(exception);
- when(compensation1.retries()).thenReturn(retries);
-
- saga.run();
-
- verify(transaction1).send(request1.serviceName(), EMPTY_RESPONSE);
- verify(transaction2).send(request2.serviceName(), transactionResponse1);
-
- verify(compensation1, times(retries + 1)).send(request1.serviceName());
- verify(compensation2, never()).send(request2.serviceName());
-
- verify(fallback1).send(request1.serviceName());
- }
-
- @Test
- public void restoresSagaToTransactionStateByPlayingAllEvents() {
- addExtraChildToNode1();
-
- Iterable<EventEnvelope> events = asList(
- envelope(new SagaStartedEvent(sagaId, requestJson, NoOpSagaRequest.SAGA_START_REQUEST)),
- envelope(new TransactionStartedEvent(sagaId, request1)),
- envelope(new TransactionEndedEvent(sagaId, request1, transactionResponse1)),
- envelope(new TransactionStartedEvent(sagaId, request2)),
- envelope(new TransactionEndedEvent(sagaId, request2, transactionResponse2))
- );
-
- eventStore.populate(events);
- saga.play();
-
- saga.run();
- assertThat(eventStore, contains(
- eventWith(sagaId, SAGA_START_TRANSACTION, SagaStartedEvent.class),
- eventWith(sagaId, transaction1, TransactionStartedEvent.class),
- eventWith(sagaId, transaction1, TransactionEndedEvent.class),
- eventWith(sagaId, transaction2, TransactionStartedEvent.class),
- eventWith(sagaId, transaction2, TransactionEndedEvent.class),
- eventWith(sagaId, transaction3, TransactionStartedEvent.class),
- eventWith(sagaId, transaction3, TransactionEndedEvent.class),
- eventWith(sagaId, SAGA_END_TRANSACTION, SagaEndedEvent.class)
- ));
-
- verify(transaction1, never()).send(anyString(), any(SagaResponse.class));
- verify(transaction2, never()).send(anyString(), any(SagaResponse.class));
- verify(transaction3).send(request3.serviceName(), transactionResponse1);
-
- verify(compensation1, never()).send(request1.serviceName());
- verify(compensation2, never()).send(request2.serviceName());
- verify(compensation3, never()).send(request3.serviceName());
- }
-
- @Test
- public void restoresPartialTransactionByPlayingAllEvents() {
- addExtraChildToNode1();
-
- Iterable<EventEnvelope> events = asList(
- envelope(new SagaStartedEvent(sagaId, requestJson, NoOpSagaRequest.SAGA_START_REQUEST)),
- envelope(new TransactionStartedEvent(sagaId, request1)),
- envelope(new TransactionEndedEvent(sagaId, request1, transactionResponse1)),
- envelope(new TransactionStartedEvent(sagaId, request2)),
- envelope(new TransactionEndedEvent(sagaId, request2, transactionResponse2)),
- envelope(new TransactionStartedEvent(sagaId, request3))
- );
-
- eventStore.populate(events);
- saga.play();
-
- saga.run();
- assertThat(eventStore, contains(
- eventWith(sagaId, SAGA_START_TRANSACTION, SagaStartedEvent.class),
- eventWith(sagaId, transaction1, TransactionStartedEvent.class),
- eventWith(sagaId, transaction1, TransactionEndedEvent.class),
- eventWith(sagaId, transaction2, TransactionStartedEvent.class),
- eventWith(sagaId, transaction2, TransactionEndedEvent.class),
- eventWith(sagaId, transaction3, TransactionStartedEvent.class),
- eventWith(sagaId, transaction3, TransactionStartedEvent.class),
- eventWith(sagaId, transaction3, TransactionEndedEvent.class),
- eventWith(sagaId, SAGA_END_TRANSACTION, SagaEndedEvent.class)
- ));
-
- verify(transaction1, never()).send(anyString(), any(SagaResponse.class));
- verify(transaction2, never()).send(anyString(), any(SagaResponse.class));
- verify(transaction3).send(request3.serviceName(), transactionResponse1);
-
- verify(compensation1, never()).send(request1.serviceName());
- verify(compensation2, never()).send(request2.serviceName());
- verify(compensation3, never()).send(request3.serviceName());
- }
-
- @Test
- public void restoresToCompensationFromAbortedTransactionByPlayingAllEvents() {
- addExtraChildToNode1();
-
- Iterable<EventEnvelope> events = asList(
- envelope(new SagaStartedEvent(sagaId, requestJson, NoOpSagaRequest.SAGA_START_REQUEST)),
- envelope(new TransactionStartedEvent(sagaId, request1)),
- envelope(new TransactionEndedEvent(sagaId, request1)),
- envelope(new TransactionStartedEvent(sagaId, request2)),
- envelope(new TransactionEndedEvent(sagaId, request2)),
- envelope(new TransactionStartedEvent(sagaId, request3)),
- envelope(new TransactionAbortedEvent(sagaId, request3, exception))
- );
-
- eventStore.populate(events);
- saga.play();
-
- saga.run();
- assertThat(eventStore, contains(
- eventWith(sagaId, SAGA_START_TRANSACTION, SagaStartedEvent.class),
- eventWith(sagaId, transaction1, TransactionStartedEvent.class),
- eventWith(sagaId, transaction1, TransactionEndedEvent.class),
- eventWith(sagaId, transaction2, TransactionStartedEvent.class),
- eventWith(sagaId, transaction2, TransactionEndedEvent.class),
- eventWith(sagaId, transaction3, TransactionStartedEvent.class),
- eventWith(sagaId, transaction3, TransactionAbortedEvent.class),
- eventWith(sagaId, compensation2, TransactionCompensatedEvent.class),
- eventWith(sagaId, compensation1, TransactionCompensatedEvent.class),
- eventWith(sagaId, SAGA_START_COMPENSATION, SagaEndedEvent.class)
- ));
-
- verify(transaction1, never()).send(anyString(), any(SagaResponse.class));
- verify(transaction2, never()).send(anyString(), any(SagaResponse.class));
- verify(transaction3, never()).send(anyString(), any(SagaResponse.class));
-
- verify(compensation1).send(request1.serviceName());
- verify(compensation2).send(request2.serviceName());
- verify(compensation3, never()).send(request3.serviceName());
- }
-
- @Test
- public void restoresSagaToCompensationStateByPlayingAllEvents() {
- addExtraChildToNode1();
-
- Iterable<EventEnvelope> events = asList(
- envelope(new SagaStartedEvent(sagaId, requestJson, NoOpSagaRequest.SAGA_START_REQUEST)),
- envelope(new TransactionStartedEvent(sagaId, request1)),
- envelope(new TransactionEndedEvent(sagaId, request1)),
- envelope(new TransactionStartedEvent(sagaId, request2)),
- envelope(new TransactionEndedEvent(sagaId, request2)),
- envelope(new TransactionStartedEvent(sagaId, request3)),
- envelope(new TransactionEndedEvent(sagaId, request3)),
- envelope(new TransactionCompensatedEvent(sagaId, request2))
- );
-
- eventStore.populate(events);
- saga.play();
-
- saga.run();
- assertThat(eventStore, contains(
- eventWith(sagaId, SAGA_START_TRANSACTION, SagaStartedEvent.class),
- eventWith(sagaId, transaction1, TransactionStartedEvent.class),
- eventWith(sagaId, transaction1, TransactionEndedEvent.class),
- eventWith(sagaId, transaction2, TransactionStartedEvent.class),
- eventWith(sagaId, transaction2, TransactionEndedEvent.class),
- eventWith(sagaId, transaction3, TransactionStartedEvent.class),
- eventWith(sagaId, transaction3, TransactionEndedEvent.class),
- eventWith(sagaId, compensation2, TransactionCompensatedEvent.class),
- eventWith(sagaId, compensation3, TransactionCompensatedEvent.class),
- eventWith(sagaId, compensation1, TransactionCompensatedEvent.class),
- eventWith(sagaId, SAGA_START_COMPENSATION, SagaEndedEvent.class)
- ));
-
- verify(transaction1, never()).send(anyString(), any(SagaResponse.class));
- verify(transaction2, never()).send(anyString(), any(SagaResponse.class));
- verify(transaction3, never()).send(anyString(), any(SagaResponse.class));
-
- verify(compensation1).send(request1.serviceName());
- verify(compensation2, never()).send(request2.serviceName());
- verify(compensation3).send(request3.serviceName());
- }
-
- @Test
- public void restoresPartialCompensationByPlayingAllEvents() {
- addExtraChildToNode1();
-
- Iterable<EventEnvelope> events = asList(
- envelope(new SagaStartedEvent(sagaId, requestJson, NoOpSagaRequest.SAGA_START_REQUEST)),
- envelope(new TransactionStartedEvent(sagaId, request1)),
- envelope(new TransactionEndedEvent(sagaId, request1)),
- envelope(new TransactionStartedEvent(sagaId, request2)),
- envelope(new TransactionEndedEvent(sagaId, request2)),
- envelope(new TransactionStartedEvent(sagaId, request3)),
- envelope(new TransactionAbortedEvent(sagaId, request3, exception)),
- envelope(new TransactionCompensatedEvent(sagaId, request2))
- );
-
- eventStore.populate(events);
- saga.play();
-
- saga.run();
- assertThat(eventStore, contains(
- eventWith(sagaId, SAGA_START_TRANSACTION, SagaStartedEvent.class),
- eventWith(sagaId, transaction1, TransactionStartedEvent.class),
- eventWith(sagaId, transaction1, TransactionEndedEvent.class),
- eventWith(sagaId, transaction2, TransactionStartedEvent.class),
- eventWith(sagaId, transaction2, TransactionEndedEvent.class),
- eventWith(sagaId, transaction3, TransactionStartedEvent.class),
- eventWith(sagaId, transaction3, TransactionAbortedEvent.class),
- eventWith(sagaId, compensation2, TransactionCompensatedEvent.class),
- eventWith(sagaId, compensation1, TransactionCompensatedEvent.class),
- eventWith(sagaId, SAGA_START_COMPENSATION, SagaEndedEvent.class)
- ));
-
- verify(transaction1, never()).send(anyString(), any(SagaResponse.class));
- verify(transaction2, never()).send(anyString(), any(SagaResponse.class));
- verify(transaction3, never()).send(anyString(), any(SagaResponse.class));
-
- verify(compensation1).send(request1.serviceName());
- verify(compensation2, never()).send(request2.serviceName());
- verify(compensation3, never()).send(request3.serviceName());
- }
-
- @Test
- public void restoresSagaToEndStateByPlayingAllEvents() {
- Iterable<EventEnvelope> events = asList(
- envelope(new SagaStartedEvent(sagaId, requestJson, NoOpSagaRequest.SAGA_START_REQUEST)),
- envelope(new TransactionStartedEvent(sagaId, request1)),
- envelope(new TransactionEndedEvent(sagaId, request1)),
- envelope(new TransactionStartedEvent(sagaId, request2)),
- envelope(new TransactionEndedEvent(sagaId, request2))
- );
-
- eventStore.populate(events);
- saga.play();
-
- saga.run();
- assertThat(eventStore, contains(
- eventWith(sagaId, SAGA_START_TRANSACTION, SagaStartedEvent.class),
- eventWith(sagaId, transaction1, TransactionStartedEvent.class),
- eventWith(sagaId, transaction1, TransactionEndedEvent.class),
- eventWith(sagaId, transaction2, TransactionStartedEvent.class),
- eventWith(sagaId, transaction2, TransactionEndedEvent.class),
- eventWith(sagaId, SAGA_END_TRANSACTION, SagaEndedEvent.class)
- ));
-
- verify(transaction1, never()).send(anyString(), any(SagaResponse.class));
- verify(transaction2, never()).send(anyString(), any(SagaResponse.class));
-
- verify(compensation1, never()).send(request1.serviceName());
- verify(compensation2, never()).send(request2.serviceName());
- }
-
- @Test
- public void failFastIfSagaLogIsDown() throws Exception {
- SagaLog sagaLog = mock(SagaLog.class);
- tasks.put(SAGA_START_TASK, new SagaStartTask(sagaId, requestJson, sagaLog));
-
- doThrow(RuntimeException.class).when(sagaLog).offer(any(SagaStartedEvent.class));
-
- try {
- saga.run();
- expectFailing(SagaStartFailedException.class);
- } catch (SagaStartFailedException e) {
- assertThat(e.getMessage(), is("Failed to persist SagaStartedEvent for " + requestJson));
- }
-
- verify(sagaLog).offer(any(SagaStartedEvent.class));
- verify(transaction1, never()).send(anyString(), any(SagaResponse.class));
- verify(transaction2, never()).send(anyString(), any(SagaResponse.class));
-
- verify(compensation1, never()).send(request1.serviceName());
- verify(compensation2, never()).send(request2.serviceName());
- }
-
- private Answer<SagaResponse> withAnswer(Callable<SagaResponse> callable) {
- return invocationOnMock -> callable.call();
- }
-
- private EventEnvelope envelope(SagaEvent event) {
- return new EventEnvelope(idGenerator.nextId(), event);
- }
-
- private void addExtraChildToNode1() {
- node1.addChild(node3);
- node3.addChild(leaf);
- }
-
- private SagaRequest request(String requestId,
- String serviceName,
- Transaction transaction,
- Compensation compensation,
- String... parentIds) {
-
- return new SagaRequestImpl(requestId, serviceName, TYPE_REST, transaction, compensation, parentIds);
- }
-
- private SagaRequest request(String requestId,
- String serviceName,
- Transaction transaction,
- Compensation compensation,
- Fallback fallback) {
-
- return new SagaRequestImpl(requestId, serviceName, TYPE_REST, transaction, compensation, fallback);
- }
-
- private HashSet<String> setOf(String requestId) {
- return new HashSet<>(singletonList(requestId));
- }
-
- private RequestProcessTask requestProcessTask(RecoveryPolicy recoveryPolicy) {
- return new RequestProcessTask(sagaId, sagaLog, recoveryPolicy, new FallbackPolicy(100));
- }
-}
diff --git a/saga-core/src/test/java/org/apache/servicecomb/saga/core/SagaStartTaskTest.java b/saga-core/src/test/java/org/apache/servicecomb/saga/core/SagaStartTaskTest.java
deleted file mode 100644
index b1d0c4e..0000000
--- a/saga-core/src/test/java/org/apache/servicecomb/saga/core/SagaStartTaskTest.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-import static com.seanyinx.github.unit.scaffolding.AssertUtils.expectFailing;
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.CoreMatchers.startsWith;
-import static org.junit.Assert.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.mock;
-
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-
-public class SagaStartTaskTest {
- private final SagaRequest request = mock(SagaRequest.class);
- private final SagaLog sagaLog = mock(SagaLog.class);
-
- private final String sagaId = "0";
- private final String requestJson = null;
- private final SagaStartTask sagaStartTask = new SagaStartTask(sagaId, requestJson, sagaLog);
-
- @Test
- public void emptyResponseOnSuccessfulEventPersistence() throws Exception {
- ArgumentCaptor<SagaStartedEvent> argumentCaptor = ArgumentCaptor.forClass(SagaStartedEvent.class);
- doNothing().when(sagaLog).offer(argumentCaptor.capture());
-
- sagaStartTask.commit(request, SagaResponse.EMPTY_RESPONSE);
-
- SagaStartedEvent event = argumentCaptor.getValue();
- assertThat(event.sagaId, is(sagaId));
- assertThat(event.json(null), is(requestJson));
- assertThat(event.payload(), is(request));
- }
-
- @Test
- public void blowsUpWhenEventIsNotPersisted() {
- doThrow(RuntimeException.class).when(sagaLog).offer(any(SagaStartedEvent.class));
-
- try {
- sagaStartTask.commit(request, SagaResponse.EMPTY_RESPONSE);
- expectFailing(SagaStartFailedException.class);
- } catch (SagaStartFailedException e) {
- assertThat(e.getMessage(), startsWith("Failed to persist SagaStartedEvent"));
- }
- }
-}
diff --git a/saga-core/src/test/java/org/apache/servicecomb/saga/core/TransactionImpl.java b/saga-core/src/test/java/org/apache/servicecomb/saga/core/TransactionImpl.java
deleted file mode 100644
index a59b142..0000000
--- a/saga-core/src/test/java/org/apache/servicecomb/saga/core/TransactionImpl.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core;
-
-import java.util.Map;
-
-public class TransactionImpl extends RestOperation implements Transaction {
-
- public TransactionImpl(String path, String method, Map<String, Map<String, String>> params) {
- super(path, method, params);
- }
-}
diff --git a/saga-core/src/test/java/org/apache/servicecomb/saga/core/actors/ActorBasedSagaExecutionComponentTest.java b/saga-core/src/test/java/org/apache/servicecomb/saga/core/actors/ActorBasedSagaExecutionComponentTest.java
deleted file mode 100644
index 01f8adb..0000000
--- a/saga-core/src/test/java/org/apache/servicecomb/saga/core/actors/ActorBasedSagaExecutionComponentTest.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core.actors;
-
-import org.apache.servicecomb.saga.core.application.SagaFactory;
-import org.apache.servicecomb.saga.core.PersistentStore;
-import org.apache.servicecomb.saga.core.SagaExecutionComponentTestBase;
-
-
-public class ActorBasedSagaExecutionComponentTest extends SagaExecutionComponentTestBase {
-
- @Override
- protected SagaFactory sagaFactory(PersistentStore eventStore) {
- return new ActorBasedSagaFactory(500, eventStore, null);
- }
-}
diff --git a/saga-core/src/test/java/org/apache/servicecomb/saga/core/actors/ActorBasedSagaIntegrationTest.java b/saga-core/src/test/java/org/apache/servicecomb/saga/core/actors/ActorBasedSagaIntegrationTest.java
deleted file mode 100644
index ac649f0..0000000
--- a/saga-core/src/test/java/org/apache/servicecomb/saga/core/actors/ActorBasedSagaIntegrationTest.java
+++ /dev/null
@@ -1,691 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core.actors;
-
-import static org.apache.servicecomb.saga.core.Transaction.SAGA_END_TRANSACTION;
-import static org.apache.servicecomb.saga.core.Transaction.SAGA_START_TRANSACTION;
-import static java.util.Arrays.asList;
-import static java.util.Collections.emptySet;
-import static java.util.Collections.singletonList;
-import static java.util.concurrent.TimeUnit.SECONDS;
-import static org.hamcrest.CoreMatchers.anyOf;
-import static org.hamcrest.collection.IsIterableContainingInOrder.contains;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.util.HashSet;
-import java.util.Set;
-import java.util.concurrent.Callable;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.CyclicBarrier;
-
-import org.apache.servicecomb.saga.core.Compensation;
-import org.apache.servicecomb.saga.core.EventEnvelope;
-import org.apache.servicecomb.saga.core.EventStore;
-import org.apache.servicecomb.saga.core.Fallback;
-import org.apache.servicecomb.saga.core.ForwardRecovery;
-import org.apache.servicecomb.saga.core.IdGenerator;
-import org.apache.servicecomb.saga.core.LongIdGenerator;
-import org.apache.servicecomb.saga.core.NoOpSagaRequest;
-import org.apache.servicecomb.saga.core.Operation;
-import org.apache.servicecomb.saga.core.Saga;
-import org.apache.servicecomb.saga.core.SagaEventMatcher;
-import org.apache.servicecomb.saga.core.SagaRequest;
-import org.apache.servicecomb.saga.core.SagaRequestImpl;
-import org.apache.servicecomb.saga.core.SagaResponse;
-import org.apache.servicecomb.saga.core.SagaStartedEvent;
-import org.apache.servicecomb.saga.core.SuccessfulSagaResponse;
-import org.apache.servicecomb.saga.core.TransactionCompensatedEvent;
-import org.apache.servicecomb.saga.core.TransactionStartedEvent;
-import org.apache.servicecomb.saga.core.application.SagaFactory;
-import org.hamcrest.CoreMatchers;
-import org.hamcrest.collection.IsIterableContainingInOrder;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.mockito.stubbing.Answer;
-
-import com.seanyinx.github.unit.scaffolding.Randomness;
-
-import org.apache.servicecomb.saga.core.BackwardRecovery;
-import org.apache.servicecomb.saga.core.PersistentStore;
-import org.apache.servicecomb.saga.core.SagaDefinition;
-import org.apache.servicecomb.saga.core.SagaEndedEvent;
-import org.apache.servicecomb.saga.core.SagaEvent;
-import org.apache.servicecomb.saga.core.Transaction;
-import org.apache.servicecomb.saga.core.TransactionAbortedEvent;
-import org.apache.servicecomb.saga.core.TransactionEndedEvent;
-import org.apache.servicecomb.saga.core.application.interpreter.FromJsonFormat;
-import org.apache.servicecomb.saga.infrastructure.EmbeddedEventStore;
-
-@SuppressWarnings("unchecked")
-public class ActorBasedSagaIntegrationTest {
- private static final String sagaId = Randomness.uniquify("sagaId");
-
- private final FromJsonFormat<Set<String>> childrenExtractor = mock(FromJsonFormat.class);
- private final IdGenerator<Long> idGenerator = new LongIdGenerator();
- private final EventStore eventStore = new EmbeddedEventStore();
-
- private final PersistentStore persistentStore = mock(PersistentStore.class);
- private final SagaDefinition sagaDefinition = mock(SagaDefinition.class);
-
- private final Transaction transaction1 = mock(Transaction.class, "transaction1");
- private final Transaction transaction2 = mock(Transaction.class, "transaction2");
- private final Transaction transaction3 = mock(Transaction.class, "transaction3");
- private final Transaction transaction4 = mock(Transaction.class, "transaction4");
-
- private final Compensation compensation1 = mock(Compensation.class, "compensation1");
- private final Compensation compensation2 = mock(Compensation.class, "compensation2");
- private final Compensation compensation3 = mock(Compensation.class, "compensation3");
- private final Compensation compensation4 = mock(Compensation.class, "compensation4");
-
- private final Fallback fallback1 = mock(Fallback.class, "fallback1");
-
- private final String requestJson = "{}";
- private final SagaRequest request1 = request("request1", "service1", transaction1, compensation1, fallback1);
- private final SagaRequest request2 = request("request2", "service2", transaction2, compensation2, request1.id());
- private final SagaRequest request3 = request("request3", "service3", transaction3, compensation3, request1.id());
- private final SagaRequest request4 = request("request4", "service4", transaction4, compensation4, request3.id());
-
- private final SagaResponse transactionResponse1 = new SuccessfulSagaResponse("transaction1");
- private final SagaResponse transactionResponse2 = new SuccessfulSagaResponse("transaction2");
- private final SagaResponse transactionResponse3 = new SuccessfulSagaResponse("transaction3");
- private final SagaResponse compensationResponse1 = new SuccessfulSagaResponse("compensation1");
- private final SagaResponse compensationResponse2 = new SuccessfulSagaResponse("compensation2");
- private final SagaResponse compensationResponse3 = new SuccessfulSagaResponse("compensation3");
-
- @SuppressWarnings("ThrowableInstanceNeverThrown")
- private final RuntimeException exception = new RuntimeException("oops");
-
- private Saga saga;
- private final SagaFactory sagaFactory = new ActorBasedSagaFactory(100, persistentStore, childrenExtractor);
-
- // root - node1 - node2 - leaf
- @Before
- public void setUp() throws Exception {
- when(sagaDefinition.policy()).thenReturn(new BackwardRecovery());
- when(sagaDefinition.requests()).thenReturn(new SagaRequest[]{request1, request2});
-
- when(childrenExtractor.fromJson(anyString())).thenReturn(emptySet());
- when(childrenExtractor.fromJson(SagaResponse.NONE_RESPONSE.body())).thenReturn(setOf("none"));
-
- when(transaction1.send(request1.serviceName(), SagaResponse.EMPTY_RESPONSE)).thenReturn(transactionResponse1);
- when(transaction2.send(request2.serviceName(), transactionResponse1)).thenReturn(transactionResponse2);
- when(transaction3.send(request3.serviceName(), transactionResponse1)).thenReturn(transactionResponse3);
-
- when(compensation1.send(request1.serviceName(), compensationResponse2)).thenReturn(compensationResponse1);
- when(compensation2.send(request2.serviceName(), compensationResponse3)).thenReturn(compensationResponse2);
- when(compensation3.send(request3.serviceName(), SagaResponse.EMPTY_RESPONSE)).thenReturn(compensationResponse3);
- }
-
- @After
- public void tearDown() throws Exception {
- sagaFactory.terminate();
- assertTrue(sagaFactory.isTerminated());
- }
-
- @Test
- public void transactionsAreRunSuccessfully() {
- saga = sagaFactory.createSaga(requestJson, sagaId, eventStore, sagaDefinition);
- saga.run();
-
- assertThat(eventStore, IsIterableContainingInOrder.contains(
- SagaEventMatcher.eventWith(sagaId, SAGA_START_TRANSACTION, SagaStartedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction1, TransactionStartedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction1, TransactionEndedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction2, TransactionStartedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction2, TransactionEndedEvent.class),
- SagaEventMatcher.eventWith(sagaId, SAGA_END_TRANSACTION, SagaEndedEvent.class)
- ));
-
- verify(transaction1).send(request1.serviceName(), SagaResponse.EMPTY_RESPONSE);
- verify(transaction2).send(request2.serviceName(), transactionResponse1);
-
- verify(compensation1, never()).send(request1.serviceName());
- verify(compensation2, never()).send(request2.serviceName());
- }
-
- // root - node1 - node2 - leaf
- // \_ node3 _/
- @Test
- public void compensateCommittedTransactionsOnFailure() {
- when(sagaDefinition.requests()).thenReturn(new SagaRequest[]{request1, request2, request3});
- saga = sagaFactory.createSaga(requestJson, sagaId, eventStore, sagaDefinition);
-
- // barrier to make sure the two transactions starts at the same time
- CyclicBarrier barrier = new CyclicBarrier(2);
- when(transaction2.send(request2.serviceName(), transactionResponse1))
- .thenAnswer(
- withAnswer(() -> {
- barrier.await();
- Thread.sleep(100);
- throw exception;
- }));
-
- when(transaction3.send(request3.serviceName(), transactionResponse1))
- .thenAnswer(
- withAnswer(() -> {
- barrier.await();
- return transactionResponse3;
- }));
-
- saga.run();
-
- assertThat(eventStore, IsIterableContainingInOrder.contains(
- SagaEventMatcher.eventWith(sagaId, SAGA_START_TRANSACTION, SagaStartedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction1, TransactionStartedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction1, TransactionEndedEvent.class),
- CoreMatchers.anyOf(SagaEventMatcher.eventWith(sagaId, transaction2, TransactionStartedEvent.class), SagaEventMatcher
- .eventWith(sagaId, transaction3, TransactionStartedEvent.class)),
- CoreMatchers.anyOf(SagaEventMatcher.eventWith(sagaId, transaction2, TransactionStartedEvent.class), SagaEventMatcher
- .eventWith(sagaId, transaction3, TransactionStartedEvent.class)),
- SagaEventMatcher.eventWith(sagaId, transaction3, TransactionEndedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction2, TransactionAbortedEvent.class),
- SagaEventMatcher.eventWith(sagaId, compensation3, TransactionCompensatedEvent.class),
- SagaEventMatcher.eventWith(sagaId, compensation1, TransactionCompensatedEvent.class),
- SagaEventMatcher.eventWith(sagaId, Compensation.SAGA_START_COMPENSATION, SagaEndedEvent.class)));
-
- verify(transaction1).send(request1.serviceName(), SagaResponse.EMPTY_RESPONSE);
- verify(transaction2).send(request2.serviceName(), transactionResponse1);
- verify(transaction3).send(request3.serviceName(), transactionResponse1);
-
- verify(compensation1).send(request1.serviceName());
- verify(compensation2, never()).send(request2.serviceName());
- verify(compensation3).send(request3.serviceName());
- }
-
- @Test
- public void skipIgnoredTransaction() throws Exception {
- when(sagaDefinition.requests()).thenReturn(new SagaRequest[]{request1, request2, request3});
- saga = sagaFactory.createSaga(requestJson, sagaId, eventStore, sagaDefinition);
-
- when(childrenExtractor.fromJson(transactionResponse1.body())).thenReturn(setOf(request3.id()));
-
- saga.run();
-
- assertThat(eventStore, IsIterableContainingInOrder.contains(
- SagaEventMatcher.eventWith(sagaId, SAGA_START_TRANSACTION, SagaStartedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction1, TransactionStartedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction1, TransactionEndedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction3, TransactionStartedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction3, TransactionEndedEvent.class),
- SagaEventMatcher.eventWith(sagaId, SAGA_END_TRANSACTION, SagaEndedEvent.class)
- ));
-
- verify(transaction1).send(request1.serviceName(), SagaResponse.EMPTY_RESPONSE);
- verify(transaction3).send(request3.serviceName(), transactionResponse1);
- verify(transaction2, never()).send(anyString(), any(SagaResponse.class));
-
- verify(compensation1, never()).send(request1.serviceName());
- verify(compensation2, never()).send(request2.serviceName());
- verify(compensation3, never()).send(request3.serviceName());
- }
-
- @Test
- public void skipAllIgnoredTransactions() throws Exception {
- when(sagaDefinition.requests()).thenReturn(new SagaRequest[]{request1, request2, request3, request4});
- saga = sagaFactory.createSaga(requestJson, sagaId, eventStore, sagaDefinition);
-
- when(childrenExtractor.fromJson(transactionResponse1.body())).thenReturn(setOf("none"));
-
- saga.run();
-
- assertThat(eventStore, IsIterableContainingInOrder.contains(
- SagaEventMatcher.eventWith(sagaId, SAGA_START_TRANSACTION, SagaStartedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction1, TransactionStartedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction1, TransactionEndedEvent.class),
- SagaEventMatcher.eventWith(sagaId, SAGA_END_TRANSACTION, SagaEndedEvent.class)
- ));
-
- verify(transaction1).send(request1.serviceName(), SagaResponse.EMPTY_RESPONSE);
- verify(transaction2, never()).send(anyString(), any(SagaResponse.class));
- verify(transaction3, never()).send(anyString(), any(SagaResponse.class));
- verify(transaction4, never()).send(anyString(), any(SagaResponse.class));
-
- verify(compensation1, never()).send(request1.serviceName());
- verify(compensation2, never()).send(request2.serviceName());
- verify(compensation3, never()).send(request3.serviceName());
- verify(compensation4, never()).send(request4.serviceName());
- }
-
- @Test
- public void doNotCompensateIgnoredTransactions() throws Exception {
- when(sagaDefinition.requests()).thenReturn(new SagaRequest[]{request1, request2, request3, request4});
- saga = sagaFactory.createSaga(requestJson, sagaId, eventStore, sagaDefinition);
-
- when(childrenExtractor.fromJson(transactionResponse1.body())).thenReturn(setOf(request3.id()));
-
- when(transaction4.send(request4.serviceName(), transactionResponse3)).thenThrow(exception);
-
- saga.run();
-
- assertThat(eventStore, IsIterableContainingInOrder.contains(
- SagaEventMatcher.eventWith(sagaId, SAGA_START_TRANSACTION, SagaStartedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction1, TransactionStartedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction1, TransactionEndedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction3, TransactionStartedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction3, TransactionEndedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction4, TransactionStartedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction4, TransactionAbortedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction3, TransactionCompensatedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction1, TransactionCompensatedEvent.class),
- SagaEventMatcher.eventWith(sagaId, Compensation.SAGA_START_COMPENSATION, SagaEndedEvent.class)
- ));
-
- verify(transaction1).send(request1.serviceName(), SagaResponse.EMPTY_RESPONSE);
- verify(transaction3).send(request3.serviceName(), transactionResponse1);
- verify(transaction4).send(request4.serviceName(), transactionResponse3);
- verify(transaction2, never()).send(anyString(), any(SagaResponse.class));
-
- verify(compensation1).send(request1.serviceName());
- verify(compensation3).send(request3.serviceName());
- verify(compensation2, never()).send(request2.serviceName());
- verify(compensation4, never()).send(request4.serviceName());
- }
-
- // TODO: 2017/10/31 actor will hang and its parent and children will be blocked without its response, timeout must be applied
- @Ignore
- // root - node1 - node2 - leaf
- // \_ node3 _/
- @Test
- public void redoHangingTransactionsOnFailure() throws InterruptedException {
- when(sagaDefinition.requests()).thenReturn(new SagaRequest[]{request1, request2, request3});
- saga = sagaFactory.createSaga(requestJson, sagaId, eventStore, sagaDefinition);
-
- // barrier to make sure the two transactions starts at the same time
- CyclicBarrier barrier = new CyclicBarrier(2);
- when(transaction3.send(request3.serviceName(), transactionResponse1))
- .thenAnswer(withAnswer(() -> {
- barrier.await();
- throw exception;
- }));
-
- CountDownLatch latch = new CountDownLatch(1);
-
- when(transaction2.send(request2.serviceName(), transactionResponse1))
- .thenAnswer(withAnswer(() -> {
- barrier.await();
- latch.await(1, SECONDS);
- return transactionResponse2;
- })).thenReturn(transactionResponse2);
-
- saga.run();
-
- // the ordering of events may not be consistence due to concurrent processing of requests
- assertThat(eventStore, IsIterableContainingInOrder.contains(
- SagaEventMatcher.eventWith(sagaId, SAGA_START_TRANSACTION, SagaStartedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction1, TransactionStartedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction1, TransactionEndedEvent.class),
- CoreMatchers.anyOf(
- SagaEventMatcher.eventWith(sagaId, transaction2, TransactionStartedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction3, TransactionStartedEvent.class)),
- CoreMatchers.anyOf(
- SagaEventMatcher.eventWith(sagaId, transaction3, TransactionStartedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction2, TransactionStartedEvent.class)),
- SagaEventMatcher.eventWith(sagaId, transaction3, TransactionAbortedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction2, TransactionStartedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction2, TransactionEndedEvent.class),
- SagaEventMatcher.eventWith(sagaId, compensation2, TransactionCompensatedEvent.class),
- SagaEventMatcher.eventWith(sagaId, compensation1, TransactionCompensatedEvent.class),
- SagaEventMatcher.eventWith(sagaId, Compensation.SAGA_START_COMPENSATION, SagaEndedEvent.class)));
-
- verify(transaction1).send(request1.serviceName(), SagaResponse.EMPTY_RESPONSE);
- verify(transaction2, times(2)).send(request2.serviceName(), transactionResponse1);
- verify(transaction3).send(request3.serviceName(), transactionResponse1);
-
- verify(compensation1).send(request1.serviceName());
- verify(compensation2).send(request2.serviceName());
- verify(compensation3, never()).send(request3.serviceName());
-
- latch.countDown();
- }
-
- @Test
- public void retriesFailedTransactionTillSuccess() {
- when(sagaDefinition.policy()).thenReturn(new ForwardRecovery());
- saga = sagaFactory.createSaga(requestJson, sagaId, eventStore, sagaDefinition);
-
- when(transaction2.send(request2.serviceName(), transactionResponse1))
- .thenThrow(exception).thenThrow(exception).thenReturn(transactionResponse2);
-
- saga.run();
-
- assertThat(eventStore, IsIterableContainingInOrder.contains(
- SagaEventMatcher.eventWith(sagaId, SAGA_START_TRANSACTION, SagaStartedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction1, TransactionStartedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction1, TransactionEndedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction2, TransactionStartedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction2, TransactionEndedEvent.class),
- SagaEventMatcher.eventWith(sagaId, SAGA_END_TRANSACTION, SagaEndedEvent.class)
- ));
-
- verify(transaction1).send(request1.serviceName(), SagaResponse.EMPTY_RESPONSE);
- verify(transaction2, times(3)).send(request2.serviceName(), transactionResponse1);
-
- verify(compensation1, never()).send(anyString(), any(SagaResponse.class));
- verify(compensation2, never()).send(anyString(), any(SagaResponse.class));
- }
-
- @Test
- public void fallbackWhenCompensationFailed() {
- int retries = 3;
- saga = sagaFactory.createSaga(requestJson, sagaId, eventStore, sagaDefinition);
-
- when(transaction2.send(request2.serviceName(), transactionResponse1)).thenThrow(exception);
- when(compensation1.send(request1.serviceName())).thenThrow(exception);
- when(compensation1.retries()).thenReturn(retries);
-
- saga.run();
-
- verify(transaction1).send(request1.serviceName(), SagaResponse.EMPTY_RESPONSE);
- verify(transaction2).send(request2.serviceName(), transactionResponse1);
-
- verify(compensation1, times(retries + 1)).send(request1.serviceName());
- verify(compensation2, never()).send(request2.serviceName());
-
- verify(fallback1).send(request1.serviceName());
- }
-
- @Test
- public void restoresSagaToTransactionStateByPlayingAllEvents() {
- when(sagaDefinition.requests()).thenReturn(new SagaRequest[]{request1, request2, request3});
- saga = sagaFactory.createSaga(requestJson, sagaId, eventStore, sagaDefinition);
-
- Iterable<EventEnvelope> events = asList(
- envelope(new SagaStartedEvent(sagaId, requestJson, NoOpSagaRequest.SAGA_START_REQUEST)),
- envelope(new TransactionStartedEvent(sagaId, request1)),
- envelope(new TransactionEndedEvent(sagaId, request1, transactionResponse1)),
- envelope(new TransactionStartedEvent(sagaId, request2)),
- envelope(new TransactionEndedEvent(sagaId, request2, transactionResponse2))
- );
-
- eventStore.populate(events);
- saga.play();
-
- saga.run();
- assertThat(eventStore, IsIterableContainingInOrder.contains(
- SagaEventMatcher.eventWith(sagaId, SAGA_START_TRANSACTION, SagaStartedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction1, TransactionStartedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction1, TransactionEndedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction2, TransactionStartedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction2, TransactionEndedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction3, TransactionStartedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction3, TransactionEndedEvent.class),
- SagaEventMatcher.eventWith(sagaId, SAGA_END_TRANSACTION, SagaEndedEvent.class)
- ));
-
- verify(transaction1, never()).send(anyString(), any(SagaResponse.class));
- verify(transaction2, never()).send(anyString(), any(SagaResponse.class));
- verify(transaction3).send(request3.serviceName(), transactionResponse1);
-
- verify(compensation1, never()).send(request1.serviceName());
- verify(compensation2, never()).send(request2.serviceName());
- verify(compensation3, never()).send(request3.serviceName());
- }
-
- @Test
- public void restoresPartialTransactionByPlayingAllEvents() {
- when(sagaDefinition.requests()).thenReturn(new SagaRequest[]{request1, request2, request3});
- saga = sagaFactory.createSaga(requestJson, sagaId, eventStore, sagaDefinition);
-
- Iterable<EventEnvelope> events = asList(
- envelope(new SagaStartedEvent(sagaId, requestJson, NoOpSagaRequest.SAGA_START_REQUEST)),
- envelope(new TransactionStartedEvent(sagaId, request1)),
- envelope(new TransactionEndedEvent(sagaId, request1, transactionResponse1)),
- envelope(new TransactionStartedEvent(sagaId, request2)),
- envelope(new TransactionEndedEvent(sagaId, request2, transactionResponse2)),
- envelope(new TransactionStartedEvent(sagaId, request3))
- );
-
- eventStore.populate(events);
- saga.play();
-
- saga.run();
- assertThat(eventStore, IsIterableContainingInOrder.contains(
- SagaEventMatcher.eventWith(sagaId, SAGA_START_TRANSACTION, SagaStartedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction1, TransactionStartedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction1, TransactionEndedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction2, TransactionStartedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction2, TransactionEndedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction3, TransactionStartedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction3, TransactionStartedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction3, TransactionEndedEvent.class),
- SagaEventMatcher.eventWith(sagaId, SAGA_END_TRANSACTION, SagaEndedEvent.class)
- ));
-
- verify(transaction1, never()).send(anyString(), any(SagaResponse.class));
- verify(transaction2, never()).send(anyString(), any(SagaResponse.class));
- verify(transaction3).send(request3.serviceName(), transactionResponse1);
-
- verify(compensation1, never()).send(request1.serviceName());
- verify(compensation2, never()).send(request2.serviceName());
- verify(compensation3, never()).send(request3.serviceName());
- }
-
- @Test
- public void restoresToCompensationFromAbortedTransactionByPlayingAllEvents() {
- when(sagaDefinition.requests()).thenReturn(new SagaRequest[]{request1, request2, request3});
- saga = sagaFactory.createSaga(requestJson, sagaId, eventStore, sagaDefinition);
-
- Iterable<EventEnvelope> events = asList(
- envelope(new SagaStartedEvent(sagaId, requestJson, NoOpSagaRequest.SAGA_START_REQUEST)),
- envelope(new TransactionStartedEvent(sagaId, request1)),
- envelope(new TransactionEndedEvent(sagaId, request1)),
- envelope(new TransactionStartedEvent(sagaId, request2)),
- envelope(new TransactionEndedEvent(sagaId, request2)),
- envelope(new TransactionStartedEvent(sagaId, request3)),
- envelope(new TransactionAbortedEvent(sagaId, request3, exception))
- );
-
- eventStore.populate(events);
- saga.play();
-
- saga.run();
- assertThat(eventStore, IsIterableContainingInOrder.contains(
- SagaEventMatcher.eventWith(sagaId, SAGA_START_TRANSACTION, SagaStartedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction1, TransactionStartedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction1, TransactionEndedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction2, TransactionStartedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction2, TransactionEndedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction3, TransactionStartedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction3, TransactionAbortedEvent.class),
- SagaEventMatcher.eventWith(sagaId, compensation2, TransactionCompensatedEvent.class),
- SagaEventMatcher.eventWith(sagaId, compensation1, TransactionCompensatedEvent.class),
- SagaEventMatcher.eventWith(sagaId, Compensation.SAGA_START_COMPENSATION, SagaEndedEvent.class)
- ));
-
- verify(transaction1, never()).send(anyString(), any(SagaResponse.class));
- verify(transaction2, never()).send(anyString(), any(SagaResponse.class));
- verify(transaction3, never()).send(anyString(), any(SagaResponse.class));
-
- verify(compensation1).send(request1.serviceName());
- verify(compensation2).send(request2.serviceName());
- verify(compensation3, never()).send(request3.serviceName());
- }
-
- @Test
- public void restoresSagaToCompensationStateByPlayingAllEvents() {
- when(sagaDefinition.requests()).thenReturn(new SagaRequest[]{request1, request2, request3});
- saga = sagaFactory.createSaga(requestJson, sagaId, eventStore, sagaDefinition);
-
- Iterable<EventEnvelope> events = asList(
- envelope(new SagaStartedEvent(sagaId, requestJson, NoOpSagaRequest.SAGA_START_REQUEST)),
- envelope(new TransactionStartedEvent(sagaId, request1)),
- envelope(new TransactionEndedEvent(sagaId, request1)),
- envelope(new TransactionStartedEvent(sagaId, request2)),
- envelope(new TransactionEndedEvent(sagaId, request2)),
- envelope(new TransactionStartedEvent(sagaId, request3)),
- envelope(new TransactionAbortedEvent(sagaId, request3, exception)),
- envelope(new TransactionCompensatedEvent(sagaId, request2))
- );
-
- eventStore.populate(events);
- saga.play();
-
- saga.run();
- assertThat(eventStore, IsIterableContainingInOrder.contains(
- SagaEventMatcher.eventWith(sagaId, SAGA_START_TRANSACTION, SagaStartedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction1, TransactionStartedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction1, TransactionEndedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction2, TransactionStartedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction2, TransactionEndedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction3, TransactionStartedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction3, TransactionAbortedEvent.class),
- SagaEventMatcher.eventWith(sagaId, compensation2, TransactionCompensatedEvent.class),
- SagaEventMatcher.eventWith(sagaId, compensation1, TransactionCompensatedEvent.class),
- SagaEventMatcher.eventWith(sagaId, Compensation.SAGA_START_COMPENSATION, SagaEndedEvent.class)
- ));
-
- verify(transaction1, never()).send(anyString(), any(SagaResponse.class));
- verify(transaction2, never()).send(anyString(), any(SagaResponse.class));
- verify(transaction3, never()).send(anyString(), any(SagaResponse.class));
-
- verify(compensation1).send(request1.serviceName());
- verify(compensation2, never()).send(request2.serviceName());
- verify(compensation3, never()).send(request3.serviceName());
- }
-
- @Test
- public void restoresPartialCompensationByPlayingAllEvents() {
- when(sagaDefinition.requests()).thenReturn(new SagaRequest[]{request1, request2, request3});
- saga = sagaFactory.createSaga(requestJson, sagaId, eventStore, sagaDefinition);
-
- Iterable<EventEnvelope> events = asList(
- envelope(new SagaStartedEvent(sagaId, requestJson, NoOpSagaRequest.SAGA_START_REQUEST)),
- envelope(new TransactionStartedEvent(sagaId, request1)),
- envelope(new TransactionEndedEvent(sagaId, request1)),
- envelope(new TransactionStartedEvent(sagaId, request2)),
- envelope(new TransactionEndedEvent(sagaId, request2)),
- envelope(new TransactionStartedEvent(sagaId, request3)),
- envelope(new TransactionAbortedEvent(sagaId, request3, exception)),
- envelope(new TransactionCompensatedEvent(sagaId, request2))
- );
-
- eventStore.populate(events);
- saga.play();
-
- saga.run();
- assertThat(eventStore, IsIterableContainingInOrder.contains(
- SagaEventMatcher.eventWith(sagaId, SAGA_START_TRANSACTION, SagaStartedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction1, TransactionStartedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction1, TransactionEndedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction2, TransactionStartedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction2, TransactionEndedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction3, TransactionStartedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction3, TransactionAbortedEvent.class),
- SagaEventMatcher.eventWith(sagaId, compensation2, TransactionCompensatedEvent.class),
- SagaEventMatcher.eventWith(sagaId, compensation1, TransactionCompensatedEvent.class),
- SagaEventMatcher.eventWith(sagaId, Compensation.SAGA_START_COMPENSATION, SagaEndedEvent.class)
- ));
-
- verify(transaction1, never()).send(anyString(), any(SagaResponse.class));
- verify(transaction2, never()).send(anyString(), any(SagaResponse.class));
- verify(transaction3, never()).send(anyString(), any(SagaResponse.class));
-
- verify(compensation1).send(request1.serviceName());
- verify(compensation2, never()).send(request2.serviceName());
- verify(compensation3, never()).send(request3.serviceName());
- }
-
- @Test
- public void restoresSagaToEndStateByPlayingAllEvents() {
- saga = sagaFactory.createSaga(requestJson, sagaId, eventStore, sagaDefinition);
- Iterable<EventEnvelope> events = asList(
- envelope(new SagaStartedEvent(sagaId, requestJson, NoOpSagaRequest.SAGA_START_REQUEST)),
- envelope(new TransactionStartedEvent(sagaId, request1)),
- envelope(new TransactionEndedEvent(sagaId, request1)),
- envelope(new TransactionStartedEvent(sagaId, request2)),
- envelope(new TransactionEndedEvent(sagaId, request2))
- );
-
- eventStore.populate(events);
- saga.play();
-
- saga.run();
- assertThat(eventStore, IsIterableContainingInOrder.contains(
- SagaEventMatcher.eventWith(sagaId, SAGA_START_TRANSACTION, SagaStartedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction1, TransactionStartedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction1, TransactionEndedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction2, TransactionStartedEvent.class),
- SagaEventMatcher.eventWith(sagaId, transaction2, TransactionEndedEvent.class),
- SagaEventMatcher.eventWith(sagaId, SAGA_END_TRANSACTION, SagaEndedEvent.class)
- ));
-
- verify(transaction1, never()).send(anyString(), any(SagaResponse.class));
- verify(transaction2, never()).send(anyString(), any(SagaResponse.class));
-
- verify(compensation1, never()).send(request1.serviceName());
- verify(compensation2, never()).send(request2.serviceName());
- }
-
- @Test
- public void failFastIfSagaLogIsDown() throws Exception {
- EventStore sagaLog = mock(EventStore.class);
- saga = sagaFactory.createSaga(requestJson, sagaId, sagaLog, sagaDefinition);
-
- doThrow(RuntimeException.class).when(sagaLog).offer(any(SagaStartedEvent.class));
-
- saga.run();
-
- verify(sagaLog).offer(any(SagaStartedEvent.class));
- verify(transaction1, never()).send(anyString(), any(SagaResponse.class));
- verify(transaction2, never()).send(anyString(), any(SagaResponse.class));
-
- verify(compensation1, never()).send(request1.serviceName());
- verify(compensation2, never()).send(request2.serviceName());
- }
-
- private Answer<SagaResponse> withAnswer(Callable<SagaResponse> callable) {
- return invocationOnMock -> callable.call();
- }
-
- private EventEnvelope envelope(SagaEvent event) {
- return new EventEnvelope(idGenerator.nextId(), event);
- }
-
- private SagaRequest request(String requestId,
- String serviceName,
- Transaction transaction,
- Compensation compensation,
- String... parentIds) {
-
- return new SagaRequestImpl(requestId, serviceName, Operation.TYPE_REST, transaction, compensation, parentIds);
- }
-
- private SagaRequest request(String requestId,
- String serviceName,
- Transaction transaction,
- Compensation compensation,
- Fallback fallback) {
-
- return new SagaRequestImpl(requestId, serviceName, Operation.TYPE_REST, transaction, compensation, fallback);
- }
-
- private HashSet<String> setOf(String requestId) {
- return new HashSet<>(singletonList(requestId));
- }
-}
diff --git a/saga-core/src/test/java/org/apache/servicecomb/saga/core/actors/CompletionCallbackActorTest.java b/saga-core/src/test/java/org/apache/servicecomb/saga/core/actors/CompletionCallbackActorTest.java
deleted file mode 100644
index 5823a06..0000000
--- a/saga-core/src/test/java/org/apache/servicecomb/saga/core/actors/CompletionCallbackActorTest.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core.actors;
-
-import static akka.actor.ActorRef.noSender;
-import static akka.actor.Props.empty;
-import static com.seanyinx.github.unit.scaffolding.Randomness.uniquify;
-import static org.awaitility.Awaitility.await;
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsInstanceOf.instanceOf;
-import static org.junit.Assert.assertThat;
-
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.servicecomb.saga.core.NoOpSagaRequest;
-import org.apache.servicecomb.saga.core.actors.messages.AbortMessage;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mockito;
-
-import org.apache.servicecomb.saga.core.FailedSagaResponse;
-import org.apache.servicecomb.saga.core.SagaResponse;
-import org.apache.servicecomb.saga.core.actors.messages.CompensateMessage;
-import org.apache.servicecomb.saga.core.actors.messages.FailMessage;
-import org.apache.servicecomb.saga.core.actors.messages.TransactMessage;
-import akka.actor.ActorRef;
-import akka.actor.ActorSystem;
-import akka.testkit.javadsl.TestKit;
-
-public class CompletionCallbackActorTest {
- private static final ActorSystem actorSystem = ActorSystem.create();
-
- private final SagaResponse response = Mockito.mock(SagaResponse.class);
- private final RequestActorContext context = new RequestActorContext(null);
-
- private final ActorRef actor1 = someActor();
- private final ActorRef actor2 = someActor();
-
- @Before
- public void setUp() throws Exception {
- context.addActor(uniquify("requestId"), actor1);
- context.addActor(uniquify("requestId"), actor2);
- }
-
- @AfterClass
- public static void tearDown() throws Exception {
- TestKit.shutdownActorSystem(actorSystem);
- }
-
- @Test
- public void killAllOnTransactionComplete() throws Exception {
- new TestKit(actorSystem) {{
- CompletableFuture<SagaResponse> future = new CompletableFuture<>();
-
- ActorRef actor = actorSystem.actorOf(CompletionCallbackActor.props(future));
-
- actor.tell(context, noSender());
- actor.tell(new TransactMessage(null, response), noSender());
-
- await().atMost(2, TimeUnit.SECONDS)
- .until(() -> actor1.isTerminated() && actor2.isTerminated() && actor.isTerminated());
-
- assertThat(future.get(), is(response));
- }};
- }
-
- @Test
- public void killAllOnCompensationComplete() throws Exception {
- new TestKit(actorSystem) {{
- CompletableFuture<SagaResponse> future = new CompletableFuture<>();
-
- ActorRef actor = actorSystem.actorOf(CompletionCallbackActor.props(future));
-
- actor.tell(context, noSender());
- actor.tell(new CompensateMessage(response), noSender());
-
- await().atMost(2, TimeUnit.SECONDS)
- .until(() -> actor1.isTerminated() && actor2.isTerminated() && actor.isTerminated());
-
- assertThat(future.get(), is(response));
- }};
- }
-
- @Test
- public void killAllOnFailure() throws Exception {
- new TestKit(actorSystem) {{
- CompletableFuture<SagaResponse> future = new CompletableFuture<>();
-
- ActorRef actor = actorSystem.actorOf(CompletionCallbackActor.props(future));
-
- actor.tell(context, noSender());
- actor.tell(new FailMessage(new RuntimeException("oops")), noSender());
-
- await().atMost(2, TimeUnit.SECONDS)
- .until(() -> actor1.isTerminated() && actor2.isTerminated() && actor.isTerminated());
-
- assertThat(future.get(), is(instanceOf(FailedSagaResponse.class)));
- }};
- }
-
- @Test
- public void tellLeafToCompensateOnAbort() throws Exception {
- new TestKit(actorSystem) {{
- context.addActor(NoOpSagaRequest.SAGA_END_REQUEST.id(), getRef());
- CompletableFuture<SagaResponse> future = new CompletableFuture<>();
-
- ActorRef actor = actorSystem.actorOf(CompletionCallbackActor.props(future));
-
- actor.tell(context, noSender());
- AbortMessage message = new AbortMessage(new RuntimeException("oops"));
- actor.tell(message, noSender());
-
- CompensateMessage compensateMessage = (CompensateMessage) receiveOne(duration("2 seconds"));
- assertThat(compensateMessage.response(), is(message.response()));
- }};
- }
-
- private ActorRef someActor() {
- return actorSystem.actorOf(empty());
- }
-}
diff --git a/saga-core/src/test/java/org/apache/servicecomb/saga/core/actors/EventContextImplTest.java b/saga-core/src/test/java/org/apache/servicecomb/saga/core/actors/EventContextImplTest.java
deleted file mode 100644
index cfd3788..0000000
--- a/saga-core/src/test/java/org/apache/servicecomb/saga/core/actors/EventContextImplTest.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core.actors;
-
-import static com.seanyinx.github.unit.scaffolding.Randomness.uniquify;
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
-import static org.mockito.Mockito.when;
-
-import org.apache.servicecomb.saga.core.SagaRequest;
-import org.apache.servicecomb.saga.core.SagaResponse;
-import org.apache.servicecomb.saga.core.actors.messages.AbortRecoveryMessage;
-import org.apache.servicecomb.saga.core.actors.messages.CompensationRecoveryMessage;
-import org.apache.servicecomb.saga.core.actors.messages.TransactionRecoveryMessage;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mockito;
-import org.scalatest.junit.JUnitSuite;
-
-import akka.actor.ActorSystem;
-import akka.testkit.javadsl.TestKit;
-
-public class EventContextImplTest extends JUnitSuite {
- private static final ActorSystem actorSystem = ActorSystem.create();
-
- private final SagaRequest request = Mockito.mock(SagaRequest.class);
- private final SagaResponse response = Mockito.mock(SagaResponse.class);
-
- private final RequestActorContext context = new RequestActorContext(null);
- private final EventContextImpl eventContext = new EventContextImpl(context);
- private final String requestId = uniquify("requestId");
-
- @Before
- public void setUp() throws Exception {
- when(request.id()).thenReturn(requestId);
- }
-
- @AfterClass
- public static void tearDown() throws Exception {
- TestKit.shutdownActorSystem(actorSystem);
- }
-
- @Test
- public void sendTransactionRecoveryMessageToActor_OnTransactionEnd() throws Exception {
- new TestKit(actorSystem) {{
- context.addActor(requestId, getRef());
-
- eventContext.endTransaction(request, response);
-
- TransactionRecoveryMessage message = (TransactionRecoveryMessage) receiveOne(duration("2 seconds"));
- assertThat(message.response(), is(response));
- }};
- }
-
- @Test
- public void sendCompensationRecoveryMessageToActor_OnCompensationEnd() throws Exception {
- new TestKit(actorSystem) {{
- context.addActor(requestId, getRef());
-
- eventContext.compensateTransaction(request, response);
-
- expectMsgClass(CompensationRecoveryMessage.class);
- }};
- }
-
- @Test
- public void sendAbortMessageToActor_OnAbort() throws Exception {
- new TestKit(actorSystem) {{
- context.addActor(requestId, getRef());
-
- eventContext.abortTransaction(request, response);
-
- AbortRecoveryMessage message = ((AbortRecoveryMessage) receiveOne(duration("2 seconds")));
- assertThat(message.response(), is(response));
- }};
- }
-}
diff --git a/saga-core/src/test/java/org/apache/servicecomb/saga/core/actors/RequestActorBuilderTest.java b/saga-core/src/test/java/org/apache/servicecomb/saga/core/actors/RequestActorBuilderTest.java
deleted file mode 100644
index b3a2c14..0000000
--- a/saga-core/src/test/java/org/apache/servicecomb/saga/core/actors/RequestActorBuilderTest.java
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core.actors;
-
-import static org.hamcrest.Matchers.containsInAnyOrder;
-import static org.hamcrest.core.IsInstanceOf.instanceOf;
-import static org.junit.Assert.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import org.apache.servicecomb.saga.core.NoOpSagaRequest;
-import org.apache.servicecomb.saga.core.SagaRequest;
-import org.apache.servicecomb.saga.core.SagaResponse;
-import org.apache.servicecomb.saga.core.SagaTask;
-import org.hamcrest.Matchers;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mockito;
-import org.scalatest.junit.JUnitSuite;
-
-import com.seanyinx.github.unit.scaffolding.Randomness;
-
-import org.apache.servicecomb.saga.core.CompositeSagaResponse;
-import org.apache.servicecomb.saga.core.actors.messages.CompensateMessage;
-import org.apache.servicecomb.saga.core.actors.messages.TransactMessage;
-import org.apache.servicecomb.saga.core.application.interpreter.FromJsonFormat;
-import akka.actor.ActorRef;
-import akka.actor.ActorSystem;
-import akka.testkit.javadsl.TestKit;
-
-@SuppressWarnings("unchecked")
-public class RequestActorBuilderTest extends JUnitSuite {
- private static final ActorSystem actorSystem = ActorSystem.create();
-
- private final String requestId1 = Randomness.uniquify("requestId1");
- private final String requestId2 = Randomness.uniquify("requestId2");
- private final String requestId3 = Randomness.uniquify("requestId3");
- private final String taskId = "some task";
-
- private final SagaRequest request1 = Mockito.mock(SagaRequest.class);
- private final SagaRequest request2 = Mockito.mock(SagaRequest.class);
- private final SagaRequest request3 = Mockito.mock(SagaRequest.class);
-
- private final SagaResponse response1 = Mockito.mock(SagaResponse.class);
- private final SagaResponse response2 = Mockito.mock(SagaResponse.class);
- private final SagaResponse response3 = Mockito.mock(SagaResponse.class);
-
- private final SagaRequest[] requests = {request1, request2, request3};
-
- private final SagaTask task = Mockito.mock(SagaTask.class);
- private final Map<String, SagaTask> tasks = new HashMap<>();
-
- private final FromJsonFormat<Set<String>> childrenExtractor = Mockito.mock(FromJsonFormat.class);
- private final RequestActorBuilder actorBuilder = new RequestActorBuilder(actorSystem, childrenExtractor);
-
- @Before
- public void setUp() throws Exception {
- tasks.put(SagaTask.SAGA_START_TASK, task);
- tasks.put(SagaTask.SAGA_END_TASK, task);
- tasks.put(taskId, task);
-
- when(request1.id()).thenReturn(requestId1);
- when(request2.id()).thenReturn(requestId2);
- when(request3.id()).thenReturn(requestId3);
-
- when(request1.task()).thenReturn(taskId);
- when(request2.task()).thenReturn(taskId);
- when(request3.task()).thenReturn(taskId);
-
- when(request1.parents()).thenReturn(new String[0]);
- when(request2.parents()).thenReturn(new String[] {requestId1});
- when(request3.parents()).thenReturn(new String[] {requestId1});
-
- when(task.commit(NoOpSagaRequest.SAGA_START_REQUEST, SagaResponse.EMPTY_RESPONSE)).thenReturn(
- SagaResponse.EMPTY_RESPONSE);
- when(task.commit(request1, SagaResponse.EMPTY_RESPONSE)).thenReturn(response1);
- when(task.commit(request2, response1)).thenReturn(response2);
- when(task.commit(request3, response1)).thenReturn(response3);
-
- when(childrenExtractor.fromJson(anyString())).thenReturn(Collections.emptySet());
- }
-
- @AfterClass
- public static void tearDown() throws Exception {
- TestKit.shutdownActorSystem(actorSystem);
- }
-
- @Test
- public void createOneActorPerRequest() throws Exception {
- new TestKit(actorSystem) {{
- ArgumentCaptor<SagaResponse> argumentCaptor = ArgumentCaptor.forClass(SagaResponse.class);
- when(task.commit(eq(NoOpSagaRequest.SAGA_END_REQUEST), argumentCaptor.capture())).thenReturn(
- SagaResponse.EMPTY_RESPONSE);
-
- ActorRef root = actorBuilder.build(requests, tasks, getRef()).actorOf(NoOpSagaRequest.SAGA_START_REQUEST.id());
-
- root.tell(new TransactMessage(NoOpSagaRequest.SAGA_START_REQUEST, SagaResponse.EMPTY_RESPONSE), getRef());
-
- List<SagaResponse> responses = receiveN(1, duration("2 seconds")).stream()
- .map(o -> ((TransactMessage) o).response())
- .collect(Collectors.toList());
-
- assertThat(responses, Matchers.containsInAnyOrder(SagaResponse.EMPTY_RESPONSE));
-
- verify(task).commit(NoOpSagaRequest.SAGA_START_REQUEST, SagaResponse.EMPTY_RESPONSE);
- verify(task).commit(request1, SagaResponse.EMPTY_RESPONSE);
- verify(task).commit(request2, response1);
- verify(task).commit(request3, response1);
- verify(task).commit(eq(NoOpSagaRequest.SAGA_END_REQUEST), any(SagaResponse.class));
-
- SagaResponse response = argumentCaptor.getValue();
- assertThat(response, instanceOf(CompositeSagaResponse.class));
- assertThat(((CompositeSagaResponse) response).responses(),
- containsInAnyOrder(response2, response3));
- }};
- }
-
- @Test
- public void compensateAllCompletedTransactions() throws Exception {
- new TestKit(actorSystem) {{
- ArgumentCaptor<SagaResponse> argumentCaptor = ArgumentCaptor.forClass(SagaResponse.class);
- when(task.commit(eq(NoOpSagaRequest.SAGA_END_REQUEST), argumentCaptor.capture())).thenReturn(
- SagaResponse.EMPTY_RESPONSE);
-
- ActorRef root = actorBuilder.build(requests, tasks, getRef()).actorOf(NoOpSagaRequest.SAGA_START_REQUEST.id());
-
- root.tell(new TransactMessage(NoOpSagaRequest.SAGA_START_REQUEST, SagaResponse.EMPTY_RESPONSE), getRef());
-
- List<SagaResponse> responses = receiveN(1, duration("2 seconds")).stream()
- .map(o -> ((TransactMessage) o).response())
- .collect(Collectors.toList());
-
- assertThat(responses, Matchers.containsInAnyOrder(SagaResponse.EMPTY_RESPONSE));
-
- CompensateMessage message = new CompensateMessage(response1);
- getLastSender().tell(message, getRef());
- expectMsg(message);
-
- verify(task).compensate(NoOpSagaRequest.SAGA_START_REQUEST);
- verify(task).compensate(request1);
- verify(task).compensate(request2);
- verify(task).compensate(request3);
- verify(task).compensate(NoOpSagaRequest.SAGA_END_REQUEST);
- }};
- }
-}
diff --git a/saga-core/src/test/java/org/apache/servicecomb/saga/core/actors/RequestActorTest.java b/saga-core/src/test/java/org/apache/servicecomb/saga/core/actors/RequestActorTest.java
deleted file mode 100644
index 776b5aa..0000000
--- a/saga-core/src/test/java/org/apache/servicecomb/saga/core/actors/RequestActorTest.java
+++ /dev/null
@@ -1,399 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core.actors;
-
-import static akka.actor.ActorRef.noSender;
-import static akka.actor.Props.empty;
-import static com.seanyinx.github.unit.scaffolding.Randomness.uniquify;
-import static java.util.Collections.emptySet;
-import static java.util.Collections.singleton;
-import static org.hamcrest.Matchers.contains;
-import static org.hamcrest.Matchers.containsInAnyOrder;
-import static org.hamcrest.core.IsInstanceOf.instanceOf;
-import static org.junit.Assert.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.util.List;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import org.apache.servicecomb.saga.core.CompositeSagaResponse;
-import org.apache.servicecomb.saga.core.FailedSagaResponse;
-import org.apache.servicecomb.saga.core.Operation;
-import org.apache.servicecomb.saga.core.SagaRequest;
-import org.apache.servicecomb.saga.core.SagaResponse;
-import org.apache.servicecomb.saga.core.SagaStartFailedException;
-import org.apache.servicecomb.saga.core.SagaTask;
-import org.apache.servicecomb.saga.core.TransactionFailedException;
-import org.apache.servicecomb.saga.core.actors.messages.AbortMessage;
-import org.apache.servicecomb.saga.core.actors.messages.CompensationRecoveryMessage;
-import org.apache.servicecomb.saga.core.actors.messages.TransactMessage;
-import org.apache.servicecomb.saga.core.actors.messages.TransactionRecoveryMessage;
-import org.hamcrest.Matchers;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mockito;
-import org.scalatest.junit.JUnitSuite;
-
-import org.apache.servicecomb.saga.core.actors.messages.CompensateMessage;
-import org.apache.servicecomb.saga.core.actors.messages.FailMessage;
-import org.apache.servicecomb.saga.core.application.interpreter.FromJsonFormat;
-import akka.actor.ActorRef;
-import akka.actor.ActorSystem;
-import akka.testkit.javadsl.TestKit;
-
-@SuppressWarnings("unchecked")
-public class RequestActorTest extends JUnitSuite {
- private final String parentRequestId1 = uniquify("parentRequestId1");
- private final String parentRequestId2 = uniquify("parentRequestId2");
- private final String requestId = uniquify("requestId");
-
- private final SagaTask task = Mockito.mock(SagaTask.class);
- private final SagaRequest request = Mockito.mock(SagaRequest.class, "request");
- private final SagaRequest request1 = Mockito.mock(SagaRequest.class, "request1");
- private final SagaRequest request2 = Mockito.mock(SagaRequest.class, "request2");
- private final SagaResponse response = Mockito.mock(SagaResponse.class);
- private final FromJsonFormat<Set<String>> childrenExtractor = mock(FromJsonFormat.class);
-
- private final RequestActorContext context = new RequestActorContext(childrenExtractor);
-
- private final TransactionFailedException exception = new TransactionFailedException("oops");
- private static final ActorSystem actorSystem = ActorSystem.create();
- private final CompensateMessage compensateMessage = new CompensateMessage(new FailedSagaResponse(exception));
-
- @Before
- public void setUp() throws Exception {
- when(childrenExtractor.fromJson(anyString())).thenReturn(emptySet());
- when(request.id()).thenReturn(requestId);
-
- when(request1.id()).thenReturn(parentRequestId1);
- when(request2.id()).thenReturn(parentRequestId2);
- }
-
- @AfterClass
- public static void tearDown() throws Exception {
- TestKit.shutdownActorSystem(actorSystem);
- }
-
- @Test
- public void tellNodeResponseToAllChildren() throws Exception {
- new TestKit(actorSystem) {{
- addChildren(getRef());
-
- ActorRef parent = someActor();
- context.addParent(requestId, parent);
-
- when(request.parents()).thenReturn(new String[] {parentRequestId1});
- when(task.commit(request, Operation.SUCCESSFUL_SAGA_RESPONSE)).thenReturn(response);
-
- ActorRef actorRef = actorSystem.actorOf(RequestActor.props(context, task, request));
-
- actorRef.tell(new TransactMessage(request1, Operation.SUCCESSFUL_SAGA_RESPONSE), parent);
-
- List<SagaResponse> responses = receiveN(2, duration("2 seconds")).stream()
- .map(o -> ((TransactMessage) o).response())
- .collect(Collectors.toList());
-
- assertThat(responses, containsInAnyOrder(response, response));
-
- verify(task).commit(request, Operation.SUCCESSFUL_SAGA_RESPONSE);
- }};
- }
-
- @Test
- public void executeTransaction_OnlyWhenAllParentsResponsesAreReceived() throws Exception {
- new TestKit(actorSystem) {{
- addChildren(getRef());
-
- ActorRef parent1 = someActor();
- context.addParent(requestId, parent1);
-
- ActorRef parent2 = someActor();
- context.addParent(requestId, parent2);
-
- ArgumentCaptor<SagaResponse> argumentCaptor = ArgumentCaptor.forClass(SagaResponse.class);
-
- when(request.parents()).thenReturn(new String[] {parentRequestId1, parentRequestId2});
- when(task.commit(eq(request), argumentCaptor.capture())).thenReturn(response);
-
- ActorRef actorRef = actorSystem.actorOf(RequestActor.props(context, task, request));
-
- actorRef.tell(new TransactMessage(request1, Operation.SUCCESSFUL_SAGA_RESPONSE), parent1);
- expectNoMsg(duration("500 milliseconds"));
-
- actorRef.tell(new TransactMessage(request2, SagaResponse.EMPTY_RESPONSE), parent2);
-
- List<SagaResponse> responses = receiveN(2, duration("2 seconds")).stream()
- .map(o -> ((TransactMessage) o).response())
- .collect(Collectors.toList());
-
- assertThat(responses, containsInAnyOrder(response, response));
-
- SagaResponse response = argumentCaptor.getValue();
- assertThat(response, instanceOf(CompositeSagaResponse.class));
- assertThat(((CompositeSagaResponse) response).responses(),
- Matchers.containsInAnyOrder(SagaResponse.EMPTY_RESPONSE, Operation.SUCCESSFUL_SAGA_RESPONSE));
- }};
- }
-
- @Test
- public void tellAllRelativesToAbortOnError() throws Exception {
- new TestKit(actorSystem) {{
- context.addChild(requestId, getRef());
- context.addActor(requestId, getRef());
-
- context.addParent(requestId, getRef());
-
- when(request.parents()).thenReturn(new String[] {parentRequestId1});
- when(task.commit(request, Operation.SUCCESSFUL_SAGA_RESPONSE)).thenThrow(exception);
-
- ActorRef actorRef = actorSystem.actorOf(RequestActor.props(context, task, request));
-
- actorRef.tell(new TransactMessage(request1, Operation.SUCCESSFUL_SAGA_RESPONSE), getRef());
-
- List<SagaResponse> responses = receiveN(2, duration("2 seconds")).stream()
- .map(o -> ((AbortMessage) o).response())
- .collect(Collectors.toList());
-
- assertThat(responses, containsInAnyOrder(instanceOf(FailedSagaResponse.class), instanceOf(FailedSagaResponse.class)));
- }};
- }
-
- @Test
- public void tellAllRelativesExceptSenderToAbortOnAbort() throws Exception {
- new TestKit(actorSystem) {{
- context.addChild(requestId, getRef());
- context.addActor(requestId, getRef());
-
- context.addParent(requestId, getRef());
-
- when(request.parents()).thenReturn(new String[] {parentRequestId1});
-
- ActorRef actorRef = actorSystem.actorOf(RequestActor.props(context, task, request));
-
- actorRef.tell(new AbortMessage(exception), someActor());
-
- List<SagaResponse> responses = receiveN(2, duration("2 seconds")).stream()
- .map(o -> ((AbortMessage) o).response())
- .collect(Collectors.toList());
-
- assertThat(responses, containsInAnyOrder(instanceOf(FailedSagaResponse.class), instanceOf(FailedSagaResponse.class)));
-
- actorRef.tell(new AbortMessage(exception), someActor());
- expectNoMsg(duration("500 milliseconds"));
- }};
- }
-
- @Test
- public void compensateIfTransactionIsCompleted() throws Exception {
- new TestKit(actorSystem) {{
- addChildren(someActor());
- context.addParent(requestId, getRef());
-
- when(request.parents()).thenReturn(new String[] {parentRequestId1});
- when(task.commit(request, Operation.SUCCESSFUL_SAGA_RESPONSE)).thenReturn(response);
-
- ActorRef actorRef = actorSystem.actorOf(RequestActor.props(context, task, request));
-
- actorRef.tell(new TransactMessage(request1, Operation.SUCCESSFUL_SAGA_RESPONSE), getRef());
- actorRef.tell(new AbortMessage(exception), noSender());
- actorRef.tell(compensateMessage, getRef());
- actorRef.tell(compensateMessage, getRef());
-
- expectMsg(duration("2 seconds"), compensateMessage);
- verify(task).compensate(request);
-
- // no duplicate compensation
- reset(task);
- actorRef.tell(compensateMessage, getRef());
- actorRef.tell(compensateMessage, getRef());
- expectNoMsg(duration("200 milliseconds"));
- verify(task, never()).compensate(request);
- }};
- }
-
- @Test
- public void doNotCompensateIfTransactionIsNotCompleted() throws Exception {
- new TestKit(actorSystem) {{
- addChildren(someActor());
- context.addParent(requestId, getRef());
-
- when(request.parents()).thenReturn(new String[] {parentRequestId1});
-
- ActorRef actorRef = actorSystem.actorOf(RequestActor.props(context, task, request));
-
- actorRef.tell(new AbortMessage(exception), noSender());
- actorRef.tell(compensateMessage, getRef());
- actorRef.tell(compensateMessage, getRef());
-
- List<Object> responses = receiveN(2, duration("2 seconds"));
- assertThat(responses, contains(instanceOf(AbortMessage.class), instanceOf(CompensateMessage.class)));
- verify(task, never()).compensate(request);
-
- // no duplicate compensation
- reset(task);
- actorRef.tell(compensateMessage, getRef());
- actorRef.tell(compensateMessage, getRef());
- expectNoMsg(duration("200 milliseconds"));
- verify(task, never()).compensate(request);
- }};
- }
-
- @Test
- public void skipIfActorIsNotChosenByAnyParent() throws Exception {
- when(childrenExtractor.fromJson(Operation.SUCCESSFUL_SAGA_RESPONSE.body())).thenReturn(singleton("none"));
-
- new TestKit(actorSystem) {{
- addChildren(getRef());
- context.addParent(requestId, getRef());
-
- when(request.parents()).thenReturn(new String[] {parentRequestId1});
-
- ActorRef actorRef = actorSystem.actorOf(RequestActor.props(context, task, request));
-
- actorRef.tell(new TransactMessage(request1, Operation.SUCCESSFUL_SAGA_RESPONSE), getRef());
-
- List<SagaResponse> responses = receiveN(2, duration("2 seconds")).stream()
- .map(o -> ((TransactMessage) o).response())
- .collect(Collectors.toList());
-
- assertThat(responses, Matchers.containsInAnyOrder(SagaResponse.NONE_RESPONSE, SagaResponse.NONE_RESPONSE));
- verify(task, never()).commit(request, Operation.SUCCESSFUL_SAGA_RESPONSE);
-
- // skip compensation for ignored actor
- actorRef.tell(compensateMessage, getRef());
- actorRef.tell(compensateMessage, getRef());
-
- expectMsg(duration("2 seconds"), compensateMessage);
- verify(task, never()).compensate(request);
- }};
- }
-
- @Test
- public void transactIfChosenByAnyParent() throws Exception {
- when(childrenExtractor.fromJson(Operation.SUCCESSFUL_SAGA_RESPONSE.body())).thenReturn(singleton(requestId));
-
- new TestKit(actorSystem) {{
- addChildren(getRef());
-
- ActorRef parent1 = someActor();
- context.addParent(requestId, parent1);
-
- ActorRef parent2 = someActor();
- context.addParent(requestId, parent2);
-
- when(request.parents()).thenReturn(new String[] {parentRequestId1, parentRequestId2});
- when(task.commit(eq(request), any(CompositeSagaResponse.class))).thenReturn(response);
-
- ActorRef actorRef = actorSystem.actorOf(RequestActor.props(context, task, request));
-
- actorRef.tell(new TransactMessage(request1, Operation.SUCCESSFUL_SAGA_RESPONSE), parent1);
- actorRef.tell(new TransactMessage(request2, Operation.SUCCESSFUL_SAGA_RESPONSE), parent2);
-
- List<SagaResponse> responses = receiveN(2, duration("2 seconds")).stream()
- .map(o -> ((TransactMessage) o).response())
- .collect(Collectors.toList());
-
- assertThat(responses, containsInAnyOrder(response, response));
- }};
- }
-
- @Test
- public void tellTransactionResponseToChildrenOnRecovery() throws Exception {
- new TestKit(actorSystem) {{
- context.addChild(requestId, getRef());
-
- ActorRef parent = someActor();
- context.addParent(requestId, parent);
-
- when(request.parents()).thenReturn(new String[] {parentRequestId1});
-
- ActorRef actorRef = actorSystem.actorOf(RequestActor.props(context, task, request));
-
- actorRef.tell(new TransactionRecoveryMessage(response), noSender());
- actorRef.tell(new TransactMessage(request1, Operation.SUCCESSFUL_SAGA_RESPONSE), parent);
-
- List<SagaResponse> responses = receiveN(1, duration("2 seconds")).stream()
- .map(o -> ((TransactMessage) o).response())
- .collect(Collectors.toList());
-
- assertThat(responses, containsInAnyOrder(response));
-
- verify(task, never()).commit(request, Operation.SUCCESSFUL_SAGA_RESPONSE);
- }};
- }
-
- @Test
- public void tellCompensationToParentsOnRecovery() throws Exception {
- new TestKit(actorSystem) {{
- context.addChild(requestId, someActor());
- context.addParent(requestId, getRef());
-
- when(request.parents()).thenReturn(new String[] {parentRequestId1});
-
- ActorRef actorRef = actorSystem.actorOf(RequestActor.props(context, task, request));
-
- actorRef.tell(new AbortMessage(exception), someActor());
- actorRef.tell(new CompensationRecoveryMessage(), someActor());
- actorRef.tell(compensateMessage, someActor());
-
- List<Object> responses = receiveN(2, duration("2 seconds"));
- assertThat(responses, contains(instanceOf(AbortMessage.class), instanceOf(CompensateMessage.class)));
-
- verify(task, never()).compensate(request);
- }};
- }
-
- @Test
- public void abortOnPersistenceFailure() throws Exception {
- new TestKit(actorSystem) {{
- context.addChild(requestId, noSender());
- context.addParent(requestId, getRef());
-
- when(request.parents()).thenReturn(new String[] {parentRequestId1});
-
- SagaStartFailedException oops = new SagaStartFailedException("oops", exception);
- when(task.commit(request, SagaResponse.EMPTY_RESPONSE)).thenThrow(oops);
-
- ActorRef actorRef = actorSystem.actorOf(RequestActor.props(context, task, request));
-
- actorRef.tell(new TransactMessage(request, SagaResponse.EMPTY_RESPONSE), getRef());
-
- expectMsgClass(FailMessage.class);
- }};
- }
-
- private ActorRef someActor() {
- return actorSystem.actorOf(empty());
- }
-
- private void addChildren(ActorRef ref) {
- context.addChild(requestId, ref);
- context.addChild(requestId, ref);
- context.addActor(requestId, ref);
- }
-}
diff --git a/saga-core/src/test/java/org/apache/servicecomb/saga/core/dag/DirectedAcyclicGraphTraversalTest.java b/saga-core/src/test/java/org/apache/servicecomb/saga/core/dag/DirectedAcyclicGraphTraversalTest.java
deleted file mode 100644
index beb9607..0000000
--- a/saga-core/src/test/java/org/apache/servicecomb/saga/core/dag/DirectedAcyclicGraphTraversalTest.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core.dag;
-
-import static java.util.Arrays.asList;
-import static org.hamcrest.collection.IsIterableContainingInOrder.contains;
-import static org.junit.Assert.assertThat;
-
-import java.util.Collection;
-import org.junit.Before;
-import org.junit.Test;
-
-public class DirectedAcyclicGraphTraversalTest {
-
- private final Node<String> root = new Node<>(0, "i don't care");
- private final Node<String> node1 = new Node<>(1, "i don't care");
- private final Node<String> node2 = new Node<>(2, "i don't care");
- private final Node<String> node3 = new Node<>(3, "i don't care");
- private final Node<String> node4 = new Node<>(4, "i don't care");
- private final Node<String> node5 = new Node<>(5, "i don't care");
- private final Node<String> leaf = new Node<>(6, "i don't care");
-
- private final SingleLeafDirectedAcyclicGraph<String> dag = new SingleLeafDirectedAcyclicGraph<>(root, leaf);
-
- // 0
- // / \
- // 1 \
- // / \ \
- // 3 4 2
- // \ / /
- // 5 /
- // \ /
- // 6
- @Before
- public void setUp() throws Exception {
- root.addChildren(asList(node1, node2));
- node1.addChildren(asList(node3, node4));
- node3.addChild(node5);
- node4.addChild(node5);
- node5.addChild(leaf);
- node2.addChild(leaf);
- }
-
- @Test
- public void traverseGraphOneLevelPerStepFromRoot() {
- Traveller<String> traveller = new ByLevelTraveller<>(dag, new FromRootTraversalDirection<>());
-
- Collection<Node<String>> nodes = traveller.nodes();
-
- traveller.next();
- assertThat(nodes, contains(root));
-
- traveller.next();
- assertThat(nodes, contains(root, node1, node2));
-
- traveller.next();
- assertThat(nodes, contains(root, node1, node2, node3, node4));
-
- traveller.next();
- assertThat(nodes, contains(root, node1, node2, node3, node4, node5));
-
- traveller.next();
- assertThat(nodes, contains(root, node1, node2, node3, node4, node5, leaf));
- }
-
- @Test
- public void traverseGraphOneLevelPerStepFromLeaf() {
- Traveller<String> traveller = new ByLevelTraveller<>(dag, new FromLeafTraversalDirection<>());
-
- Collection<Node<String>> nodes = traveller.nodes();
-
- traveller.next();
- assertThat(nodes, contains(leaf));
-
- traveller.next();
- assertThat(nodes, contains(leaf, node2, node5));
-
- traveller.next();
- assertThat(nodes, contains(leaf, node2, node5, node3, node4));
-
- traveller.next();
- assertThat(nodes, contains(leaf, node2, node5, node3, node4, node1));
-
- traveller.next();
- assertThat(nodes, contains(leaf, node2, node5, node3, node4, node1, root));
- }
-}
diff --git a/saga-core/src/test/java/org/apache/servicecomb/saga/core/dag/GraphBasedSagaExecutionComponentTest.java b/saga-core/src/test/java/org/apache/servicecomb/saga/core/dag/GraphBasedSagaExecutionComponentTest.java
deleted file mode 100644
index 8515f93..0000000
--- a/saga-core/src/test/java/org/apache/servicecomb/saga/core/dag/GraphBasedSagaExecutionComponentTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core.dag;
-
-import java.util.concurrent.Executors;
-
-import org.apache.servicecomb.saga.core.PersistentStore;
-import org.apache.servicecomb.saga.core.SagaExecutionComponentTestBase;
-import org.apache.servicecomb.saga.core.application.SagaFactory;
-
-
-public class GraphBasedSagaExecutionComponentTest extends SagaExecutionComponentTestBase {
-
- @Override
- protected SagaFactory sagaFactory(PersistentStore eventStore) {
- return new GraphBasedSagaFactory(500, eventStore, null, Executors.newFixedThreadPool(5));
- }
-}
diff --git a/saga-core/src/test/java/org/apache/servicecomb/saga/core/dag/GraphBuilderTest.java b/saga-core/src/test/java/org/apache/servicecomb/saga/core/dag/GraphBuilderTest.java
deleted file mode 100644
index 8703c7a..0000000
--- a/saga-core/src/test/java/org/apache/servicecomb/saga/core/dag/GraphBuilderTest.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core.dag;
-
-import static com.seanyinx.github.unit.scaffolding.AssertUtils.expectFailing;
-import static org.apache.servicecomb.saga.core.Operation.TYPE_REST;
-import static java.util.Collections.emptyMap;
-import static java.util.Collections.emptySet;
-import static java.util.Collections.singleton;
-import static org.hamcrest.CoreMatchers.startsWith;
-import static org.hamcrest.collection.IsIterableContainingInOrder.contains;
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.when;
-
-import java.util.Collection;
-import java.util.stream.Collectors;
-
-import org.apache.servicecomb.saga.core.NoOpSagaRequest;
-import org.apache.servicecomb.saga.core.SagaException;
-import org.apache.servicecomb.saga.core.SagaRequest;
-import org.apache.servicecomb.saga.core.SagaRequestImpl;
-import org.hamcrest.collection.IsIterableContainingInOrder;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mockito;
-
-import org.apache.servicecomb.saga.core.CompensationImpl;
-import org.apache.servicecomb.saga.core.TransactionImpl;
-
-@SuppressWarnings("unchecked")
-public class GraphBuilderTest {
-
- private final SagaRequest request1 = new SagaRequestImpl(
- "request-aaa",
- "aaa",
- TYPE_REST,
- new TransactionImpl("/rest/as", "post", emptyMap()),
- new CompensationImpl("/rest/as","delete", emptyMap())
- );
-
- private final SagaRequest request2 = new SagaRequestImpl(
- "request-bbb",
- "bbb",
- TYPE_REST,
- new TransactionImpl("/rest/bs", "post", emptyMap()),
- new CompensationImpl("/rest/bs","delete", emptyMap())
- );
-
- private final SagaRequest request3 = new SagaRequestImpl(
- "request-ccc",
- "ccc",
- TYPE_REST,
- new TransactionImpl("/rest/cs", "post", emptyMap()),
- new CompensationImpl("/rest/cs","delete", emptyMap()),
- null,
- new String[]{"request-aaa", "request-bbb"}
- );
- private final SagaRequest[] requests = {request1, request2, request3};
-
- private final SagaRequest duplicateRequest = new SagaRequestImpl(
- "request-duplicate-id",
- "xxx",
- TYPE_REST,
- new TransactionImpl("/rest/xs", "post", emptyMap()),
- new CompensationImpl("/rest/xs","delete", emptyMap())
- );
- private final SagaRequest[] duplicateRequests = {duplicateRequest, duplicateRequest};
-
- private final GraphCycleDetector<SagaRequest> detector = Mockito.mock(GraphCycleDetector.class);
- private final GraphBuilder graphBuilder = new GraphBuilder(detector);
-
- @Before
- public void setUp() throws Exception {
- when(detector.cycleJoints(any())).thenReturn(emptySet());
- }
-
- @Test
- public void buildsGraphOfParallelRequests() {
- SingleLeafDirectedAcyclicGraph<SagaRequest> tasks = graphBuilder.build(requests);
-
- Traveller<SagaRequest> traveller = new ByLevelTraveller<>(tasks, new FromRootTraversalDirection<>());
- Collection<Node<SagaRequest>> nodes = traveller.nodes();
-
- traveller.next();
- assertThat(requestsOf(nodes), IsIterableContainingInOrder.contains(NoOpSagaRequest.SAGA_START_REQUEST));
- nodes.clear();
-
- traveller.next();
- assertThat(requestsOf(nodes), contains(request1, request2));
- nodes.clear();
-
- traveller.next();
- assertThat(requestsOf(nodes), contains(request3));
- nodes.clear();
-
- traveller.next();
- assertThat(requestsOf(nodes), IsIterableContainingInOrder.contains(NoOpSagaRequest.SAGA_END_REQUEST));
- }
-
- @Test
- public void blowsUpWhenJsonContainsDuplicateRequestId() {
- try {
- graphBuilder.build(duplicateRequests);
- fail(SagaException.class.getSimpleName() + " is expected, but none thrown");
- } catch (SagaException e) {
- assertThat(e.getMessage(),
- is("Failed to interpret requests with duplicate request id: request-duplicate-id"));
- }
- }
-
- @Test
- public void blowsUpWhenGraphContainsCycle() {
- reset(detector);
- when(detector.cycleJoints(any())).thenReturn(singleton(new Node<>(0L, null)));
-
- try {
- graphBuilder.build(requests);
- expectFailing(SagaException.class);
- } catch (SagaException e) {
- assertThat(e.getMessage(), startsWith("Cycle detected in the request graph at nodes "));
- }
- }
-
- private Collection<SagaRequest> requestsOf(Collection<Node<SagaRequest>> nodes) {
- return nodes.stream()
- .map(Node::value)
- .collect(Collectors.toList());
- }
-}
diff --git a/saga-core/src/test/java/org/apache/servicecomb/saga/core/dag/GraphCycleDetectorTest.java b/saga-core/src/test/java/org/apache/servicecomb/saga/core/dag/GraphCycleDetectorTest.java
deleted file mode 100644
index 934c54b..0000000
--- a/saga-core/src/test/java/org/apache/servicecomb/saga/core/dag/GraphCycleDetectorTest.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core.dag;
-
-import static org.hamcrest.Matchers.contains;
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
-
-import java.util.Set;
-import org.junit.Before;
-import org.junit.Test;
-
-@SuppressWarnings("unchecked")
-public class GraphCycleDetectorTest {
-
- private final Node<String> root = node(0);
- private final Node<String> leaf = node(Long.MAX_VALUE);
-
- private final Node<String> node1 = node(1);
- private final Node<String> node2 = node(2);
- private final Node<String> node3 = node(3);
-
- private final SingleLeafDirectedAcyclicGraph<String> graph = new SingleLeafDirectedAcyclicGraph<>(root, leaf);
- private final GraphCycleDetector<String> detector = new GraphCycleDetectorImpl<>();
-
- @Before
- public void setUp() throws Exception {
- root.addChild(node1);
-
- node2.addChild(leaf);
- node3.addChild(leaf);
- }
-
- @Test
- public void emptyNodesWhenNoCycleInGraph() {
- node1.addChild(node2);
- node1.addChild(node3);
-
- Set<Node<String>> nodes = detector.cycleJoints(graph);
-
- assertThat(nodes.isEmpty(), is(true));
- }
-
- @Test
- public void nonEmptyNodesIfGraphContainsCycle() {
- node1.addChild(node2);
- node2.addChild(node3);
- node3.addChild(node1);
-
- Set<Node<String>> nodes = detector.cycleJoints(graph);
-
- assertThat(nodes, contains(node1));
- }
-
- private Node<String> node(long id) {
- return new Node<>(id, "value " + id);
- }
-}
diff --git a/saga-core/src/test/java/org/apache/servicecomb/saga/core/dag/NodeTest.java b/saga-core/src/test/java/org/apache/servicecomb/saga/core/dag/NodeTest.java
deleted file mode 100644
index 2da4ba0..0000000
--- a/saga-core/src/test/java/org/apache/servicecomb/saga/core/dag/NodeTest.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.core.dag;
-
-import static java.util.Arrays.asList;
-import static org.hamcrest.Matchers.containsInAnyOrder;
-import static org.hamcrest.collection.IsIterableContainingInOrder.contains;
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
-
-import org.junit.Before;
-import org.junit.Test;
-
-public class NodeTest {
-
-
- private final Node<String> parent = new Node<>(0, "i don't care");
- private final Node<String> node1 = new Node<>(1, "i don't care");
- private final Node<String> node2 = new Node<>(2, "i don't care");
- private final Node<String> node3 = new Node<>(3, "i don't care");
- private final Node<String> node4 = new Node<>(4, "i don't care");
- private final Node<String> node5 = new Node<>(5, "i don't care");
- private final Node<String> node6 = new Node<>(6, "i don't care");
-
- // 0
- // / \
- // 1 \
- // / \ \
- // 3 4 2
- // \ / /
- // 5 /
- // \ /
- // 6
- @Before
- public void setUp() throws Exception {
- parent.addChildren(asList(node1, node2));
- node1.addChildren(asList(node3, node4));
- node3.addChild(node5);
- node4.addChild(node5);
- node5.addChild(node6);
- node2.addChild(node6);
- }
-
- @Test
- public void nodeIsLinkedBidirectionally() {
- assertThat(parent.children(), containsInAnyOrder(node1, node2));
- assertThat(node1.parents(), contains(parent));
- assertThat(node1.children(), containsInAnyOrder(node3, node4));
-
- assertThat(node2.parents(), contains(parent));
- assertThat(node2.children(), contains(node6));
-
- assertThat(node3.parents(), contains(node1));
- assertThat(node3.children(), contains(node5));
-
- assertThat(node4.parents(), contains(node1));
- assertThat(node4.children(), contains(node5));
-
- assertThat(node5.parents(), containsInAnyOrder(node3, node4));
- assertThat(node5.children(), contains(node6));
-
- assertThat(node6.parents(), containsInAnyOrder(node2, node5));
- assertThat(node6.children().isEmpty(), is(true));
- }
-}
diff --git a/saga-core/src/test/java/org/apache/servicecomb/saga/infrastructure/ContextAwareEventStoreTest.java b/saga-core/src/test/java/org/apache/servicecomb/saga/infrastructure/ContextAwareEventStoreTest.java
deleted file mode 100644
index 1216e5f..0000000
--- a/saga-core/src/test/java/org/apache/servicecomb/saga/infrastructure/ContextAwareEventStoreTest.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.servicecomb.saga.infrastructure;
-
-import static org.mockito.Mockito.verify;
-
-import org.apache.servicecomb.saga.core.EventStore;
-import org.junit.Test;
-import org.mockito.Mockito;
-
-import org.apache.servicecomb.saga.core.SagaContext;
-import org.apache.servicecomb.saga.core.SagaEvent;
-
-public class ContextAwareEventStoreTest {
- private final EventStore underlying = Mockito.mock(EventStore.class);
- private final SagaContext context = Mockito.mock(SagaContext.class);
- private final SagaEvent sagaEvent = Mockito.mock(SagaEvent.class);
-
- private final ContextAwareEventStore contextAwareEventStore = new ContextAwareEventStore(underlying, context);
-
- @Test
- public void persistWithUnderlyingStore() throws Exception {
- contextAwareEventStore.offer(sagaEvent);
-
- verify(sagaEvent).gatherTo(context);
- verify(underlying).offer(sagaEvent);
- }
-}
diff --git a/saga-core/src/test/resources/application.conf b/saga-core/src/test/resources/application.conf
deleted file mode 100644
index 0629dd6..0000000
--- a/saga-core/src/test/resources/application.conf
+++ /dev/null
@@ -1,21 +0,0 @@
-## ---------------------------------------------------------------------------
-## Licensed to the Apache Software Foundation (ASF) under one or more
-## contributor license agreements. See the NOTICE file distributed with
-## this work for additional information regarding copyright ownership.
-## The ASF licenses this file to You under the Apache License, Version 2.0
-## (the "License"); you may not use this file except in compliance with
-## the License. You may obtain a copy of the License at
-##
-## http://www.apache.org/licenses/LICENSE-2.0
-##
-## Unless required by applicable law or agreed to in writing, software
-## distributed under the License is distributed on an "AS IS" BASIS,
-## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-## See the License for the specific language governing permissions and
-## limitations under the License.
-## ---------------------------------------------------------------------------
-akka {
- loggers = ["akka.event.slf4j.Slf4jLogger"]
- loglevel = "DEBUG"
- logging-filter = "akka.event.slf4j.Slf4jLoggingFilter"
-}
diff --git a/saga-core/src/test/resources/log4j2.xml b/saga-core/src/test/resources/log4j2.xml
deleted file mode 100644
index cae04cb..0000000
--- a/saga-core/src/test/resources/log4j2.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ Licensed to the Apache Software Foundation (ASF) under one or more
- ~ contributor license agreements. See the NOTICE file distributed with
- ~ this work for additional information regarding copyright ownership.
- ~ The ASF licenses this file to You under the Apache License, Version 2.0
- ~ (the "License"); you may not use this file except in compliance with
- ~ the License. You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<Configuration status="WARN">
- <Appenders>
- <Console name="Console" target="SYSTEM_OUT">
- <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
- </Console>
- </Appenders>
- <Loggers>
- <AsyncRoot level="info">
- <AppenderRef ref="Console"/>
- </AsyncRoot>
- </Loggers>
-</Configuration>
diff --git a/saga-demo/conditional-transaction-demo/README.md b/saga-demo/conditional-transaction-demo/README.md
deleted file mode 100755
index 9ae1deb..0000000
--- a/saga-demo/conditional-transaction-demo/README.md
+++ /dev/null
@@ -1,174 +0,0 @@
-# Conditional Transaction Demo
-This demo simulates a partial backend of an e-commerce application including four services:
-* payment
-* membership
-* inventory
-* supplier
-
-**Note** Please go through the dependency-free-transaction-demo first, before proceeding with this demo.
-
-## Background
-Many e-commerce sites have membership concept, which will level up when a customer makes a certain amount of purchase.
-Moreover, as goods are sold and the stock drops to a certain level, the e-commerce company needs to fetch more goods from
-its suppliers. Both scenarios introduce conditional transactions.
-
-## Workflow
-```
- /---> if total purchase >= 1K, level up membership
-start ---> make payment ---> dispatch product from inventory ---> end
- \---> if product stock < 10, replenish product from supplier
-```
-The conditions are business logic and belong to business service. Therefore, the decision to level up membership is made
-in payment service and the decision to replenish products is made in inventory service. Saga is to be informed of service
-decision by adding an additional element `sagaChildren` in service response JSON to indicate which services are to be invoked
-next as shown below.
-```json
-{
- "customerId": "mike",
- "body": "Payment made with id xxx for customer mike",
- "sagaChildren": ["inventory"]
-}
-```
-
-If `sagaChildren` is empty or not provided in service response, saga will invoke all of its child services. To invoke none
-of them, explicitly return `"sagaChildren": ["none"]`.
-
-If any of the sub-transaction specified in sagaChildren fails, all completed sub-transactions will be compensated as usual,
-when the recovery policy if backward recovery.
-
-## Running Demo
-1. run the following command to create docker images in saga project root folder.
-```
-mvn package -DskipTests -Pdocker -Pdemo
-```
-
-2. start application up in saga/saga-demo/conditional-transaction-demo with the following command
-```
-docker-compose up
-```
-
-## User Requests
-The request JSON to ensure the workflow order looks like the following:
-```json
-{
- "policy": "BackwardRecovery",
- "requests": [
- {
- "id": "payment",
- "type": "rest",
- "serviceName": "payment.servicecomb.io:8080",
- "transaction": {
- "method": "post",
- "path": "/payment",
- "params": {
- "form": {
- "customerId": "mike",
- "purchaseAmount": 400
- }
- }
- },
- "compensation": {
- "method": "put",
- "path": "/payment",
- "params": {
- "form": {
- "customerId": "mike"
- }
- }
- }
- },
- {
- "id": "membership",
- "type": "rest",
- "serviceName": "membership.servicecomb.io:8080",
- "parents": [
- "payment"
- ],
- "transaction": {
- "method": "post",
- "path": "/membership",
- "params": {
- "form": {
- "customerId": "mike"
- }
- }
- },
- "compensation": {
- "method": "put",
- "path": "/membership",
- "params": {
- "form": {
- "customerId": "mike"
- }
- }
- }
- },
- {
- "id": "inventory",
- "type": "rest",
- "serviceName": "inventory.servicecomb.io:8080",
- "parents": [
- "payment"
- ],
- "transaction": {
- "method": "post",
- "path": "/inventory",
- "params": {
- "form": {
- "customerId": "mike"
- }
- }
- },
- "compensation": {
- "method": "put",
- "path": "/inventory",
- "params": {
- "form": {
- "customerId": "mike"
- }
- }
- }
- },
- {
- "id": "supplier",
- "type": "rest",
- "serviceName": "supplier.servicecomb.io:8080",
- "parents": [
- "inventory"
- ],
- "transaction": {
- "method": "post",
- "path": "/supplier",
- "params": {
- "form": {
- "customerId": "servicecomb_mall"
- }
- }
- },
- "compensation": {
- "method": "put",
- "path": "/supplier",
- "params": {
- "form": {
- "customerId": "servicecomb_mall"
- }
- }
- }
- }
- ]
-}
-
-```
-
-To send the above JSON request to Saga, use [postman](https://www.getpostman.com/postman) with POST request to url `http://<docker.host.ip>:8083/requests`
-
-Each request to payment service will increase user mike's total purchase by $400. The 3<sup>rd</sup> request will trigger
-membership level up.
-
-The initial product stock is 11 in inventory and each request to inventory service will deduct product stock by 1.
-So the 2<sup>nd</sup> request will trigger product replenishment from supplier.
-
-**Note** transactions and compensations implemented by services must be idempotent. In this demo, we did not enforce that
-for simplicity.
-
-To see all events generated by Saga, visit `http://<docker.host.ip>:8083/events` with postman.
diff --git a/saga-demo/conditional-transaction-demo/conditional-transaction-demo-tests/pom.xml b/saga-demo/conditional-transaction-demo/conditional-transaction-demo-tests/pom.xml
deleted file mode 100644
... 11964 lines suppressed ...
--
To stop receiving notification emails like this one, please contact
ningjiang@apache.org.