Sub-scope 06 (mongo) transaction (+retry, +session) — manifest and negative-space probes
revision=a24ece9cf797f7ea647e33bf846b115208ed1ba5
generatedAt=2026-08-29T23:59:14+00:00
cwd=/shared/codebase/clean-architecture-backend-template/src

=== OWNED FILES ===
873cb3db4ee900e7638124c59f6091948fbfd0f6 main/java/dev/caskeleton/adapter/outbound/mongo/transaction/MongoTransactionExecutor.java 23
23a83b409d3e42360e212b7899f04a96ec5dacce main/java/dev/caskeleton/adapter/outbound/mongo/transaction/MongoTransactionProfile.java 77
9ae3e814bfc78daccebc1b0dce2a3ef953f834f8 main/java/dev/caskeleton/adapter/outbound/mongo/transaction/MongoTransactionScope.java 86
1d0b146c9ba9268d8dd7ec8cb6e4c50b4c6bb7f8 main/java/dev/caskeleton/adapter/outbound/mongo/transaction/MongoTransactionSession.java 43
d5937274e6f7ac95abf66459dd5b728e5e5d3316 main/java/dev/caskeleton/adapter/outbound/mongo/transaction/MongoTransactionSessionFactory.java 15
bef7501ef1742d8114f289f1c44ff1f25f209906 main/java/dev/caskeleton/adapter/outbound/mongo/transaction/ReactiveMongoTransactionExecutor.java 31
ffe70abd80b87c2fb0dd2f69e96cff659f34b026 main/java/dev/caskeleton/adapter/outbound/mongo/transaction/ReactiveMongoTransactionSession.java 38
7cb9136000f9746a9bb33e3c4357148498fb1e0e main/java/dev/caskeleton/adapter/outbound/mongo/transaction/ReactiveMongoTransactionSessionFactory.java 16
5f96fa86ea42eab9306cc73f02feccf7f6683e88 main/java/dev/caskeleton/adapter/outbound/mongo/transaction/SpringMongoTransactionExecutor.java 59
92bda406cc21352893e4b9a839eac8163ea153ae main/java/dev/caskeleton/adapter/outbound/mongo/transaction/SpringMongoTransactionSessionFactory.java 263
6d96b51eb94a60f92fe251a9b0452430bc0f3b49 main/java/dev/caskeleton/adapter/outbound/mongo/transaction/SpringReactiveMongoTransactionExecutor.java 175
b6ef0091d7849f646e8949b2cfa3da3c21791a8f main/java/dev/caskeleton/adapter/outbound/mongo/transaction/SpringReactiveMongoTransactionSessionFactory.java 214
dfb46a08cb5d404e721005514cf0f98900da6d8a main/java/dev/caskeleton/adapter/outbound/mongo/transaction/retry/MongoCommitReconciler.java 27
b6df5b2ebf39793d5dc8bf38c222e59069b46b9a main/java/dev/caskeleton/adapter/outbound/mongo/transaction/retry/MongoRetryBudget.java 80
692a21a115dfa0ea183c625bb5653a96025016b5 main/java/dev/caskeleton/adapter/outbound/mongo/transaction/retry/MongoRetryDecision.java 68
028037fa1a84eea4b12018d906d801aac0d2dd85 main/java/dev/caskeleton/adapter/outbound/mongo/transaction/retry/MongoTransactionRetryCoordinator.java 189
774883c35befc8249cfadc1a7ae5de9c45a6fdbb main/java/dev/caskeleton/adapter/outbound/mongo/transaction/session/MongoCausalSessionContext.java 49
8a25a7c246398a8a1bded005280c6d2c6ca6a290 main/java/dev/caskeleton/adapter/outbound/mongo/transaction/session/MongoCausalSessionExecutor.java 16
795c67ae7615f079513485cd5041ed388215b6ca main/java/dev/caskeleton/adapter/outbound/mongo/transaction/session/ReactiveMongoCausalSessionExecutor.java 69
806d3be20120b8e599ea97a967fb342fc9e8fa4e main/java/dev/caskeleton/adapter/outbound/mongo/transaction/session/SpringMongoCausalSessionExecutor.java 79
0e1323f4abb3933a88d1b6c9fb78457feda4c7be test/java/dev/caskeleton/adapter/outbound/mongo/transaction/MongoSessionAcquisitionTest.java 77
30619b8f143dc38c06fa5123f34768823edc58ba test/java/dev/caskeleton/adapter/outbound/mongo/transaction/MongoTransactionProfileTest.java 55
c56553a2d953a98df8d0d7772a9d33a8084903b7 test/java/dev/caskeleton/adapter/outbound/mongo/transaction/MongoTransactionScopeTest.java 76
344c75f520992801a82a926afdb29437a6980fef test/java/dev/caskeleton/adapter/outbound/mongo/transaction/SpringReactiveMongoTransactionExecutorTest.java 236
22d6be5d8e4222d45e01a631887da99bcccc6616 test/java/dev/caskeleton/adapter/outbound/mongo/transaction/retry/CleanupFailureIsReportedTest.java 156
2fde8127fa3874c2a81bb00d2275f645d3d5edaa test/java/dev/caskeleton/adapter/outbound/mongo/transaction/retry/MongoTransactionRetryCoordinatorTest.java 220
f49adb300b1efa68e93e3f07e1e993bac13ca6bf test/java/dev/caskeleton/adapter/outbound/mongo/transaction/session/MongoCausalSessionExecutorTest.java 43

production: 20
test: 7
production LOC:  1617 total

=== 8.1 reachability: transaction beans and cross-package production references ===
$ grep -n 'Transaction\|CausalSession\|RetryCoordinator' adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoPlatformAutoConfiguration.java
exit=1

