# 두 번째 완료가 비교하는 것 261: if (row.state() == IdempotencyState.COMPLETED 262: && "COMPLETE".equals(row.lastTransitionKind()) 263: && operationId.value().equals(row.lastTransitionOperationId())) { 264: return responseDigest.equals(row.responseDigest()) 265: ? IdempotencyCompleteOutcome.ALREADY_COMPLETED_SAME_RESULT 266: : IdempotencyCompleteOutcome.RESPONSE_CONFLICT; 267: } 268: IdempotencyCompleteOutcome mismatch = classifyCompleteMismatch(row, owner); # 첫 완료가 다이제스트에 넣는 것과 그 이유 주석 274: owner, 275: operationId.value(), 276: // The transition digest, not the response digest. Reusing the response digest here made 277: // two completions of different operations with identical payloads indistinguishable, 278: // and lost the replay window the completion also decided. 279: transitionDigest( 280: "COMPLETE", 281: operationId, 282: owner, 283: responseDigest, 284: Long.toString(replayTtl.toMillis())), 285: response.payload(), # 공용 헬퍼와 그것이 읽는 열 557: private static ReplayVerdict replayVerdict( 558- IdempotencyRecordRow row, 559- String transitionKind, 560- OperationId operationId, 561- String expectedDigest) { 562- if (!transitionKind.equals(row.lastTransitionKind()) 563- || !operationId.value().equals(row.lastTransitionOperationId())) { 564- return ReplayVerdict.NOT_A_REPLAY; 565- } 566- return expectedDigest.equals(row.lastTransitionResultDigest()) 567- ? ReplayVerdict.SAME_ARGUMENTS 568- : ReplayVerdict.DIFFERENT_ARGUMENTS; 569- } 570- 27: String lastTransitionOperationId, 28: String lastTransitionKind, 29: String lastTransitionResultDigest, 58: ADD COLUMN IF NOT EXISTS last_transition_result_digest char(64), # 그 헬퍼를 쓰는 네 전이 182: switch (replayVerdict(row, "START", operationId, startDigest)) { 221: switch (replayVerdict(row, "RENEW", operationId, renewDigest)) { 319: switch (replayVerdict(row, transitionKind, operationId, failDigest)) { 366: switch (replayVerdict(row, "RELEASE", operationId, releaseDigest)) { # complete 본문에서 그것을 부르는 줄: 0 # 값이 다르다는 것은 이미 단위 시험이 고정한다 39: void twoCompletionsWithDifferentReplayWindowsDiffer() { 40- assertThat(IdempotencyDigestPolicy.of("COMPLETE", "op-1", "owner-1", 1, 3, "digest-a", "60000")) 41- .isNotEqualTo( 42- IdempotencyDigestPolicy.of("COMPLETE", "op-1", "owner-1", 1, 3, "digest-a", "90000")); 43- } # 갱신 경로의 주석 216: // The lease TTL is part of what a renewal decided, so it is part of the digest. Without it, a 217: // retry asking for a different lease was confirmed as the renewal already applied, and the 218: // caller went on believing it held the record for longer than the row says it does. # 출하 통합 시험이 덮는 인자 재생 256: void aRetriedFailureWithTheSameArgumentsIsConfirmedRatherThanAppliedTwice() { 281: void aFailureRepeatedUnderOneOperationIdWithDifferentRetentionIsAConflict() { 315: void aRenewalRepeatedUnderOneOperationIdWithADifferentLeaseIsAConflict() { # 그 파일에서 완료를 부르는 곳: 2 # ALREADY_COMPLETED_SAME_RESULT 를 단언하는 곳: 0 # 레디스 구현도 같은 자리에서 멈춘다 231: case "ALREADY" -> 232- // The same owner completing twice. Whether it is the same result decides whether this 233- // is an idempotent repeat or a contradiction the caller has to see. 234- reply.payload().equals(response.payload()) 235- ? IdempotencyCompleteOutcome.ALREADY_COMPLETED_SAME_RESULT 236- : IdempotencyCompleteOutcome.RESPONSE_CONFLICT; -- 291: case "ALREADY" -> IdempotencyFailOutcome.ALREADY_MARKED_SAME_OPERATION; 113: return {'ALREADY', attempt, rev, owner, redis.call('HGET', KEYS[1], 'resp') or '', ''} 130: if ARGV[8] ~= '' then