@@ -677,4 +677,52 @@ class DatabaseReaderTests : GRDBTestCase {
677677 try await test ( AnyDatabaseReader ( makeDatabaseQueue ( ) ) )
678678 try await test ( AnyDatabaseWriter ( makeDatabaseQueue ( ) ) )
679679 }
680+
681+ // Regression test for https://github.com/groue/GRDB.swift/pull/1797
682+ func test_cancellation_does_not_impact_other_tasks( ) async throws {
683+ func test( _ dbReader: some DatabaseReader ) async throws {
684+ // Numbers that have the test fail more or less reliably
685+ // (on my machine) unless the #1797 patch is applied.
686+ let repeatCount = 30
687+ let taskCount = 400
688+ for _ in 0 ..< repeatCount {
689+ try await withThrowingTaskGroup ( of: Void . self) { group in
690+ for i in 0 ..< taskCount{
691+ let task = Task {
692+ try await dbReader. read { db in
693+ try db. execute ( sql: " SELECT 1 " )
694+ }
695+ }
696+ group. addTask {
697+ if i. isMultiple ( of: 2 ) {
698+ Task {
699+ // For the test to fail, we need to be lucky, here:
700+ // Cancellation must occur after the database access
701+ // has completed, but before `read` has returned. This
702+ // triggers the failure of unrelated tasks because
703+ // the database enters the cancelled state
704+ // (fixed by #1797).
705+ task. cancel ( )
706+ }
707+ // Ignore expected CancellationError
708+ try ? await task. value
709+ } else {
710+ // Unexpected CancellationError fails the test
711+ try await task. value
712+ }
713+ }
714+ }
715+ try await group. waitForAll ( )
716+ }
717+ }
718+ }
719+ try await test ( makeDatabaseQueue ( ) )
720+ try await test ( makeDatabasePool ( ) )
721+ try await test ( makeDatabasePool ( ) . makeSnapshot ( ) )
722+ #if SQLITE_ENABLE_SNAPSHOT || (!GRDBCUSTOMSQLITE && !GRDBCIPHER)
723+ try await test ( makeDatabasePool ( ) . makeSnapshotPool ( ) )
724+ #endif
725+ try await test ( AnyDatabaseReader ( makeDatabaseQueue ( ) ) )
726+ try await test ( AnyDatabaseWriter ( makeDatabaseQueue ( ) ) )
727+ }
680728}
0 commit comments