$ git grep -n 'MongoTransactionExecutor\|MongoTransactionRetryCoordinator\|SpringMongoTransactionSessionFactory\|MongoCausalSessionExecutor\|MongoTransactionScope\|ReactiveMongoTransactionExecutor' -- 'adapter/outbound/persistence-mongo/src/main' | grep -v '/transaction/'
exit=1

=== 8.1b the transactions flag: what it gates and what it does not compose ===
$ grep -n 'transactionsEnabled' adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoStartupValidator.java
32:  private final boolean transactionsEnabled;
43:      boolean transactionsEnabled,
50:    this.transactionsEnabled = transactionsEnabled;
97:    if (transactionsEnabled && !capabilities.isStable(MongoCapability.TRANSACTION)) {
exit=0

$ grep -n 'properties.transactions()' adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoPlatformAutoConfiguration.java
362:              properties.transactions(),
exit=0

$ grep -n 'boolean transactions' adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/autoconfigure/MongoPlatformSettings.java
29:    boolean transactions,
exit=0

=== 8.2 the central rule: body retry and commit retry are separate loops ===
$ grep -n 'catch (MongoTransactionTransientException transientFailure)' -A 6 adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/transaction/retry/MongoTransactionRetryCoordinator.java
87:        } catch (MongoTransactionTransientException transientFailure) {
88-          lastTransient = transientFailure;
89-          decisionRecorder.accept(
90-              MongoRetryDecision.retryBody(budget.delayBefore(attempt + 1, random)));
91-          continue;
92-        }
93-        return commitWithRetry(session, value, startedAt);
exit=0

$ grep -n 'private <T> T commitWithRetry' -A 8 adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/transaction/retry/MongoTransactionRetryCoordinator.java
145:  private <T> T commitWithRetry(MongoTransactionSession session, T value, long startedAt) {
146-    MongoTransactionCommitUnknownException lastUnknown = null;
147-    for (int commitAttempt = 1;
148-        budget.allowsAttempt(commitAttempt, elapsedSince(startedAt));
149-        commitAttempt++) {
150-      sleep(budget.delayBefore(commitAttempt, random));
151-      try {
152-        session.commit();
153-        return value;
exit=0

$ grep -n 'MongoTransactionCommitUnknownException' adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/transaction/SpringReactiveMongoTransactionExecutor.java
4:import dev.caskeleton.adapter.outbound.mongo.api.error.MongoTransactionCommitUnknownException;
130:                failure instanceof MongoTransactionCommitUnknownException
155:            MongoTransactionCommitUnknownException.class,
160:                    new MongoTransactionCommitUnknownException(
exit=0

=== 8.2b why MongoTransactionManager / TransactionTemplate are not used ===
$ grep -n 'Deliberately not built on' -A 3 adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/transaction/SpringMongoTransactionSessionFactory.java
32: * <p>Deliberately not built on {@code MongoTransactionManager} or {@code TransactionTemplate}. Both
33- * commit implicitly when the callback returns, which collapses body and commit into one step — and
34- * the whole design rests on those two steps failing differently and being retried differently.
35- *
exit=0

=== 8.3 scope binding: nested bind restores rather than clears ===
$ grep -n 'Registration bind' -B 8 adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/transaction/MongoTransactionScope.java
46-   * Binds operations for the current thread and returns what undoes it.
47-   *
48-   * <p>Binding used to be {@code set} and unbinding {@code remove}, which is only correct when
49-   * scopes never nest. They do: an outer transaction body that calls a second transactional
50-   * component ran an inner bind, and the inner {@code remove} left the outer body with nothing
51-   * bound — so every subsequent {@code require()} in the outer body failed, and any code that fell
52-   * back to an ordinary template wrote outside the transaction it believed it was in.
53-   */
54:  static Registration bind(MongoOperations operations) {
exit=0

$ grep -n 'ThreadLocal' adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/transaction/MongoTransactionScope.java adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/transaction/session/SpringMongoCausalSessionExecutor.java
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/transaction/MongoTransactionScope.java:20:  private static final ThreadLocal<MongoOperations> CURRENT = new ThreadLocal<>();
adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/transaction/session/SpringMongoCausalSessionExecutor.java:21:  private static final ThreadLocal<MongoOperations> CURRENT = new ThreadLocal<>();
exit=0

=== 8.4 profile bounds ===
$ grep -n 'SERVER_LIFETIME_LIMIT' -A 4 adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/transaction/MongoTransactionProfile.java
23:  public static final Duration SERVER_LIFETIME_LIMIT = Duration.ofSeconds(60);
24-
25-  public MongoTransactionProfile {
26-    Objects.requireNonNull(consistency, "consistency");
27-    Objects.requireNonNull(timeout, "timeout");
--
38:    if (timeout.compareTo(SERVER_LIFETIME_LIMIT) > 0) {
39-      throw new IllegalArgumentException(
40-          "a transaction timeout of "
41-              + timeout
42-              + " exceeds the server's default lifetime limit of "
43:              + SERVER_LIFETIME_LIMIT);
44-    }
45-    if (maxAttempts < 1) {
46-      throw new IllegalArgumentException("maxAttempts must be at least 1");
47-    }
exit=0

$ grep -n 'STALE_READ_ALLOWED\|staleReadsPossible\|readsFromSecondary' adapter/outbound/persistence-mongo/src/main/java/dev/caskeleton/adapter/outbound/mongo/transaction/MongoTransactionProfile.java
12: * transaction's snapshot, and neither is what the caller who wrote {@code STALE_READ_ALLOWED}
29:    if (consistency == MongoConsistencyProfile.STALE_READ_ALLOWED) {
32:              + MongoConsistencyProfile.STALE_READ_ALLOWED
exit=0

