[ 
https://issues.apache.org/jira/browse/CAMEL-25006?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18118913#comment-18118913
 ] 

shashank commented on CAMEL-25006:
----------------------------------

PR: https://github.com/apache/camel/pull/26866

_Claude Code on behalf of allthingssecurity_

> In-memory Saga: after a saga timed out, a REQUIRED step on the same exchange 
> silently starts and completes a new saga (SUPPORTS runs outside any saga)
> ------------------------------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: CAMEL-25006
>                 URL: https://issues.apache.org/jira/browse/CAMEL-25006
>             Project: Camel
>          Issue Type: Bug
>          Components: camel-core
>            Reporter: shashank
>            Priority: Minor
>
> Since CAMEL-24144 (4.22.0) {{InMemorySagaCoordinator}} removes itself from 
> {{InMemorySagaService}} when it reaches COMPENSATED/COMPLETED 
> ({{doCompensate}}/{{doComplete}}, {{InMemorySagaCoordinator.java:170-190}}). 
> {{getSaga(id)}} then returns {{null}} ({{InMemorySagaService.java:63-65}}), 
> and the saga processors treat {{null}} as "this exchange is not in a saga":
> * {{RequiredSagaProcessor}} creates a new saga 
> ({{RequiredSagaProcessor.java:44-50}}) and, as the new saga is not inherited, 
> completes it at the end of the step ({{:58-60}});
> * {{SupportsSagaProcessor}} runs the step outside any saga 
> ({{SupportsSagaProcessor.java:47-48}});
> * {{MandatorySagaProcessor}} fails with "Exchange is not part of a saga" 
> ({{:39-41}}).
> The exchange still carries the id of the saga it belongs to. When that saga 
> timed out, the next REQUIRED step is completed in a saga of its own, while 
> the saga the exchange belongs to has been compensated. Before CAMEL-24144 the 
> same step failed at {{beginStep}} with {{IllegalStateException}} (the 
> CAMEL-24144 ticket describes that behaviour), and it still fails that way 
> when it arrives while the saga is COMPENSATING. So the outcome depends on 
> whether the compensation already finished.
> *Reproduction*:
> {code:java}
> from("direct:owner").saga().timeout(200, 
> MILLISECONDS).compensation("direct:compOwner")
>     .process(e -> Thread.sleep(400))       // a slow call outlasts the saga 
> timeout
>     .to("direct:payment");
> from("direct:payment").saga()             // REQUIRED (default)
>     .compensation("direct:compPayment").completion("direct:complPayment")
>     .process(e -> paymentTaken++);
> {code}
> {noformat}
> [stale: payment arrives after the saga was COMPENSATED+removed] owner 
> failed=true exception=IllegalStateException: Cannot complete: status is 
> COMPENSATED
> [stale: ...] compOwner=1 paymentAction=1 complPayment=1 compPayment=0
> [stale control: payment arrives while COMPENSATING] owner failed=true 
> exception=IllegalStateException: Cannot begin: status is COMPENSATING
> [stale control: ...] compOwner=1 paymentAction=0 complPayment=0 compPayment=0
> {noformat}
> The order was compensated, yet the payment was taken and confirmed (its 
> completion ran), and nothing will ever compensate it.
> TLA+: {{NoMixedOutcome}} (a participant carrying S's id never runs in another 
> saga or outside a saga while S compensates) is violated by 
> {{sync_timeout_required}} and {{sync_timeout_supports}} (TimerFire -> FzSnap 
> -> FzRun -> FzFinal -> PArrive(p1)). With a tombstone for ended sagas 
> ({{fix_*}}) the property holds.
> *Proposed fix:* distinguish "no saga id" from "unknown/ended saga id":
> * {{InMemorySagaService}} keeps a bounded tombstone of ended saga ids (or the 
> coordinator object in a small expiring map) and {{getSaga}} returns the ended 
> coordinator, whose {{beginStep}} fails with "Cannot begin: status is 
> COMPENSATED/COMPLETED" as before CAMEL-24144; or
> * {{SagaProcessor.getCurrentSagaCoordinator}} fails the exchange ("saga <id> 
> is no longer active") when the exchange carries an id and the service returns 
> {{null}}, instead of falling through to "no saga".
> The PR takes the second option: the in-memory service keeps removing ended 
> sagas (the memory fix of CAMEL-24144), and REQUIRED/SUPPORTS steps fail when 
> the exchange carries the id of a saga that the service does not know.
> _Filed with Claude Code on behalf of allthingssecurity._



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to