Commit 9eac975
feat(infra): implement real idempotency storage and replay for S10/S11/S13 (STA-72) (#185)
* feat(infra): implement real idempotency storage and replay for S10/S11/S13 (STA-72)
Replace validation-only IdempotencyKeyFilter in api-gateway-iam (S10),
merchant-onboarding (S11), and merchant-iam (S13) with full idempotency
implementation that persists key + SHA-256 request hash + response body,
replays cached responses on duplicate requests, and returns 422 on
hash mismatches.
Changes per service:
- Flyway migration to create {prefix}_idempotency_keys table
- IdempotencyKeyFilter rewritten with JdbcTemplate persistence,
CachedBodyRequestWrapper for body re-reading, and
ContentCachingResponseWrapper for response capture
- IdempotencyCleanupJob for hourly expired key cleanup
- application.yml additions for TTL and cleanup config
- 5 unit tests (IdempotencyKeyFilterTest)
- 4 integration tests (IdempotencyKeyFilterIT)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(infra): address PR review — scoped PK, TOCTOU race fix, batched cleanup (STA-72)
- Add request_method + request_path to composite PK for endpoint-scoped idempotency
- INSERT-first reservation pattern to prevent TOCTOU race on concurrent duplicates
- Filter expired keys at read time (AND expires_at > NOW())
- Batched DELETE in cleanup jobs to avoid lock spikes
- Remove raw idempotency keys from log messages
- Add missing table cleanup in S13 IT @beforeeach
- Add 409 Conflict response for in-flight duplicate requests
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(infra): add JVM shutdown hooks to stop Testcontainers after test execution
Testcontainers started in static initializers were never stopped, causing
orphaned PostgreSQL, Kafka, Redis, and Mailpit containers to accumulate
after each test run (~30-50 containers, 5-15 GB leaked memory).
Add Runtime.getRuntime().addShutdownHook() to all 10 AbstractIntegrationTest
classes to ensure containers are stopped when the JVM exits.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(infra): address CodeRabbit review — only persist 2xx, exception safety, expired reclaim (STA-72)
- Only persist idempotency records for 2xx responses; delete reservation
for non-2xx so failed requests can be retried
- Wrap chain.doFilter in try-catch to clean up reservation on exception,
preventing orphaned in-flight rows that block retries until TTL expires
- Reclaim expired rows on INSERT conflict: if cleanup hasn't run and an
expired row blocks the INSERT, delete it and retry once
- Add PUT method unit test to all 3 services
- Strengthen ProceedAndPersist test assertion to verify no error codes
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>1 parent d4a8289 commit 9eac975
26 files changed
Lines changed: 2020 additions & 36 deletions
File tree
- api-gateway-iam/api-gateway-iam/src
- integration-test/java/com/stablecoin/payments/gateway/iam
- application/config
- main
- java/com/stablecoin/payments/gateway/iam/application
- config
- job
- resources
- db/migration
- test/java/com/stablecoin/payments/gateway/iam/application/config
- merchant-iam/merchant-iam/src
- integration-test
- java/com/stablecoin/payments/merchant/iam
- application/config
- resources
- main
- java/com/stablecoin/payments/merchant/iam/application
- config
- job
- resources
- db/migration
- test/java/com/stablecoin/payments/merchant/iam/application/config
- merchant-onboarding/merchant-onboarding/src
- integration-test
- java/com/stablecoin/payments/merchant/onboarding/application/config
- resources
- main
- java/com/stablecoin/payments/merchant/onboarding/application
- config
- job
- resources
- db/migration
- test/java/com/stablecoin/payments/merchant/onboarding/application/config
Lines changed: 1 addition & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
55 | 55 | | |
56 | 56 | | |
57 | 57 | | |
| 58 | + | |
58 | 59 | | |
59 | 60 | | |
60 | 61 | | |
| |||
Lines changed: 143 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
0 commit comments