Skip to content

Commit 7eca425

Browse files
jamesarichclaude
andcommitted
fix(database): use a single connection for in-memory test databases
configureCommon() applied setMultipleConnectionPool(maxNumOfReaders = 4) to every database, including the in-memory ones used by tests. A read on a pooled reader connection can observe a snapshot older than the latest write on the writer connection, so a read immediately after a write may return stale rows. DeviceLinkRepositoryImplTest.reconcilePrunesShortCodesNoLongerInCatalog read [a, b] (the pre-prune state) instead of [a] after a deleteNotIn — passing locally but flaking on CI depending on connection-assignment timing (failed shard-core on #5738; the identical code passed on #5780). In-memory builders now pass multiConnection = false so reads serialize behind writes on one connection. Production/file databases keep the multi-reader pool. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent decc74c commit 7eca425

4 files changed

Lines changed: 17 additions & 8 deletions

File tree

core/database/src/androidMain/kotlin/org/meshtastic/core/database/DatabaseBuilder.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ actual fun getDatabaseBuilder(dbName: String): RoomDatabase.Builder<MeshtasticDa
4545
/** Returns a [RoomDatabase.Builder] configured for an in-memory Android database. */
4646
actual fun getInMemoryDatabaseBuilder(): RoomDatabase.Builder<MeshtasticDatabase> =
4747
Room.inMemoryDatabaseBuilder<MeshtasticDatabase>(factory = { MeshtasticDatabaseConstructor.initialize() })
48-
.configureCommon()
48+
.configureCommon(multiConnection = false)
4949
.setDriver(BundledSQLiteDriver())
5050

5151
/** Returns the Android directory where database files are stored. */

core/database/src/commonMain/kotlin/org/meshtastic/core/database/MeshtasticDatabase.kt

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -139,11 +139,20 @@ abstract class MeshtasticDatabase : RoomDatabase() {
139139
abstract fun discoveryDao(): DiscoveryDao
140140

141141
companion object {
142-
/** Configures a [RoomDatabase.Builder] with standard settings for this project. */
143-
fun <T : RoomDatabase> RoomDatabase.Builder<T>.configureCommon(): RoomDatabase.Builder<T> =
144-
this.fallbackToDestructiveMigration(dropAllTables = false)
145-
.setMultipleConnectionPool(maxNumOfReaders = 4, maxNumOfWriters = 1)
146-
.setQueryCoroutineContext(ioDispatcher)
142+
/**
143+
* Configures a [RoomDatabase.Builder] with standard settings for this project.
144+
*
145+
* @param multiConnection opens a multi-reader connection pool for concurrent reads. Production/file databases
146+
* want this. In-memory databases (tests) MUST pass `false`: a pooled reader connection can serve a snapshot
147+
* older than the latest write on the writer connection, so a read immediately after a write may observe stale
148+
* rows — making read-after-write assertions non-deterministically flaky (see `DeviceLinkRepositoryImplTest`).
149+
* A single connection serializes reads behind writes.
150+
*/
151+
fun <T : RoomDatabase> RoomDatabase.Builder<T>.configureCommon(
152+
multiConnection: Boolean = true,
153+
): RoomDatabase.Builder<T> = this.fallbackToDestructiveMigration(dropAllTables = false)
154+
.apply { if (multiConnection) setMultipleConnectionPool(maxNumOfReaders = 4, maxNumOfWriters = 1) }
155+
.setQueryCoroutineContext(ioDispatcher)
147156
}
148157
}
149158

core/database/src/iosMain/kotlin/org/meshtastic/core/database/DatabaseBuilder.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ actual fun getDatabaseBuilder(dbName: String): RoomDatabase.Builder<MeshtasticDa
5151
/** Returns a [RoomDatabase.Builder] configured for an in-memory iOS database. */
5252
actual fun getInMemoryDatabaseBuilder(): RoomDatabase.Builder<MeshtasticDatabase> =
5353
Room.inMemoryDatabaseBuilder<MeshtasticDatabase>(factory = { MeshtasticDatabaseConstructor.initialize() })
54-
.configureCommon()
54+
.configureCommon(multiConnection = false)
5555
.setDriver(BundledSQLiteDriver())
5656

5757
/** Returns the iOS directory where database files are stored. */

core/database/src/jvmMain/kotlin/org/meshtastic/core/database/DatabaseBuilder.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ actual fun getDatabaseBuilder(dbName: String): RoomDatabase.Builder<MeshtasticDa
5757
/** Returns a [RoomDatabase.Builder] configured for an in-memory JVM database. */
5858
actual fun getInMemoryDatabaseBuilder(): RoomDatabase.Builder<MeshtasticDatabase> =
5959
Room.inMemoryDatabaseBuilder<MeshtasticDatabase>(factory = { MeshtasticDatabaseConstructor.initialize() })
60-
.configureCommon()
60+
.configureCommon(multiConnection = false)
6161
.setDriver(BundledSQLiteDriver())
6262

6363
/** Returns the JVM/Desktop directory where database files are stored. */

0 commit comments

Comments
 (0)