@@ -1352,4 +1352,58 @@ class ValueObservationTests: GRDBTestCase {
13521352 XCTAssertEqual ( value, true )
13531353 } )
13541354 }
1355+
1356+ // Regression test for <https://github.com/groue/GRDB.swift/discussions/1746>
1357+ @MainActor func testIssue1746( ) async throws {
1358+ let dbQueue = try makeDatabaseQueue ( )
1359+ try await dbQueue. write { db in
1360+ try db. execute ( sql: " CREATE TABLE test (id INTEGER PRIMARY KEY) " )
1361+ }
1362+
1363+ // Start a task that waits for writeContinuation before it writes.
1364+ let ( writeStream, writeContinuation) = AsyncStream . makeStream ( of: Void . self)
1365+ let task = Task {
1366+ for await _ in writeStream { }
1367+ try ? await dbQueue. write { db in
1368+ XCTAssertFalse ( Task . isCancelled) // Required for the test to be meaningful
1369+ try db. execute ( sql: " INSERT INTO test DEFAULT VALUES " )
1370+ }
1371+ }
1372+
1373+ // A transaction observer that cancels a Task after commit.
1374+ class CancelObserver : TransactionObserver {
1375+ let task : Task < Void , Never >
1376+ init ( task: Task < Void , Never > ) {
1377+ self . task = task
1378+ }
1379+ func observes( eventsOfKind eventKind: DatabaseEventKind ) -> Bool { true }
1380+ func databaseDidChange( with event: DatabaseEvent ) { }
1381+ func databaseDidRollback( _ db: Database ) { }
1382+ func databaseDidCommit( _ db: Database ) {
1383+ task. cancel ( )
1384+ }
1385+ }
1386+
1387+ // Register CancelObserver first, so no other observer could access
1388+ // the database before the task is cancelled.
1389+ dbQueue. add ( transactionObserver: CancelObserver ( task: task) , extent: . databaseLifetime)
1390+
1391+ // Start observing.
1392+ // We expect to see 0, then 1.
1393+ let values = ValueObservation
1394+ . tracking ( Table ( " test " ) . fetchCount)
1395+ . values ( in: dbQueue)
1396+ for try await value in values {
1397+ if value == 0 {
1398+ // Perform the write.
1399+ writeContinuation. finish ( )
1400+ } else if value == 1 {
1401+ // Test passes
1402+ break
1403+ } else {
1404+ XCTFail ( " Unexpected value \( value) " )
1405+ break
1406+ }
1407+ }
1408+ }
13551409}
0 commit comments