# 야간 워크플로가 이 레인에 대해 적는 것
  jpa-nightly.yml:122       - name: Verify pool saturation and REQUIRES_NEW connection behaviour
  jpa-nightly.yml:123         working-directory: src
  jpa-nightly.yml:124         # A behaviour contract, not a measurement. This step used to switch assertions off with an
  jpa-nightly.yml:125         # explicit property and call the result a certification, so the only threshold it ever
  jpa-nightly.yml:126         # asserted was that thresholds were not being asserted. What
  jpa-nightly.yml:127         # it checks now — that REQUIRES_NEW needs two connections per concurrent thread, that a
  jpa-nightly.yml:128         # saturated pool reports its pending count, that a caller waits rather than proceeding
  jpa-nightly.yml:129         # without a connection — is true on any runner, so there is nothing to switch off.
  jpa-nightly.yml:130         run: >-
  jpa-nightly.yml:131           ./gradlew
  jpa-nightly.yml:132           :adapter:outbound:persistence-jpa:jpaPlatformPoolContractTest
  jpa-nightly.yml:133           --no-daemon
  jpa-nightly.yml:134           --stacktrace

# 그 레인이 도는 소스 세트와 그 안의 시험 파일
  persistence-jpa/build.gradle:281 // What the lane genuinely verifies is a behaviour contract: a REQUIRES_NEW depth of one needs two
  persistence-jpa/build.gradle:282 // connections per concurrent thread, a saturated pool reports its pending count, and a caller waits
  persistence-jpa/build.gradle:283 // rather than proceeding without a connection. Those are true on any machine, so they need no flag
  persistence-jpa/build.gradle:284 // — and this name does not promise a number nobody measured. A real performance gate needs a
  persistence-jpa/build.gradle:285 // dedicated runner, warmup and sample counts, and recorded thresholds; when that exists it belongs
  persistence-jpa/build.gradle:286 // in a lane of its own rather than behind a boolean on this one.
  persistence-jpa/build.gradle:287 def jpaPlatformPoolContractTest = tasks.register('jpaPlatformPoolContractTest', Test) {
  persistence-jpa/build.gradle:288     group = 'verification'
  persistence-jpa/build.gradle:289     description = 'Verifies Hikari pool and REQUIRES_NEW connection behaviour (design §38).'
  persistence-jpa/build.gradle:290     testClassesDirs = sourceSets.jpaPlatformPerformanceTest.output.classesDirs
  persistence-jpa/build.gradle:291     classpath = sourceSets.jpaPlatformPerformanceTest.runtimeClasspath
  persistence-jpa/build.gradle:292     useJUnitPlatform()
  persistence-jpa/build.gradle:293     failOnNoDiscoveredTests = true
  persistence-jpa/build.gradle:294     outputs.upToDateWhen { false }
  persistence-jpa/build.gradle:295     jvmArgs('-Duser.timezone=UTC')
  persistence-jpa/build.gradle:296 }
  persistence-jpa/build.gradle:297 
  persistence-jpa/build.gradle:298 // The JPA release gate (design §41). Aggregates every lane whose absence would let one of the
  persistence-jpa/build.gradle:299 // documented gates in docs/jpa/support-matrix.md pass unverified.
  persistence-jpa/build.gradle:300 tasks.register('jpaPlatformReleaseGate') {
  persistence-jpa/build.gradle:301     group = 'verification'
  persistence-jpa/build.gradle:302     description = 'Runs every JPA platform lane required for a release (design §41).'
  persistence-jpa/build.gradle:303     dependsOn tasks.named('test')
  persistence-jpa/build.gradle:304     dependsOn jpaPlatformContractTest
  persistence-jpa/build.gradle:305     dependsOn jpaPlatformMigrationTest
  persistence-jpa/build.gradle:306     dependsOn jpaPlatformFailureTest
  persistence-jpa/build.gradle:307     dependsOn jpaPlatformQueryPlanTest
  persistence-jpa/build.gradle:308     dependsOn jpaPlatformSecurityTest
  persistence-jpa/build.gradle:309     dependsOn jpaPlatformPoolContractTest
  persistence-jpa/build.gradle:310 }
  HikariPoolSaturationContractTest.java
  PoolPressureContractTest.java
  RequiresNewPoolPressureContractTest.java

