Skip to content

Commit 6e993d5

Browse files
authored
Fixes crash in queries that timeout (#351)
1 parent 1516e0c commit 6e993d5

File tree

2 files changed

+37
-4
lines changed

2 files changed

+37
-4
lines changed

Sources/PostgresNIO/New/PostgresChannelHandler.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,8 +273,9 @@ final class PostgresChannelHandler: ChannelDuplexHandler {
273273

274274

275275
case .forwardStreamError(let error, let read, let cleanupContext):
276-
self.rowStream!.receive(completion: .failure(error))
276+
let rowStream = self.rowStream!
277277
self.rowStream = nil
278+
rowStream.receive(completion: .failure(error))
278279
if let cleanupContext = cleanupContext {
279280
self.closeConnectionAndCleanup(cleanupContext, context: context)
280281
} else if read {

Tests/IntegrationTests/AsyncTests.swift

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,45 @@ final class AsyncPostgresConnectionTests: XCTestCase {
3636

3737
try await withTestConnection(on: eventLoop) { connection in
3838
let rows = try await connection.query("SELECT generate_series(\(start), \(end));", logger: .psqlTest)
39-
var counter = 1
39+
var counter = 0
4040
for try await element in rows.decode(Int.self, context: .default) {
41-
XCTAssertEqual(element, counter)
41+
XCTAssertEqual(element, counter + 1)
4242
counter += 1
4343
}
4444

45-
XCTAssertEqual(counter, end + 1)
45+
XCTAssertEqual(counter, end)
46+
}
47+
}
48+
49+
func testSelectTimeoutWhileLongRunningQuery() async throws {
50+
let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)
51+
defer { XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully()) }
52+
let eventLoop = eventLoopGroup.next()
53+
54+
let start = 1
55+
let end = 10000000
56+
57+
try await withTestConnection(on: eventLoop) { connection -> () in
58+
try await connection.query("SET statement_timeout=1000;", logger: .psqlTest)
59+
60+
let rows = try await connection.query("SELECT generate_series(\(start), \(end));", logger: .psqlTest)
61+
var counter = 0
62+
do {
63+
for try await element in rows.decode(Int.self, context: .default) {
64+
XCTAssertEqual(element, counter + 1)
65+
counter += 1
66+
}
67+
XCTFail("Expected to get cancelled while reading the query")
68+
} catch {
69+
guard let error = error as? PSQLError else { return XCTFail("Unexpected error type") }
70+
71+
print(error)
72+
73+
XCTAssertEqual(error.code, .server)
74+
XCTAssertEqual(error.serverInfo?[.severity], "ERROR")
75+
}
76+
77+
XCTAssertFalse(connection.isClosed, "Connection should survive!")
4678
}
4779
}
4880

0 commit comments

Comments
 (0)