fix: name the plan the release published, not a second compile of it - #250
Merged
Conversation
INT03 run c0df2755 never started simulating. The worker resolved the request's compiledPlanChecksum against bot.launch_contract_plans, found nothing, and failed with JobNotSatisfiable: compiled plan sha256:f98de8f7... is not resolvable Two different digests were in play. The release stores release.contractPlan().planChecksum() — the assembler's digest over the strategy-bot.v1 document. The request carried CompiledFlowPlan.planHash() from a second planService.compile() call in release(), which is a digest of a different artifact. They have no reason to be equal, so the request named a row that was never written. Storage was correct and the query was correct. The producer told the consumer the wrong name. forRelease no longer accepts the digest. It reads release.contractPlan().planChecksum(), which makes the divergence unrepresentable rather than merely checked, and removes the redundant second compile — prepare() had already compiled and assembled the contract. Two tests were hiding this, which is why it reached a deployment: - ImmutableStrategyReleaseCommandServiceTest required the request to carry planPort.saved.planHash(). The test asserted the defect. It now requires the published contract checksum, plus an assertion that the two digests really differ in that fixture so it cannot pass by coincidence. - ImmutableStrategyReleasePersistenceIntegrationTest built its ContractPlan with "sha256:" + "c".repeat(64) and passed HASH_C — the same value. The stored row and the message agreed by accident. The fixture now uses a digest distinct from every other hash in the file. Full ./gradlew test is green: 12 test tasks, backend-application re-executed with 330 tests and the rest up to date from the previous run. The correlation-ID half of this failure is root-owned and lands in the same release; the backtest-engine hardening is backtest-engine #74 / PR #75. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
INT03 run
c0df2755-01eb-3660-b57e-be20ab73001a은 시뮬레이션을 시작하지도 못했습니다.근본 원인 — 서로 다른 산출물의 해시를 비교하고 있었습니다
ImmutableStrategyReleaseCommandService.release()안에 두 값이 있었습니다.release.contractPlan().planChecksum()StrategyBotCompiledPlanAssembler가 strategy-bot.v1 문서에 대해 계산bot.launch_contract_plans.plan_checksumplan.planHash()release()가 두 번째로 호출한planService.compile()의CompiledFlowPlancompiledPlanChecksum둘은 같을 이유가 없습니다. 소비자(
PostgresCompiledPlanSource)는 메시지의 값으로 정확히 그 테이블을조회하므로, 요청은 저장된 적 없는 행의 이름을 부른 것입니다.
저장도 조회도 정상이었습니다. producer 가 consumer 에게 잘못된 이름을 알려준 것입니다.
고친 방식 — 검사가 아니라 표현 불가능
forRelease에서 해시 인자를 제거하고release.contractPlan().planChecksum()을 읽습니다. 두 값이어긋나는 상태를 만들 방법이 없어집니다. 덤으로 중복 컴파일도 사라집니다 —
prepare()가 이미 컴파일하고계약을 조립합니다.
시험 두 개가 이 결함을 가리고 있었습니다
배포까지 간 이유입니다.
ImmutableStrategyReleaseCommandServiceTest:85가 요청이planPort.saved.planHash()를 실어야한다고 단정했습니다. 시험이 결함을 불변식으로 고정하고 있었습니다. 계약 체크섬을 요구하도록 바꾸고,
그 픽스처에서 두 값이 실제로 다르다는 단정을 추가해 우연히 통과할 수 없게 했습니다.
ImmutableStrategyReleasePersistenceIntegrationTest는ContractPlan을"sha256:" + "c".repeat(64)로 만들고HASH_C(="c"*64)를 넘겼습니다. 같은 값이라 저장 행과메시지가 우연히 일치했습니다. 파일 내 다른 모든 해시와 구분되는 값으로 바꿨습니다.
시험
이 PR 이 담지 않은 것
같은 run 의 2차 장애(correlation ID 가 UUID 가 아니어서 terminal 실패 발행이 계약 위반으로 막힌 것)는
루트 소유입니다 — user-data 가 EC2 instance id 를 UUID 필드에 넣고 있었고, 같은 릴리스에 함께 올립니다.
backtest-engine쪽 방어(발행 실패가 terminal 판정을 뒤집지 않게, correlation ID 를 기동 시 검증)는backtest-engine #74 /
PR #75 입니다.
기존 run 을 대체·재실행하지 않았고, 신규 공개 release/backtest run 을 만들지 않았고, DLQ·워커·ASG·DB 를
건드리지 않았습니다.
🤖 Generated with Claude Code