Files
document-haness/docs/clean-architecture-backend-template/final/evidence/raw/165-cache-redis-semantic-adapters-probes.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

180 lines
14 KiB
Plaintext

Sub-scope 07 (cache-redis) 의미 포트 어댑터 + live/topology test 기반 — manifest and probes
revision=a24ece9cf797f7ea647e33bf846b115208ed1ba5
generatedAt=2026-08-30T04:53:45+00:00
=== OWNED FILES ===
7767ce032226a698227c32afc9919a2f1505a6c9 main/java/dev/caskeleton/adapter/outbound/cache/redis/cache/CacheEnvelope.java 213
ba2e04b43e830b1e0e51a6d3f692b14453e48737 main/java/dev/caskeleton/adapter/outbound/cache/redis/cache/RedisCacheRegionAdapter.java 428
f3e259be5879a2e9779e8bdcdd7e3b8b26ffad66 main/java/dev/caskeleton/adapter/outbound/cache/redis/idempotency/IdempotencyScripts.java 306
7cfb0cd5d9627e6fbbcc8afdb8ff4fd860b2e0b5 main/java/dev/caskeleton/adapter/outbound/cache/redis/idempotency/RedisIdempotencyStoreAdapter.java 529
564bc94df42f434302237319ff5c5ebc251772ba main/java/dev/caskeleton/adapter/outbound/cache/redis/keyspace/CapabilityKeyspace.java 106
e95efcd322b8d0856c917fcbf5e8a87962b24bad main/java/dev/caskeleton/adapter/outbound/cache/redis/lease/LeaseScripts.java 203
e31bc74da675ccf4167175beb2130bc76d4686bc main/java/dev/caskeleton/adapter/outbound/cache/redis/lease/RedisDistributedLeaseAdapter.java 403
7ffbe5e790bf632073e1e74ba925947eca306d63 main/java/dev/caskeleton/adapter/outbound/cache/redis/ratelimit/RateLimitKeys.java 49
dd5d94054767e33f9cf567f12c2c03f4827acd67 main/java/dev/caskeleton/adapter/outbound/cache/redis/ratelimit/RateLimitScripts.java 280
b0721e10cd394ad39325d5240935e836859ffa19 main/java/dev/caskeleton/adapter/outbound/cache/redis/ratelimit/RedisEdgeRateLimitAdapter.java 187
a0975e74004850c1b6a27999230ad3eacee92bb6 main/java/dev/caskeleton/adapter/outbound/cache/redis/realtime/RealtimeKeys.java 81
dfac770123e102a33caa742a6a8a44fe5e67c9b9 main/java/dev/caskeleton/adapter/outbound/cache/redis/realtime/RedisConnectionRegistryAdapter.java 301
ba584a26db38abe135f28b6b34d87ffc9095c489 main/java/dev/caskeleton/adapter/outbound/cache/redis/realtime/RedisEphemeralFanoutAdapter.java 133
81e64fe800007dd0a5065a5a4952ecde8db8214d main/java/dev/caskeleton/adapter/outbound/cache/redis/realtime/RegistrationCodec.java 76
b76c71e2c9eff216c24a9ba87c90c8433928f5c0 test/java/dev/caskeleton/adapter/outbound/cache/redis/cache/RedisCacheRegionAdapterTest.java 333
3d6f81aee563152b098ecf74119178a381b37cea test/java/dev/caskeleton/adapter/outbound/cache/redis/idempotency/RedisIdempotencyStoreAdapterTest.java 337
ad8ef22e2b87d0afcdad7f0c654e7f5d9d7f911d test/java/dev/caskeleton/adapter/outbound/cache/redis/lease/RedisDistributedLeaseAdapterTest.java 292
04fc419bee78a203dee1a6a203a6baf3fd70b07e test/java/dev/caskeleton/adapter/outbound/cache/redis/ratelimit/RedisEdgeRateLimitAdapterTest.java 321
41e39a597eb22e44d44f1ab626cb7ba4e3ca925c test/java/dev/caskeleton/adapter/outbound/cache/redis/realtime/RedisConnectionRegistryAdapterTest.java 262
65fe3f6335d61e97fa4b145bdb4b549f0c26af8e test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/RedisSdkModuleBoundaryTest.java 237
073ebb2de3602c48907e06678529c156c7941fb0 test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/RedisSupportMatrixTest.java 193
5bb26b538cacf05a74c6dfe409f84d63b399b729 test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/RedisTopologyContractTest.java 306
1a04d38388906e8be77963dc6f719428dd90a043 test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/RedisTopologyEndpoint.java 244
2a4c054061162af30a8f4073d61759adde98126d test/java/dev/caskeleton/adapter/outbound/cache/redis/LiveRedisSemanticPortsTest.java 364
main: 14
=== 8.1 의미 어댑터가 guard/executor/타입 API를 지나는가 ===
$ git grep -ln 'SyncRedisCommandExecutor\|ReactiveRedisCommandExecutor\|CommandPolicyGuard\|CommandRequest' -- 'adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/cache' 'adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/idempotency' 'adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/lease' 'adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/ratelimit' 'adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/realtime' 'adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/keyspace'
exit=1
$ git grep -ln 'RedisValueOperations\|RedisHashOperations\|RedisOperations\|RedisKeyOperations' -- 'adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/cache' 'adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/idempotency' 'adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/lease' 'adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/ratelimit' 'adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/realtime' 'adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/keyspace'
exit=1
--- 대신 무엇을 부르는가 ---
$ git grep -c 'gateway()' -- 'adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/cache' 'adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/idempotency' 'adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/lease' 'adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/ratelimit' 'adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/realtime'
adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/cache/RedisCacheRegionAdapter.java:6
adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/idempotency/RedisIdempotencyStoreAdapter.java:6
adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/lease/RedisDistributedLeaseAdapter.java:4
adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/ratelimit/RedisEdgeRateLimitAdapter.java:1
adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/realtime/RedisConnectionRegistryAdapter.java:13
exit=0
$ git grep -h '^import dev.caskeleton.adapter.outbound.cache.redis.sdk' -- 'adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/cache' 'adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/idempotency' 'adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/lease' 'adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/ratelimit' 'adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/realtime' 'adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/keyspace' | sed 's/.*sdk\.//' | sort | uniq -c | sort -rn
6 api.key.RedisNamespace;
5 lettuce.connection.RedisRuntimeOwner;
5 lettuce.connection.RedisLease;
5 lettuce.connection.RedisConnectionKind;
3 lettuce.operations.RedisCommandGateway;
1 lettuce.operations.ScoredMemberPage;
1 lettuce.operations.RedisPubSubGateway;
1 lettuce.operations.MemberScanPage;
1 lettuce.operations.HashScanPage;
1 api.operations.SortedSetAddOptions;
1 api.operations.ScoreRange;
1 api.operations.PageRequest;
1 api.operations.ExpirationCondition;
1 api.key.RedisKeyRules;
1 api.error.RedisOperationException;
exit=0
=== 8.1b gateway가 주장하는 전제 ===
$ sed -n '36,40p' adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/operations/RedisCommandGateway.java
* <p>The seam exists so the typed operations can be proven against a deterministic in-memory server
* without Docker, and so the Lettuce types stay inside {@link LettuceRedisCommandGateway}. Policy,
* permits, budgets, timeouts, and observability are not this interface's concern: everything routed
* through it has already passed {@code CommandPolicyGuard}.
*/
exit=0
$ sed -n '24,26p' adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/command/CommandPolicyGuard.java
/**
* The single admission point every command passes through.
*
exit=0
=== 8.2 두 번째 키 렌더 경로 ===
$ grep -n 'requireRenderedSize\|MAX_KEY_BYTES' adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/keyspace/CapabilityKeyspace.java
exit=1
$ grep -n 'requireRenderedSize' adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/api/key/RedisKeyRenderer.java
45: return RedisKeyRules.requireRenderedSize(rendered.toString(), maxKeyBytes);
exit=0
$ git grep -ln 'CapabilityKeyspace' -- 'adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis'
adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/cache/RedisCacheRegionAdapter.java
adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/idempotency/RedisIdempotencyStoreAdapter.java
adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/keyspace/CapabilityKeyspace.java
adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/lease/RedisDistributedLeaseAdapter.java
adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/ratelimit/RateLimitKeys.java
adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/realtime/RealtimeKeys.java
exit=0
=== 8.3 README 대조: 이 어댑터들이 구현하는 application/shared port ===
$ git grep -h 'implements [A-Za-z<>, ]*Port' -- 'adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/cache' 'adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/idempotency' 'adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/lease' 'adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/ratelimit' 'adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/realtime' | sed 's/^ *//'
public final class RedisCacheRegionAdapter<K, V> implements CacheRegionPort<K, V> {
public final class RedisIdempotencyStoreAdapter implements IdempotencyStorePortV2 {
public final class RedisDistributedLeaseAdapter implements DistributedLeasePort {
public final class RedisEdgeRateLimitAdapter implements EdgeRateLimitPort {
public final class RedisConnectionRegistryAdapter implements ConnectionRegistryPort {
public final class RedisEphemeralFanoutAdapter implements EphemeralFanoutPort {
exit=0
$ sed -n '25,28p;35,37p' adapter/outbound/cache-redis/README.md
| Redis SDK typed API (`…cache.redis.sdk`) | 있음 | settings bind + validate 까지만 | 없음 |
| Topology client / connection lifecycle | 없음 | 없음 | 없음 |
| cache / session / idempotency / rate limit / lease semantic port | 없음 | 없음 | 없음 |
| role-aware health·readiness contributor | 없음 | 없음 | 없음 |
readiness registry에도 `selected` card가 없으므로 Redis R2 release claim은 없다. 아래 절들은
이전 세대 semantic adapter 세트의 설계 결정을 기록한 것이며, 그 코드는 현재 이 leaf에 없다.
복구 범위는 위 plan의 Phase E가 소유한다.
exit=0
=== 8.4 이 어댑터들의 test ===
$ git ls-files 'adapter/outbound/cache-redis/src/test/java/dev/caskeleton/adapter/outbound/cache/redis/cache' 'adapter/outbound/cache-redis/src/test/java/dev/caskeleton/adapter/outbound/cache/redis/idempotency' 'adapter/outbound/cache-redis/src/test/java/dev/caskeleton/adapter/outbound/cache/redis/lease' 'adapter/outbound/cache-redis/src/test/java/dev/caskeleton/adapter/outbound/cache/redis/ratelimit' 'adapter/outbound/cache-redis/src/test/java/dev/caskeleton/adapter/outbound/cache/redis/realtime' | xargs -n1 basename
RedisCacheRegionAdapterTest.java
RedisIdempotencyStoreAdapterTest.java
RedisDistributedLeaseAdapterTest.java
RedisEdgeRateLimitAdapterTest.java
RedisConnectionRegistryAdapterTest.java
exit=0
$ git grep -h ' void [a-z]' -- 'adapter/outbound/cache-redis/src/test/java/dev/caskeleton/adapter/outbound/cache/redis/cache' 'adapter/outbound/cache-redis/src/test/java/dev/caskeleton/adapter/outbound/cache/redis/idempotency' 'adapter/outbound/cache-redis/src/test/java/dev/caskeleton/adapter/outbound/cache/redis/lease' 'adapter/outbound/cache-redis/src/test/java/dev/caskeleton/adapter/outbound/cache/redis/ratelimit' 'adapter/outbound/cache-redis/src/test/java/dev/caskeleton/adapter/outbound/cache/redis/realtime' | sed 's/^ *//' | head -50
void recordThenLookup() {
void staleButUsable() {
void expiredIsAMiss() {
void anAuthoritativeAbsenceIsNotAMiss() {
void aFutureSchemaIsQuarantined() {
void aForeignEntryIsReported() {
void regionInvalidationBumpsTheGeneration() {
void invalidateOneKey() {
void onlyIfAbsentDoesNotOverwrite() {
void onlyIfObservedRefusesAStaleWrite() {
void onlyIfObservedAppliesWhenUnchanged() {
void anUnreachableRedisDegrades() {
void negativeEntriesExpireSooner() {
void aFirstClaimExcludesTheSecond() {
void theSameAttemptReplays() {
void aDifferentRequestIsAMismatch() {
void theHappyPathCompletesAndReplays() {
void aStaleHandleCannotComplete() {
void completingTwiceIsIdempotentOnlyForTheSameResult() {
void aRetryableFailureAllowsAnotherAttempt() {
void anAbandonedOperationRequiresRecovery() {
void releasingBeforeExecutionFreesTheScope() {
void releasingAfterStartIsRefused() {
void anExpiredLeaseIsTakenOver() {
void inspectionRecoversALostReply() {
void anUnreachableRedisIsIndeterminate() {
void anUncontendedAcquireSucceeds() {
void aSecondHolderIsContended() {
void theSameClaimReplays() {
void theSameOwnerDifferentOperationConflicts() {
void aNonHolderCannotRelease() {
void aRenewExtendsOnlyOnConfirmation() {
void anExpiredBudgetIsLost() {
void releasingFreesTheLease() {
void releasingTwiceIsAbsent() {
void inspectingAnAbsentLease() {
void anUnreachableRedisIsIndeterminate() {
void ownerTokensAreUnguessable() {
void aFixedWindowBoundsItsWindow() {
void anewWindowRestoresTheBudget() {
void aSlidingCounterIsHonestAboutBeingApproximate() {
void aTokenBucketRefillsByPeriod() {
void anUnreachableRedisFailsClosed() {
void anUnknownPolicyIsIncompatible() {
void anOversizedCostIsRefused() {
void anExpiredCallerDeadlineIsRejectedImmediately() {
void subjectsAreIsolated() {
void announcedActorIsFound() {
void multipleNodesAreReportedNewestFirst() {
void reAnnounceReplaces() {
exit=0