Files
document-haness/docs/clean-architecture-backend-template/final/evidence/raw/a13-f005-retry-after-illegalargumentexception-ambiguous.txt
T
DongHyeonkaandClaude Opus 5 b2963105a8 docs(keycloak-session-store): import the session-storage lab as a new project
The keycloak project ended with four open questions that design could not
settle. A two-VM lab was built to answer them by measurement, and this is
that material: 26 experiments, 125 raw command outputs, 22 browser captures.

Follows the import procedure in README.md.

  source/     the originating repository verbatim — 78 documents, 28 SVGs,
              8 manifests, plus .source-revision recording the commit
  final/      the SSOT
    document.md   729 lines written from the 29 experiment documents, not
                  concatenated: what was predicted, what was measured, and
                  where the measurement itself was wrong
    evidence/raw    125 outputs, flattened to <experiment>__<file> because
                    the originals collided (01-baseline.txt appeared three
                    times) and the audit only globs the top level
    evidence/meta   one per raw file; command and exitCode are null and the
                    README says why rather than inventing them
    evidence/browser  22 captures
    assets/       three diagrams through techviz
    .techviz/     their VizSpecs

A separate project rather than an addition to keycloak: the B-layer answers
that project's four questions, but the A, C and D layers are about cluster
failure, SSO and operations, and one document.md should hold one subject.
The four question records there can point here through 관계.

Recorded rather than papered over: only three of the 28 diagrams were
remade. The repository forbids hand-drawn SVG and forbids titles inside the
canvas; all 28 originals carry both, so converting them is redrawing, not
reformatting. They stay in source/ and the gap is written into the document.

verify-pipeline.py passes. audit-records.py reports no issues.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 22:51:59 +09:00

47 lines
2.9 KiB
Plaintext

# 일곱 어댑터의 submit 이 돌려주는 줄 — 비동기로 감싸는 것은 하나뿐이다
SesNotificationProviderAdapter.java-107- return CompletableFuture.completedFuture(send(submission));
WebPushNotificationProviderAdapter.java-82- return CompletableFuture.completedFuture(send(submission));
SmtpNotificationProviderAdapter.java-82- return CompletableFuture.supplyAsync(() -> send(submission), executor);
TwilioSmsProviderAdapter.java-78- return CompletableFuture.completedFuture(send(submission));
FcmNotificationProviderAdapter.java-65- return coordinator.submit(List.of(submission)).thenApply(results -> results.get(0));
ApnsNotificationProviderAdapter.java-76- return CompletableFuture.completedFuture(send(submission));
WebhookNotificationProviderAdapter.java-109- return CompletableFuture.completedFuture(send(submission));
# 게이트웨이가 던지는 자리와 잡는 자리
47: runtime.adapter().submit(submission).toCompletableFuture().join();
48: applyHealth(runtime, result);
50: } catch (CompletionException failure) {
# 배차 서비스가 잡는 세 종류 — 인자 예외는 마지막에만 걸린다
221: dev.caskeleton.application.notification.platform.provider.ProviderCallNotStartedException
227: dev.caskeleton.application.notification.platform.api.error.NotificationException
243: } catch (RuntimeException transportFailure) {
# 그 마지막 가지가 만드는 값
241: ProviderExecutionEvidence.responseLost(),
248: NotificationFailureCode.PROVIDER_RESPONSE_LOST,
249: FailureCategory.AMBIGUOUS_SUBMISSION,
251: ProviderExecutionEvidence.responseLost(),
# dispatch 한 회차의 순서 — 라우팅은 제출보다 앞이다
121: RoutingDecision decision = routing.next(routingContext(work, now));
124: releaseLease(lease);
141: releaseLease(lease);
169: submitOutsideTransaction(attempt, profile, contactPoint, content, work);
175: RetryDecision next = retryPolicy.decide(retryContext(work, recorded, result, profile));
176: applyNextAction(work, recorded, next, clock.instant(), lease);
# 중지가 남기는 상태
435: case RetryDecision.Stop ignored ->
436- recipients.transitionHeldBy(
437- work.recipient().id(),
438- attempt.submissionOutcome() == SubmissionOutcome.CONFIRMED_ACCEPTED
439- ? RecipientDeliveryState.COMPLETED
440- : RecipientDeliveryState.FAILED,
441- Optional.empty(),
# 다음 회차가 청구하는 상태
JdbcNotificationServingState.java:37: WHERE delivery_state IN ('PENDING', 'READY_TO_DISPATCH', 'RETRY_WAITING')
RecipientClaimSql.java:30: + " AND delivery_state IN ('PENDING', 'READY_TO_DISPATCH', 'RETRY_WAITING')"
RecipientClaimSql.java:60: + " WHERE delivery_state IN ('PENDING', 'READY_TO_DISPATCH', 'RETRY_WAITING')"