| 363 | // against SetS3CacheMode so the secret always matches s3CacheMode — |
| 364 | // and it is held (via defer) all the way through |
| 365 | // the Phase 3 payload commit below: released any earlier, a toggle |
| 366 | // could sneak in, read the not-yet-committed OLD payload, and |
| 367 | // last-write the secret with the OLD (soon-to-expire) STS creds |
| 368 | // while Phase 3 records the new expiry — the scheduler would then |
| 369 | // skip the worker until the NEW expiry and the session dies with |
| 370 | // ExpiredToken mid-flight. Health checks only need p.mu.RLock and |
| 371 | // never touch secretSwapMu, so their responsiveness (the reason |
| 372 | // this phase runs without p.mu) is unaffected. |
| 373 | p.secretSwapMu.Lock() |
| 374 | defer p.secretSwapMu.Unlock() |
| 375 | p.mu.RLock() |
| 376 | cacheMode := p.currentS3CacheModeLocked() |
| 377 | p.mu.RUnlock() |
| 378 | refreshCfg := payload.DuckLake |