@@ -141,8 +141,9 @@ private inline def inDBTransaction[T](
141141 inline fn: scalasql.core.DbApi.Txn => T,
142142): T =
143143 // Using.resource(DBConcurrencyLimiter(concurrencyLimit = 16)): _ =>
144- Using.resource(EvalDB.dbClient()): db =>
145- db.transaction(fn)
144+ EvalDB.onBusyRetry:
145+ Using.resource(EvalDB.dbClient()): db =>
146+ db.transaction(fn)
146147end inDBTransaction
147148
148149def vacuumDB() = Task.Command(exclusive = true):
@@ -163,6 +164,18 @@ trait EvalDBTrait:
163164 closeFn()
164165 end AutoCloseClient
165166
167+ @scala.annotation.tailrec
168+ final def onBusyRetry[T](fn: => T): T =
169+ try fn
170+ catch
171+ case exn: org.sqlite.SQLiteException
172+ if exn.getResultCode() == org.sqlite.SQLiteErrorCode.SQLITE_BUSY =>
173+ val sleepTime = Random.between(100L, 1000L)
174+ println(s"SQLITE_BUSY, sleeping $sleepTime")
175+ Thread.sleep(sleepTime)
176+ onBusyRetry(fn)
177+ end onBusyRetry
178+
166179 private lazy val fn =
167180 Class.forName("org.sqlite.JDBC")
168181 val fn = () =>
@@ -173,9 +186,10 @@ trait EvalDBTrait:
173186 AutoCloseClient(client, conn.close)
174187 end fn
175188
176- Using.resource(fn()): conn =>
177- val db = conn.getAutoCommitClientConnection
178- db.updateRaw(os.read(BuildCtx.workspaceRoot / createTablesSQL))
189+ onBusyRetry:
190+ Using.resource(fn()): conn =>
191+ val db = conn.getAutoCommitClientConnection
192+ db.updateRaw(os.read(BuildCtx.workspaceRoot / createTablesSQL))
179193
180194 fn
181195 end fn
0 commit comments