# 세 시험 파일의 시험과 단언 전수
  --- HikariPoolSaturationContractTest.java
    :3  import static org.assertj.core.api.Assertions.assertThat;
    :4  import static org.assertj.core.api.Assertions.assertThatThrownBy;
    :52  void saturatedPoolFailsWithinItsTimeout() throws SQLException {
    :61  assertThatThrownBy(pool::getConnection).isInstanceOf(SQLException.class);
    :64  assertThat(waited)
    :77  void releasingAConnectionLetsTheNextCallerThrough() throws SQLException {
    :84  assertThat(third.isValid(1)).isTrue();
    :92  void measurementReportsPoolState() throws SQLException {
    :97  new PoolMeasurement(
    :100  bean.getThreadsAwaitingConnection(),
    :103  assertThat(measurement.active()).isEqualTo(1);
    :104  assertThat(measurement.total()).isGreaterThanOrEqualTo(1);
    :105  assertThat(held.isValid(1)).isTrue();
  --- PoolPressureContractTest.java
    :3  import static org.assertj.core.api.Assertions.assertThat;
    :28  void reportsPendingAndAcquireLatencyTogether() {
    :29  var measurement = new PoolMeasurement(4, 2, 3, Duration.ofMillis(80));
    :31  assertThat(measurement.pending()).isEqualTo(3);
    :32  assertThat(measurement.acquireLatency()).isEqualTo(Duration.ofMillis(80));
    :33  assertThat(measurement.total()).isEqualTo(6);
    :34  assertThat(measurement.saturated()).isTrue();
    :39  void requiresNewNeedsTwoConnectionsPerThread() {
    :45  assertThat(required)
  --- RequiresNewPoolPressureContractTest.java
    :3  import static org.assertj.core.api.Assertions.assertThat;
    :4  import static org.assertj.core.api.Assertions.assertThatThrownBy;
    :45  void poolOfOneCannotServeAnInnerTransaction() throws SQLException {
    :50  assertThatThrownBy(pool::getConnection)
    :61  void poolOfTwoServesTheSameNesting() throws SQLException {
    :68  assertThat(inner.isValid(1)).isTrue();
    :69  assertThat(inner).isNotSameAs(outer);
    :80  void sizingRuleMatchesTheObservedRequirement() {
    :86  assertThat(required)

# 대기 수를 단언하는 자리
  measurement.pending() 를 단언하는 줄 : 1 개
  그 줄이 있는 시험의 입력 :
  PoolPressureContractTest.java:26   @Test
  PoolPressureContractTest.java:27   @DisplayName("pending count and acquire latency are reported together")
  PoolPressureContractTest.java:28   void reportsPendingAndAcquireLatencyTogether() {
  PoolPressureContractTest.java:29     var measurement = new PoolMeasurement(4, 2, 3, Duration.ofMillis(80));
  PoolPressureContractTest.java:30 
  PoolPressureContractTest.java:31     assertThat(measurement.pending()).isEqualTo(3);
  PoolPressureContractTest.java:32     assertThat(measurement.acquireLatency()).isEqualTo(Duration.ofMillis(80));
  PoolPressureContractTest.java:33     assertThat(measurement.total()).isEqualTo(6);
  PoolPressureContractTest.java:34     assertThat(measurement.saturated()).isTrue();
  PoolPressureContractTest.java:35   }
  PoolPressureContractTest.java:36 
  PoolPressureContractTest.java:37   @Test
  PoolPressureContractTest.java:38   @DisplayName("a REQUIRES_NEW depth of one needs two connections per concurrent thread")
  PoolPressureContractTest.java:39   void requiresNewNeedsTwoConnectionsPerThread() {
  PoolPressureContractTest.java:40     int concurrentThreads = 8;
  PoolPressureContractTest.java:41     int maxRequiresNewDepth = 1;
  PoolPressureContractTest.java:42 
  PoolPressureContractTest.java:43     int required = concurrentThreads * (1 + maxRequiresNewDepth) + 1;
  PoolPressureContractTest.java:44 
  PoolPressureContractTest.java:45     assertThat(required)
  PoolPressureContractTest.java:46         .as("this is a property of REQUIRES_NEW, not of the machine, so it needs no opt-in")
  PoolPressureContractTest.java:47         .isEqualTo(17);
  포화를 다루는 세 시험 전문 :
  HikariPoolSaturationContractTest.java:30 class HikariPoolSaturationContractTest {
  HikariPoolSaturationContractTest.java:31 
  HikariPoolSaturationContractTest.java:32   private static final int POOL_SIZE = 2;
  HikariPoolSaturationContractTest.java:33   private static final Duration ACQUIRE_TIMEOUT = Duration.ofMillis(500);
  HikariPoolSaturationContractTest.java:34 
  HikariPoolSaturationContractTest.java:50   @Test
  HikariPoolSaturationContractTest.java:51   @DisplayName("a saturated pool fails within its acquisition timeout")
  HikariPoolSaturationContractTest.java:52   void saturatedPoolFailsWithinItsTimeout() throws SQLException {
  HikariPoolSaturationContractTest.java:53     try (HikariDataSource pool = pool()) {
  HikariPoolSaturationContractTest.java:54       List<Connection> held = new ArrayList<>();
  HikariPoolSaturationContractTest.java:55       try {
  HikariPoolSaturationContractTest.java:56         for (int index = 0; index < POOL_SIZE; index++) {
  HikariPoolSaturationContractTest.java:57           held.add(pool.getConnection());
  HikariPoolSaturationContractTest.java:58         }
  HikariPoolSaturationContractTest.java:59 
  HikariPoolSaturationContractTest.java:60         Instant startedAt = Instant.now();
  HikariPoolSaturationContractTest.java:61         assertThatThrownBy(pool::getConnection).isInstanceOf(SQLException.class);
  HikariPoolSaturationContractTest.java:62         Duration waited = Duration.between(startedAt, Instant.now());
  HikariPoolSaturationContractTest.java:63 
  HikariPoolSaturationContractTest.java:64         assertThat(waited)
  HikariPoolSaturationContractTest.java:65             .as("an unbounded wait turns exhaustion into requests that never return")
  HikariPoolSaturationContractTest.java:66             .isLessThan(ACQUIRE_TIMEOUT.plusSeconds(2));
  HikariPoolSaturationContractTest.java:67       } finally {
  HikariPoolSaturationContractTest.java:68         for (Connection connection : held) {
  HikariPoolSaturationContractTest.java:69           connection.close();
  HikariPoolSaturationContractTest.java:70         }
  HikariPoolSaturationContractTest.java:71       }
  HikariPoolSaturationContractTest.java:72     }
  HikariPoolSaturationContractTest.java:73   }
  HikariPoolSaturationContractTest.java:74 
  HikariPoolSaturationContractTest.java:75   @Test
  HikariPoolSaturationContractTest.java:76   @DisplayName("releasing a connection lets the next caller through")
  HikariPoolSaturationContractTest.java:77   void releasingAConnectionLetsTheNextCallerThrough() throws SQLException {
  HikariPoolSaturationContractTest.java:78     try (HikariDataSource pool = pool()) {
  HikariPoolSaturationContractTest.java:79       Connection first = pool.getConnection();
  HikariPoolSaturationContractTest.java:80       Connection second = pool.getConnection();
  HikariPoolSaturationContractTest.java:81       first.close();
  HikariPoolSaturationContractTest.java:82 
  HikariPoolSaturationContractTest.java:83       try (Connection third = pool.getConnection()) {
  HikariPoolSaturationContractTest.java:84         assertThat(third.isValid(1)).isTrue();
  HikariPoolSaturationContractTest.java:85       }
  HikariPoolSaturationContractTest.java:86       second.close();
  HikariPoolSaturationContractTest.java:87     }
  HikariPoolSaturationContractTest.java:88   }
  HikariPoolSaturationContractTest.java:89 
  HikariPoolSaturationContractTest.java:90   @Test
  HikariPoolSaturationContractTest.java:91   @DisplayName("the measurement reports what the pool is actually doing")
  HikariPoolSaturationContractTest.java:92   void measurementReportsPoolState() throws SQLException {
  HikariPoolSaturationContractTest.java:93     try (HikariDataSource pool = pool()) {
  HikariPoolSaturationContractTest.java:94       try (Connection held = pool.getConnection()) {
  HikariPoolSaturationContractTest.java:95         var bean = pool.getHikariPoolMXBean();
  HikariPoolSaturationContractTest.java:96         var measurement =
  HikariPoolSaturationContractTest.java:97             new PoolMeasurement(
  HikariPoolSaturationContractTest.java:98                 bean.getActiveConnections(),
  HikariPoolSaturationContractTest.java:99                 bean.getIdleConnections(),
  HikariPoolSaturationContractTest.java:100                 bean.getThreadsAwaitingConnection(),
  HikariPoolSaturationContractTest.java:101                 Duration.ZERO);
  HikariPoolSaturationContractTest.java:102 
  HikariPoolSaturationContractTest.java:103         assertThat(measurement.active()).isEqualTo(1);
  HikariPoolSaturationContractTest.java:104         assertThat(measurement.total()).isGreaterThanOrEqualTo(1);
  HikariPoolSaturationContractTest.java:105         assertThat(held.isValid(1)).isTrue();
  HikariPoolSaturationContractTest.java:106       }
  HikariPoolSaturationContractTest.java:107     }
  HikariPoolSaturationContractTest.java:108   }
  HikariPoolSaturationContractTest.java:109 
  HikariPoolSaturationContractTest.java:110   private static HikariDataSource pool() {
  HikariPoolSaturationContractTest.java:111     HikariConfig config = new HikariConfig();
  HikariPoolSaturationContractTest.java:112     config.setJdbcUrl(container.getJdbcUrl());
  HikariPoolSaturationContractTest.java:113     config.setUsername(container.getUsername());
  HikariPoolSaturationContractTest.java:114     config.setPassword(container.getPassword());
  HikariPoolSaturationContractTest.java:115     config.setMaximumPoolSize(POOL_SIZE);
  HikariPoolSaturationContractTest.java:116     config.setConnectionTimeout(ACQUIRE_TIMEOUT.toMillis());
  HikariPoolSaturationContractTest.java:117     return new HikariDataSource(config);
  HikariPoolSaturationContractTest.java:118   }

# 나머지 두 주장에는 실제 단언이 있다
  RequiresNewPoolPressureContractTest.java:43   @Test
  RequiresNewPoolPressureContractTest.java:44   @DisplayName("a pool of one deadlocks the moment an inner transaction is needed")
  RequiresNewPoolPressureContractTest.java:45   void poolOfOneCannotServeAnInnerTransaction() throws SQLException {
  RequiresNewPoolPressureContractTest.java:46     try (HikariDataSource pool = pool(1)) {
  RequiresNewPoolPressureContractTest.java:47       try (Connection outer = pool.getConnection()) {
  RequiresNewPoolPressureContractTest.java:48         outer.setAutoCommit(false);
  RequiresNewPoolPressureContractTest.java:49 
  RequiresNewPoolPressureContractTest.java:50         assertThatThrownBy(pool::getConnection)
  RequiresNewPoolPressureContractTest.java:51             .as("the outer transaction still holds its connection while the inner one is opened")
  RequiresNewPoolPressureContractTest.java:52             .isInstanceOf(SQLException.class);
  RequiresNewPoolPressureContractTest.java:53 
  RequiresNewPoolPressureContractTest.java:54         outer.rollback();
  RequiresNewPoolPressureContractTest.java:55       }
  RequiresNewPoolPressureContractTest.java:56     }
  RequiresNewPoolPressureContractTest.java:57   }
  RequiresNewPoolPressureContractTest.java:58 
  RequiresNewPoolPressureContractTest.java:59   @Test
  RequiresNewPoolPressureContractTest.java:60   @DisplayName("a pool of two serves the same nesting")
  RequiresNewPoolPressureContractTest.java:61   void poolOfTwoServesTheSameNesting() throws SQLException {
  RequiresNewPoolPressureContractTest.java:62     try (HikariDataSource pool = pool(2)) {
  RequiresNewPoolPressureContractTest.java:63       try (Connection outer = pool.getConnection()) {
  RequiresNewPoolPressureContractTest.java:64         outer.setAutoCommit(false);
  RequiresNewPoolPressureContractTest.java:65 
  RequiresNewPoolPressureContractTest.java:66         try (Connection inner = pool.getConnection()) {
  RequiresNewPoolPressureContractTest.java:67           inner.setAutoCommit(false);
  RequiresNewPoolPressureContractTest.java:68           assertThat(inner.isValid(1)).isTrue();
  RequiresNewPoolPressureContractTest.java:69           assertThat(inner).isNotSameAs(outer);
  RequiresNewPoolPressureContractTest.java:70           inner.commit();
  RequiresNewPoolPressureContractTest.java:71         }
  RequiresNewPoolPressureContractTest.java:72 
  RequiresNewPoolPressureContractTest.java:73         outer.rollback();
  RequiresNewPoolPressureContractTest.java:74       }
  RequiresNewPoolPressureContractTest.java:75     }
  RequiresNewPoolPressureContractTest.java:76   }
  RequiresNewPoolPressureContractTest.java:77 
  RequiresNewPoolPressureContractTest.java:78   @Test
  RequiresNewPoolPressureContractTest.java:79   @DisplayName("the sizing rule matches the observed requirement")
  RequiresNewPoolPressureContractTest.java:80   void sizingRuleMatchesTheObservedRequirement() {
  RequiresNewPoolPressureContractTest.java:81     int concurrentThreads = 1;
  RequiresNewPoolPressureContractTest.java:82     int maxRequiresNewDepth = 1;
  RequiresNewPoolPressureContractTest.java:83 
  RequiresNewPoolPressureContractTest.java:84     int required = concurrentThreads * (1 + maxRequiresNewDepth) + 1;
  RequiresNewPoolPressureContractTest.java:85 
  RequiresNewPoolPressureContractTest.java:86     assertThat(required)
  RequiresNewPoolPressureContractTest.java:87         .as("one thread at depth one needs two connections; the rule adds headroom")
  RequiresNewPoolPressureContractTest.java:88         .isEqualTo(3);
  RequiresNewPoolPressureContractTest.java:89   }

# PoolMeasurement 는 어디서 온 타입인가
  세 시험이 그것을 어디서 import 하는가 :
    HikariPoolSaturationContractTest.java:8  import dev.caskeleton.adapter.outbound.persistence.testkit.pool.PoolMeasurement;
    PoolPressureContractTest.java:5  import dev.caskeleton.adapter.outbound.persistence.testkit.pool.PoolMeasurement;
  PoolMeasurement.java:6 /**
  PoolMeasurement.java:7  * A reading of connection pool pressure (design §38).
  PoolMeasurement.java:8  *
  PoolMeasurement.java:9  * <p>Pending count and acquire latency are recorded together because either alone is misleading. A
  PoolMeasurement.java:10  * pool can show zero pending at the instant it is sampled while callers routinely wait; a high
  PoolMeasurement.java:11  * acquire latency with no pending count gives no idea how many callers are affected.
  PoolMeasurement.java:12  */
  PoolMeasurement.java:13 public record PoolMeasurement(int active, int idle, int pending, Duration acquireLatency) {
  PoolMeasurement.java:14 
  PoolMeasurement.java:15   public PoolMeasurement {
  PoolMeasurement.java:16     Objects.requireNonNull(acquireLatency, "acquireLatency");
  PoolMeasurement.java:17     if (active < 0 || idle < 0 || pending < 0) {
  PoolMeasurement.java:18       throw new IllegalArgumentException("pool counters must not be negative");
  PoolMeasurement.java:19     }
  PoolMeasurement.java:20     if (acquireLatency.isNegative()) {
  PoolMeasurement.java:21       throw new IllegalArgumentException("acquire latency must not be negative");
  PoolMeasurement.java:22     }
  PoolMeasurement.java:23   }
  PoolMeasurement.java:24 
  PoolMeasurement.java:25   /** How many connections the pool currently holds. */
  PoolMeasurement.java:26   public int total() {
  PoolMeasurement.java:27     return active + idle;
  PoolMeasurement.java:28   }
  PoolMeasurement.java:29 
  PoolMeasurement.java:30   /** Whether callers are waiting for a connection. */
  PoolMeasurement.java:31   public boolean saturated() {
  PoolMeasurement.java:32     return pending > 0;
  PoolMeasurement.java:33   }
  PoolMeasurement.java:34 }
  프로덕션에서 대기 수를 읽는 자리 : 0 개
  [대조] 그 검색이 훑은 main 파일 : 4714 개
