Context
From the July 2026 McRPG quest-system audit (verified: CONFIRMED, severity medium — but load-bearing). Every DB operation in the McRPG quest vertical (player loads, chain saves, board rotation persistence, quest-tree saves, GUI history loads) serializes through a single thread, and at least one downstream component's correctness silently depends on that accident.
Problem
Database creates ThreadPoolExecutor(1, 8, 30s, new LinkedBlockingDeque<>()) (src/main/java/com/diamonddagger590/mccore/database/Database.java:43-44). With an unbounded work queue, a ThreadPoolExecutor never creates threads beyond corePoolSize — max=8 is unreachable dead configuration.
Two faces:
- Performance: a slow batch (e.g. board-rotation persistence of hundreds of offerings) queues every player load behind it — join stalls during login waves.
- Hidden correctness crutch: McRPG's
ChainPersistenceService claims per-player write serialization but its future-chaining doesn't actually order execution — ordering holds only because this pool is single-threaded. Naively "fixing" this pool would introduce data races downstream.
Implementation plan
- Decide the contract explicitly and document it on
getDatabaseExecutorService():
- Option A (recommended for SQLite, the only shipped driver): make it an honest
Executors.newSingleThreadExecutor() with Javadoc stating FIFO single-threaded execution is the contract downstream code may rely on.
- Option B: real parallelism (bounded queue / fixed pool) — only after the McRPG chain-persistence ordering fix lands (companion McRPG ticket), and with Javadoc stating that submission order is NOT execution order.
- Either way, name threads (
McCore-Database-Thread-%d) for diagnosability, and add an UncaughtExceptionHandler/wrapper so RuntimeExceptions thrown by submitted tasks are logged instead of vanishing into discarded Futures (the audit found multiple bare executor.submit() sites downstream whose failures disappear).
- Update
CLAUDE.md (Database section) with the decided contract.
Acceptance criteria
Dependencies
If Option B is chosen: blocked by the McRPG ticket "Make ChainPersistenceService per-player write ordering real" (referenced from the McRPG tracking issue).
Context
From the July 2026 McRPG quest-system audit (verified: CONFIRMED, severity medium — but load-bearing). Every DB operation in the McRPG quest vertical (player loads, chain saves, board rotation persistence, quest-tree saves, GUI history loads) serializes through a single thread, and at least one downstream component's correctness silently depends on that accident.
Problem
DatabasecreatesThreadPoolExecutor(1, 8, 30s, new LinkedBlockingDeque<>())(src/main/java/com/diamonddagger590/mccore/database/Database.java:43-44). With an unbounded work queue, aThreadPoolExecutornever creates threads beyondcorePoolSize—max=8is unreachable dead configuration.Two faces:
ChainPersistenceServiceclaims per-player write serialization but its future-chaining doesn't actually order execution — ordering holds only because this pool is single-threaded. Naively "fixing" this pool would introduce data races downstream.Implementation plan
getDatabaseExecutorService():Executors.newSingleThreadExecutor()with Javadoc stating FIFO single-threaded execution is the contract downstream code may rely on.McCore-Database-Thread-%d) for diagnosability, and add anUncaughtExceptionHandler/wrapper soRuntimeExceptions thrown by submitted tasks are logged instead of vanishing into discardedFutures (the audit found multiple bareexecutor.submit()sites downstream whose failures disappear).CLAUDE.md(Database section) with the decided contract.Acceptance criteria
ManagedExecutorExtension)../gradlew testpasses with zero failures.Dependencies
If Option B is chosen: blocked by the McRPG ticket "Make ChainPersistenceService per-player write ordering real" (referenced from the McRPG tracking issue).