Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions .ai/issues/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# ResiCache Open Issue Ledger

Last synchronized: 2026-07-26
Repository baseline: `origin/main` @ `75ed279a71b17f227c3170d738eb93e50d876c8a`; local `main` at the current Ledger commit (ahead 4, behind 0)
GitHub repository: `DavidHLP/ResiCache`

## Execution order

| Order | Issue | Priority | Status | Dependency / triage |
|---:|---|---|---|---|
| 1 | [#4](issue-4.md) Per-handler Micrometer tags | P0 observability | COMMITTED | Independent and explicitly highest priority |
| 2 | [#2](issue-2.md) Redis Cluster slot IT | P1 correctness | COMMITTED | Validates existing production key construction; must use real Cluster |
| 3 | [#5](issue-5.md) Serialization migration CLI | P1 compatibility | COMMITTED | Large migration capability; pre-flight probe already exists |
| 4 | [#3](issue-3.md) JMH module | P1 performance | BLOCKED_EXTERNAL_WORK | External contributor declared intent on 2026-07-21 but no PR/branch is linked; review after higher-priority work and re-sync before takeover |

## Live GitHub facts

- Open Issues: `#2`, `#3`, `#4`, `#5`.
- Open PRs: none.
- Linked closing PRs: none for all four issues.
- Assignees: none for all four issues.
- Only active external signal: `Shubh2-0` volunteered for #3 on 2026-07-21; final re-sync still shows no implementation, but the claim remains recent and active.
- #2/#4/#5 are resolved and committed locally; GitHub remains Open because remote writes require explicit approval.

## Final repository validation

- `PATH=/tmp/resicache-tools:$PATH ./mvnw clean verify -B`: `BUILD SUCCESS`; Maven summary 873 unit tests + 18 integration tests, all 0 failures/errors/skips.
- Real standalone Redis containers started through a temporary user-space `socat`; real three-master Cluster tests reported `cluster_state:ok`.
- JaCoCo: line 87.82%, branch 75.33%.
- `testcontainers-bom:1.20.4` override preserved.
- Temporary `socat` was extracted under `/tmp/resicache-tools`; not installed system-wide and not committed.

## Validation gates

- Preserve `testcontainers-bom:1.20.4`; Spring Boot 4.0.0's transitive 1.20.6/docker-java path is incompatible with the target older Docker daemon.
- Real-Redis acceptance requires all three signals: container startup evidence, target test count > 0, and skipped count = 0.
- Every implementation receives Standards + Spec independent review before its focused commit.
- GitHub remote writes remain subject to the session GitHub Write Gate and require an explicit review package and approval.
72 changes: 72 additions & 0 deletions .ai/issues/issue-2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Issue #2 — Real Redis Cluster slot co-location integration test

- **Issue:** https://github.com/DavidHLP/ResiCache/issues/2
- **Status:** COMMITTED
- **Priority:** P1 correctness
- **Dependencies:** none; production implementation appears present and needs real-topology proof
- **External work:** no assignee, comments, branch, or linked PR

## Current findings

- `DistributedLockManager#buildLockKey` already distinguishes cluster mode and preserves or creates a hash tag.
- Unit tests already cover no-tag wrapping, existing-tag preservation, and slot equality by key construction.
- Existing `DistributedLockIntegrationTest` uses standalone Redis, so the Issue's real Cluster acceptance is not yet proved.
- Testcontainers dependency must remain pinned to `1.20.4`; target test execution and zero skips must be checked explicitly.

## Acceptance criteria

1. A real `redis:7` Cluster topology starts under Testcontainers.
2. A sync-enabled cache PUT/get-loader path obtains a Redisson distributed lock.
3. Cache key and lock key report the same `CLUSTER KEYSLOT` and map to the same node.
4. The real operation completes without `CROSSSLOT`.
5. Test report confirms target test count > 0 and skipped = 0.

## Implementation plan

- Add an isolated `AbstractRedisClusterIntegrationTest` rather than destabilizing all standalone Redis ITs.
- Reuse production `DistributedLockManager`/cache path; do not duplicate slot logic in the test.
- Add one focused Cluster integration class and only the minimum fixture configuration required.
- Update cluster limitation/docs only after the proof passes.

## Files/modules involved

- `src/main/java/.../protection/breakdown/DistributedLockManager.java` (expected read-only)
- `src/test/java/.../integration/AbstractRedisClusterIntegrationTest.java`
- `src/test/java/.../integration/*Cluster*IntegrationTest.java`
- Redis compatibility/cache lifecycle wiki or docs identified during investigation

## Tests required

- Existing `DistributedLockManagerTest`.
- New real Cluster IT with container-start and no-skip evidence.
- Full integration regression.

## Validation result

- Real `redis:7-alpine` container started and formed a three-master Cluster (`cluster_state:ok`).
- `RedisClusterSlotIntegrationTest`: 1 test, 0 failures, 0 errors, 0 skipped; `BUILD SUCCESS`.
- Production annotation path acquired a live Redisson lock; test read its actual Redis key, compared both server-side `CLUSTER KEYSLOT` values, and executed a same-slot two-key command without `CROSSSLOT`.
- Target test also proved the cache value was written after lock release.
- `DistributedLockManagerTest` + Cluster IT: 26 tests, 0 failures, 0 errors, 0 skipped; `BUILD SUCCESS`.
- Checkstyle: 0 violations; `git diff --check`: clean.
- The unchanged standalone `DistributedLockIntegrationTest` cannot start its pre-existing WSL2 fixture because this workstation lacks `socat`; rerunning it alone reproduces the same `Cannot start socat` before test execution. The new Cluster fixture does not depend on or weaken that asset.
- Review and commit completed; full repository regression passed.

## Review findings

Independent reviewer jobs again failed to yield within the bounded review window and were cancelled; the maintainer process completed the frozen Standards + Spec review directly.

- **critical/high/medium:** none.
- Topology validity: three Redis server processes form a real Cluster with node IDs and complete slot ownership; teardown requires `cluster_state:ok`.
- Acceptance proof: the test observes a live production Redisson lock key, asks Redis for both `CLUSTER KEYSLOT` values, and executes a dual-key `EXISTS`; a slot mismatch would produce `CROSSSLOT` before key existence is evaluated.
- Lifecycle/concurrency: loader release is in `finally`, preventing an assertion failure from leaving the async loader blocked.
- Compatibility: `TestRedisConfiguration` keeps its original single-server branch and selects Cluster only when `resi-cache.redis.mode=cluster`; production code is unchanged.
- Documentation matches the exact topology and server-side assertions.

## Commit / PR

Local Issue commit: `test(redis): prove cluster lock slot co-location`. Remote PR/Issue closure requires GitHub Write Gate approval.

## Remaining work

Include #2 in the final remote-write review package.
62 changes: 62 additions & 0 deletions .ai/issues/issue-3.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Issue #3 — Minimal JMH module and measured performance baseline

- **Issue:** https://github.com/DavidHLP/ResiCache/issues/3
- **Status:** BLOCKED_EXTERNAL_WORK
- **Priority:** P1 performance
- **Dependencies:** process after correctness/compatibility prerequisites and re-sync external work
- **External work:** `Shubh2-0` volunteered on 2026-07-21; no assignee, branch, linked PR, or submitted diff exists as of 2026-07-26

## Current findings

- Repository is currently a single Maven module and has no JMH dependency/profile/module.
- Issue explicitly requests a new `resicache-bench` module, three benchmark suites, and measured `PERFORMANCE.md` values.
- An intent-only comment is recent enough to re-check before takeover, but there is no code to review now.

## Acceptance criteria

1. A real JMH module/harness is discoverable and runnable independently of normal unit tests.
2. Benchmarks cover: chain pass-through vs Spring-native `@Cacheable`, per-handler additive cost, and SyncLock throughput under concurrency.
3. Fixture/bootstrap cost is outside measured operations.
4. Warmup, measurement, forks, JVM, hardware, and parameters are documented.
5. `PERFORMANCE.md` contains actual measured results and no guessed SLO.
6. Standard `./mvnw clean verify -B` remains deterministic and does not run long benchmarks.

## Implementation plan

- Re-sync Issue/PR state immediately before work.
- If still no PR, choose the smallest Maven multi-module conversion that preserves publishing and coverage behavior.
- Implement three JMH suites against production paths and a short smoke/discovery command.
- Run a baseline on the current workstation and document results as environment-specific, not universal promises.

## Files/modules involved

- root `pom.xml`
- potential core child `pom.xml` only if required by multi-module structure
- `resicache-bench/pom.xml`
- `resicache-bench/src/main/java/**` or canonical JMH source layout
- `PERFORMANCE.md`
- `wiki/modules/observability.md`

## Tests required

- Benchmark jar/list discoverability.
- One short JMH smoke for each suite.
- Normal full verify proving benchmark isolation.

## Validation result

- Re-synced after completing #2/#4/#5: no Open PR, linked PR, assignee, remote benchmark branch, or submitted diff.
- `Shubh2-0`'s explicit implementation claim from 2026-07-21 remains the latest activity (five days old), so duplicate implementation is not currently legitimate.
- Full `./mvnw clean verify -B` passes without a JMH module: 873 unit + 18 integration tests, 0 failures/errors/skips. This validates current repository health, not Issue #3 acceptance.

## Review findings

No implementation exists to review. The claimed plan names the required JMH annotation processor, three suites, thread groups, and `PERFORMANCE.md`, matching the Issue direction. Actual benchmark validity remains unverified until a PR exists.

## Commit / PR

Local ledger commit: `docs(issues): record benchmark contributor status`. No GitHub write performed.

## Remaining work

External dependency: wait for `Shubh2-0` to submit or explicitly relinquish the work. Resume by re-reading #3 and Open PRs/remote branches; if the claim becomes stale or abandoned, implement the frozen plan and measure real baselines. A maintainer GitHub comment requesting ETA would be appropriate, but it requires remote-write approval.
73 changes: 73 additions & 0 deletions .ai/issues/issue-4.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Issue #4 — Per-handler Micrometer tags on `resicache.chain.execute`

- **Issue:** https://github.com/DavidHLP/ResiCache/issues/4
- **Status:** COMMITTED
- **Priority:** P0 observability
- **Dependencies:** none
- **External work:** no assignee, comments, branch, or linked PR

## Current findings

- Current implementation moved the old inline timer from `CacheHandlerChain` into `ChainTimerChainObserver`.
- `ChainTimerChainObserver` creates one tag-less, lazily cached `Timer`; its scope token contains only chain start nanos.
- `ChainObserver#afterNode` already receives both the concrete `CacheHandler` and its `HandlerResult`, so it is the natural per-handler/per-decision observation point.
- Current timer description promises full-chain lifecycle timing. The Issue asks for handler + decision tags; implementation must avoid falsely assigning the same whole-chain duration to every handler.
- Existing `resicache.handler.fired` already counts handler evaluation and must not be duplicated.

## Acceptance criteria

1. `resicache.chain.execute` is queryable by bounded `handler`, `decision`, and `cacheName` tags.
2. `handler` comes from the finite installed handler set; `decision` is one of `CONTINUE`, `SKIP_ALL`, `TERMINATE`.
3. No `redisKey`, user input, exception text, or dynamic ID is used as a tag.
4. Each timer sample measures the corresponding handler invocation, not an incorrectly duplicated whole-chain duration.
5. Registry absence remains a no-op and concurrent calls do not share mutable per-call timing state.
6. Existing fired counter semantics remain unchanged.
7. Wiki observability documentation matches the final metric semantics.

## Implementation plan

- Refine `ChainTimerChainObserver` to record per-node timing using observer scope that remains per call / per thread-safe invocation.
- Use Micrometer registration keyed by bounded tag tuple, not one global cached timer.
- Expand `ChainObserverTest.TimerTests` with decisions, cache names, changing redis keys, and meter-count/cardinality assertions.
- Update `wiki/modules/observability.md` source references and metric table.

## Files/modules involved

- `src/main/java/io/github/davidhlp/spring/cache/redis/chain/observer/ChainTimerChainObserver.java`
- `src/main/java/io/github/davidhlp/spring/cache/redis/chain/ChainEngine.java` (read-only unless observer contract cannot express timing)
- `src/test/java/io/github/davidhlp/spring/cache/redis/chain/observer/ChainObserverTest.java`
- `wiki/modules/observability.md`

## Tests required

- Targeted unit tests for all three decisions and multiple handlers/cache names.
- Cardinality test varying only `redisKey` and asserting meter count remains constant.
- Null-registry no-op.
- `./mvnw -B -Dtest=ChainObserverTest,CacheHandlerChainFactoryTest test`
- `./mvnw -B checkstyle:check`

## Validation result

- Java runtime: Temurin/OpenJDK `21.0.2+13` installed user-locally via `vfox` because the session default was Java 17 and system Java 25 broke current Lombok processing.
- `./mvnw -B -Dtest=ChainObserverTest,ChainEngineTest,CacheHandlerChainFactoryTest test`: `BUILD SUCCESS`; 43 tests, 0 failures, 0 errors, 0 skipped.
- `./mvnw -B checkstyle:check`: `BUILD SUCCESS`; 0 violations.
- `git diff --check`: clean.

## Review findings

Independent reviewer jobs failed to yield within the review window and were cancelled; the maintainer process then completed the same frozen Standards + Spec checklist directly against the full diff and all callers/tests.

- **critical/high/medium:** none.
- **low:** none requiring code changes.
- Concurrency/resource verdict: per-node state is an immutable token paired by Engine `finally`; no shared mutable `ThreadLocal` or stale stack.
- Compatibility verdict: existing `beforeNode/afterNode` exception behavior and `resicache.handler.fired` semantics are unchanged; new observer methods are default no-op.
- Cardinality verdict: only `handler`, three-value `decision`, and configured `cacheName`; varying `redisKey` is explicitly tested not to create meters.
- Semantic verdict: each sample is one handler invocation, so `handler` and `decision` describe the measured duration rather than duplicating whole-chain duration under every handler.

## Commit / PR

Local commit: current Issue commit (`fix(observability): add bounded chain timer dimensions`). Remote PR/Issue closure requires GitHub Write Gate approval.

## Remaining work

Prepare the remote-write review package after all executable Issues are locally complete.
Loading
Loading