# 조립된 경로에서 갱신과 원장 기록 사이에 있는 것 // Still refreshed after execute, but the refresh is no longer what protects the run: the // heartbeat inside the context is. This one only proves the lease survived to the end, before // anything is written to the ledger under it. lock.refresh(template.maxTime()); if (!migration.postcondition().isSatisfied(context, result)) { throw MongoOperationRejectedException.of( "migration.postcondition", "migration " + migration.id() ... result.resumePoint().ifPresent(checkpoint -> ledger.saveCheckpoint(checkpoint, lock.fence())); if (result.status() == MongoMigrationResult.Status.COMPLETED && !context.dryRun()) { ledger.recordApplied( migration.id(), migration.checksum(), context.operator(), clock.instant(), lock.fence()); } # 완료를 만드는 팩토리는 체크포인트를 남기지 않는다 /** The migration finished. */ public static MongoMigrationResult completed(long processedCount) { return new MongoMigrationResult(Status.COMPLETED, processedCount, null, ""); } /** The migration made progress and stored a checkpoint to resume from. */ public static MongoMigrationResult incomplete( long processedCount, MongoMigrationCheckpoint checkpoint) { return new MongoMigrationResult( Status.INCOMPLETE, processedCount, Objects.requireNonNull(checkpoint, "checkpoint"), ""); } # 그 갱신이 던지는 것 if (stillOwned != 1) { held = false; throw new IllegalStateException( "the migration lease was lost before it could be refreshed; another runner may have " + "taken it after this one appeared to stall"); } # 같은 인터페이스의 다른 잠금 구현이 같은 상황에 던지는 것 public void refresh(Duration extension) { Objects.requireNonNull(extension, "extension"); if (!held.get()) { throw MongoOperationRejectedException.of( "migration.lock", "the migration lease has been released and cannot be extended"); } extend.accept(extension); # 다른 원장 구현은 펜스 인자를 쓰지 않는다 long fence) { recorded.put( Objects.requireNonNull(migrationId, "migrationId"), new AppliedMigration(migrationId, checksum, operator, appliedAt)); } # recordApplied 를 부르는 시험 전수 MongoMigrationRunnerTest.java:23: ledger.recordApplied( MongoMigrationRunnerTest.java:40: ledger.recordApplied( MongoMigrationLaneTest.java:130: ledger.recordApplied( MongoMigrationLaneTest.java:227: ledger.recordApplied(id, new MongoMigrationChecksum("abc"), "operator", FIXED.instant(), 1L); MongoMigrationLaneTest.java:231: ledger.recordApplied( # 그중 실서버에서 두 번 부르는 시험이 단언하는 것 () -> ledger.recordApplied( id, new MongoMigrationChecksum("abc"), "operator", FIXED.instant(), 1L)) .as("the unique index, not the read-then-write check, is what makes this impossible") .isInstanceOf(RuntimeException.class); # 고유 색인을 만드는 메서드를 부르는 곳 전수 test/java/dev/caskeleton/adapter/outbound/mongo/migration/MongoMigrationLaneTest.java main/java/dev/caskeleton/adapter/outbound/mongo/migration/MongoCollectionMigrationLedger.java