This is an automated email from the ASF dual-hosted git repository. github-merge-queue[bot] pushed a commit to branch gh-readonly-queue/main/pr-7040-75606f1f28426b79487bde4dcd3296cef60141dc in repository https://gitbox.apache.org/repos/asf/texera.git
commit 0834f25d605a611ed9130fd05c7a7e6f702254d1 Author: Xinyuan Lin <[email protected]> AuthorDate: Wed Jul 29 17:01:17 2026 -0700 refactor(config): replace the hand-rolled AuthConfig secret lock with lazy val (#7040) ### What changes were proposed in this PR? `AuthConfig.jwtSecretKey` hand-rolls a double-checked-locking lazy initializer — a `@volatile var`, a null sentinel and a `synchronized` block — to compute one value once. Scala's `lazy val` is that exact pattern, generated by the compiler. ```scala // before @volatile private var secretKey: String = _ def jwtSecretKey: String = { synchronized { if (secretKey == null) { secretKey = conf.getString("auth.jwt.256-bit-secret").toLowerCase() match { case "random" => getRandomHexString case key => key } } } secretKey } // after lazy val jwtSecretKey: String = conf.getString("auth.jwt.256-bit-secret").toLowerCase() match { case "random" => getRandomHexString case key => key } ``` Behaviour is preserved on every axis I checked: | | hand-rolled | `lazy val` | | --- | --- | --- | | initialized at most once | yes | yes | | safe under concurrent first access | yes (`synchronized`) | yes (compiler-generated DCL) | | safe publication of the result | yes (`@volatile`) | yes | | behaviour if the initializer throws | leaves the field null, retries next call | initialized bit not set, retries next call | | call-site shape | `AuthConfig.jwtSecretKey` | unchanged | The single caller, `JwtAuth.scala:35` (`final val TOKEN_SECRET = AuthConfig.jwtSecretKey`), needs no change — `def` and `lazy val` are indistinguishable at the call site. `getRandomHexString` stays a private `def`, so `AuthConfigSpec`'s reflective lookup of it still resolves. −14 lines, +6. ### Any related issues, documentation, discussions? Closes #7039 ### How was this PR tested? Existing tests only — this PR adds none, since it is a behaviour-preserving rewrite already covered by `AuthConfigSpec` (which pins both the configured-secret path and that the value is memoized across calls). Locally, from the repo root with Java 17: - `sbt "scalafixAll --check"` — clean. - `sbt scalafmtCheckAll` — clean. - `sbt "Config/testOnly *AuthConfigSpec"` — 3 tests, all pass, unmodified. The whole-repo scalafix/scalafmt run also compiles `common/auth`, so the `JwtAuth` call site is covered. ### Was this PR authored or co-authored using generative AI tooling? Generated-by: Claude Code (Claude Opus 5) Co-authored-by: Yicong Huang <[email protected]> --- .../org/apache/texera/common/config/AuthConfig.scala | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/common/config/src/main/scala/org/apache/texera/common/config/AuthConfig.scala b/common/config/src/main/scala/org/apache/texera/common/config/AuthConfig.scala index 43e1409ecd..abda5dff3d 100644 --- a/common/config/src/main/scala/org/apache/texera/common/config/AuthConfig.scala +++ b/common/config/src/main/scala/org/apache/texera/common/config/AuthConfig.scala @@ -28,20 +28,12 @@ object AuthConfig { // Read jwt Expiration time in minutes final val jwtExpirationMinutes: Int = conf.getInt("auth.jwt.expiration-in-minutes") - // For storing the generated/configured secret - @volatile private var secretKey: String = _ - - // Read JWT secret key with support for random generation - def jwtSecretKey: String = { - synchronized { - if (secretKey == null) { - secretKey = conf.getString("auth.jwt.256-bit-secret").toLowerCase() match { - case "random" => getRandomHexString - case key => key - } - } - } - secretKey + // Read JWT secret key with support for random generation. + // `lazy val` already compiles to a thread-safe, initialize-once accessor, so it + // replaces the hand-rolled @volatile + synchronized double-checked lock. + lazy val jwtSecretKey: String = conf.getString("auth.jwt.256-bit-secret").toLowerCase() match { + case "random" => getRandomHexString + case key => key } private def getRandomHexString: String = {
