Skip to content

Commit cd5318a

Browse files
authored
Revert "[Fix] Query Hangs if Connection is Closed (#487)" (#501)
This reverts commit f55caa7.
1 parent d18b137 commit cd5318a

File tree

3 files changed

+12
-197
lines changed

3 files changed

+12
-197
lines changed

Sources/PostgresNIO/Connection/PostgresConnection.swift

+11-28
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ public final class PostgresConnection: @unchecked Sendable {
222222
promise: promise
223223
)
224224

225-
self.write(.extendedQuery(context), cascadingFailureTo: promise)
225+
self.channel.write(HandlerTask.extendedQuery(context), promise: nil)
226226

227227
return promise.futureResult
228228
}
@@ -239,8 +239,7 @@ public final class PostgresConnection: @unchecked Sendable {
239239
promise: promise
240240
)
241241

242-
self.write(.extendedQuery(context), cascadingFailureTo: promise)
243-
242+
self.channel.write(HandlerTask.extendedQuery(context), promise: nil)
244243
return promise.futureResult.map { rowDescription in
245244
PSQLPreparedStatement(name: name, query: query, connection: self, rowDescription: rowDescription)
246245
}
@@ -256,17 +255,15 @@ public final class PostgresConnection: @unchecked Sendable {
256255
logger: logger,
257256
promise: promise)
258257

259-
self.write(.extendedQuery(context), cascadingFailureTo: promise)
260-
258+
self.channel.write(HandlerTask.extendedQuery(context), promise: nil)
261259
return promise.futureResult
262260
}
263261

264262
func close(_ target: CloseTarget, logger: Logger) -> EventLoopFuture<Void> {
265263
let promise = self.channel.eventLoop.makePromise(of: Void.self)
266264
let context = CloseCommandContext(target: target, logger: logger, promise: promise)
267265

268-
self.write(.closeCommand(context), cascadingFailureTo: promise)
269-
266+
self.channel.write(HandlerTask.closeCommand(context), promise: nil)
270267
return promise.futureResult
271268
}
272269

@@ -429,7 +426,7 @@ extension PostgresConnection {
429426
promise: promise
430427
)
431428

432-
self.write(.extendedQuery(context), cascadingFailureTo: promise)
429+
self.channel.write(HandlerTask.extendedQuery(context), promise: nil)
433430

434431
do {
435432
return try await promise.futureResult.map({ $0.asyncSequence() }).get()
@@ -458,11 +455,7 @@ extension PostgresConnection {
458455

459456
let task = HandlerTask.startListening(listener)
460457

461-
let writePromise = self.channel.eventLoop.makePromise(of: Void.self)
462-
self.channel.write(task, promise: writePromise)
463-
writePromise.futureResult.whenFailure { error in
464-
listener.failed(error)
465-
}
458+
self.channel.write(task, promise: nil)
466459
}
467460
} onCancel: {
468461
let task = HandlerTask.cancelListening(channel, id)
@@ -487,9 +480,7 @@ extension PostgresConnection {
487480
logger: logger,
488481
promise: promise
489482
))
490-
491-
self.write(task, cascadingFailureTo: promise)
492-
483+
self.channel.write(task, promise: nil)
493484
do {
494485
return try await promise.futureResult
495486
.map { $0.asyncSequence() }
@@ -524,9 +515,7 @@ extension PostgresConnection {
524515
logger: logger,
525516
promise: promise
526517
))
527-
528-
self.write(task, cascadingFailureTo: promise)
529-
518+
self.channel.write(task, promise: nil)
530519
do {
531520
return try await promise.futureResult
532521
.map { $0.commandTag }
@@ -541,12 +530,6 @@ extension PostgresConnection {
541530
throw error // rethrow with more metadata
542531
}
543532
}
544-
545-
private func write<T>(_ task: HandlerTask, cascadingFailureTo promise: EventLoopPromise<T>) {
546-
let writePromise = self.channel.eventLoop.makePromise(of: Void.self)
547-
self.channel.write(task, promise: writePromise)
548-
writePromise.futureResult.cascadeFailure(to: promise)
549-
}
550533
}
551534

552535
// MARK: EventLoopFuture interface
@@ -691,7 +674,7 @@ internal enum PostgresCommands: PostgresRequest {
691674

692675
/// Context for receiving NotificationResponse messages on a connection, used for PostgreSQL's `LISTEN`/`NOTIFY` support.
693676
public final class PostgresListenContext: Sendable {
694-
let promise: EventLoopPromise<Void>
677+
private let promise: EventLoopPromise<Void>
695678

696679
var future: EventLoopFuture<Void> {
697680
self.promise.futureResult
@@ -730,7 +713,8 @@ extension PostgresConnection {
730713
closure: notificationHandler
731714
)
732715

733-
self.write(.startListening(listener), cascadingFailureTo: listenContext.promise)
716+
let task = HandlerTask.startListening(listener)
717+
self.channel.write(task, promise: nil)
734718

735719
listenContext.future.whenComplete { _ in
736720
let task = HandlerTask.cancelListening(channel, id)
@@ -777,4 +761,3 @@ extension PostgresConnection {
777761
#endif
778762
}
779763
}
780-

Tests/IntegrationTests/PSQLIntegrationTests.swift

+1
Original file line numberDiff line numberDiff line change
@@ -359,4 +359,5 @@ final class IntegrationTests: XCTestCase {
359359
XCTAssertEqual(obj?.bar, 2)
360360
}
361361
}
362+
362363
}

Tests/PostgresNIOTests/New/PostgresConnectionTests.swift

-169
Original file line numberDiff line numberDiff line change
@@ -224,63 +224,6 @@ class PostgresConnectionTests: XCTestCase {
224224
}
225225
}
226226

227-
func testSimpleListenFailsIfConnectionIsClosed() async throws {
228-
let (connection, channel) = try await self.makeTestConnectionWithAsyncTestingChannel()
229-
230-
try await connection.closeGracefully()
231-
232-
XCTAssertEqual(channel.isActive, false)
233-
234-
do {
235-
_ = try await connection.listen("test_channel")
236-
XCTFail("Expected to fail")
237-
} catch let error as ChannelError {
238-
XCTAssertEqual(error, .ioOnClosedChannel)
239-
}
240-
}
241-
242-
func testSimpleListenFailsIfConnectionIsClosedWhileListening() async throws {
243-
let (connection, channel) = try await self.makeTestConnectionWithAsyncTestingChannel()
244-
245-
try await withThrowingTaskGroup(of: Void.self) { taskGroup in
246-
taskGroup.addTask {
247-
let events = try await connection.listen("foo")
248-
var iterator = events.makeAsyncIterator()
249-
let first = try await iterator.next()
250-
XCTAssertEqual(first?.payload, "wooohooo")
251-
do {
252-
_ = try await iterator.next()
253-
XCTFail("Did not expect to not throw")
254-
} catch let error as PSQLError {
255-
XCTAssertEqual(error.code, .clientClosedConnection)
256-
}
257-
}
258-
259-
let listenMessage = try await channel.waitForUnpreparedRequest()
260-
XCTAssertEqual(listenMessage.parse.query, #"LISTEN "foo";"#)
261-
262-
try await channel.writeInbound(PostgresBackendMessage.parseComplete)
263-
try await channel.writeInbound(PostgresBackendMessage.parameterDescription(.init(dataTypes: [])))
264-
try await channel.writeInbound(PostgresBackendMessage.noData)
265-
try await channel.writeInbound(PostgresBackendMessage.bindComplete)
266-
try await channel.writeInbound(PostgresBackendMessage.commandComplete("LISTEN"))
267-
try await channel.writeInbound(PostgresBackendMessage.readyForQuery(.idle))
268-
269-
try await channel.writeInbound(PostgresBackendMessage.notification(.init(backendPID: 12, channel: "foo", payload: "wooohooo")))
270-
271-
try await connection.close()
272-
273-
XCTAssertEqual(channel.isActive, false)
274-
275-
switch await taskGroup.nextResult()! {
276-
case .success:
277-
break
278-
case .failure(let failure):
279-
XCTFail("Unexpected error: \(failure)")
280-
}
281-
}
282-
}
283-
284227
func testCloseGracefullyClosesWhenInternalQueueIsEmpty() async throws {
285228
let (connection, channel) = try await self.makeTestConnectionWithAsyncTestingChannel()
286229
try await withThrowingTaskGroup(of: Void.self) { [logger] taskGroup async throws -> () in
@@ -695,118 +638,6 @@ class PostgresConnectionTests: XCTestCase {
695638
}
696639
}
697640

698-
func testQueryFailsIfConnectionIsClosed() async throws {
699-
let (connection, channel) = try await self.makeTestConnectionWithAsyncTestingChannel()
700-
701-
try await connection.closeGracefully()
702-
703-
XCTAssertEqual(channel.isActive, false)
704-
705-
do {
706-
_ = try await connection.query("SELECT version;", logger: self.logger)
707-
XCTFail("Expected to fail")
708-
} catch let error as ChannelError {
709-
XCTAssertEqual(error, .ioOnClosedChannel)
710-
}
711-
}
712-
713-
func testPrepareStatementFailsIfConnectionIsClosed() async throws {
714-
let (connection, channel) = try await self.makeTestConnectionWithAsyncTestingChannel()
715-
716-
try await connection.closeGracefully()
717-
718-
XCTAssertEqual(channel.isActive, false)
719-
720-
do {
721-
_ = try await connection.prepareStatement("SELECT version;", with: "test_query", logger: .psqlTest).get()
722-
XCTFail("Expected to fail")
723-
} catch let error as ChannelError {
724-
XCTAssertEqual(error, .ioOnClosedChannel)
725-
}
726-
}
727-
728-
func testExecuteFailsIfConnectionIsClosed() async throws {
729-
let (connection, channel) = try await self.makeTestConnectionWithAsyncTestingChannel()
730-
731-
try await connection.closeGracefully()
732-
733-
XCTAssertEqual(channel.isActive, false)
734-
735-
do {
736-
let statement = PSQLExecuteStatement(name: "SELECT version;", binds: .init(), rowDescription: nil)
737-
_ = try await connection.execute(statement, logger: .psqlTest).get()
738-
XCTFail("Expected to fail")
739-
} catch let error as ChannelError {
740-
XCTAssertEqual(error, .ioOnClosedChannel)
741-
}
742-
}
743-
744-
func testExecutePreparedStatementFailsIfConnectionIsClosed() async throws {
745-
let (connection, channel) = try await self.makeTestConnectionWithAsyncTestingChannel()
746-
747-
try await connection.closeGracefully()
748-
749-
XCTAssertEqual(channel.isActive, false)
750-
751-
struct TestPreparedStatement: PostgresPreparedStatement {
752-
static let sql = "SELECT pid, datname FROM pg_stat_activity WHERE state = $1"
753-
typealias Row = (Int, String)
754-
755-
var state: String
756-
757-
func makeBindings() -> PostgresBindings {
758-
var bindings = PostgresBindings()
759-
bindings.append(self.state)
760-
return bindings
761-
}
762-
763-
func decodeRow(_ row: PostgresNIO.PostgresRow) throws -> Row {
764-
try row.decode(Row.self)
765-
}
766-
}
767-
768-
do {
769-
let preparedStatement = TestPreparedStatement(state: "active")
770-
_ = try await connection.execute(preparedStatement, logger: .psqlTest)
771-
XCTFail("Expected to fail")
772-
} catch let error as ChannelError {
773-
XCTAssertEqual(error, .ioOnClosedChannel)
774-
}
775-
}
776-
777-
func testExecutePreparedStatementWithVoidRowFailsIfConnectionIsClosed() async throws {
778-
let (connection, channel) = try await self.makeTestConnectionWithAsyncTestingChannel()
779-
780-
try await connection.closeGracefully()
781-
782-
XCTAssertEqual(channel.isActive, false)
783-
784-
struct TestPreparedStatement: PostgresPreparedStatement {
785-
static let sql = "SELECT * FROM pg_stat_activity WHERE state = $1"
786-
typealias Row = ()
787-
788-
var state: String
789-
790-
func makeBindings() -> PostgresBindings {
791-
var bindings = PostgresBindings()
792-
bindings.append(self.state)
793-
return bindings
794-
}
795-
796-
func decodeRow(_ row: PostgresNIO.PostgresRow) throws -> Row {
797-
()
798-
}
799-
}
800-
801-
do {
802-
let preparedStatement = TestPreparedStatement(state: "active")
803-
_ = try await connection.execute(preparedStatement, logger: .psqlTest)
804-
XCTFail("Expected to fail")
805-
} catch let error as ChannelError {
806-
XCTAssertEqual(error, .ioOnClosedChannel)
807-
}
808-
}
809-
810641
func makeTestConnectionWithAsyncTestingChannel() async throws -> (PostgresConnection, NIOAsyncTestingChannel) {
811642
let eventLoop = NIOAsyncTestingEventLoop()
812643
let channel = await NIOAsyncTestingChannel(handlers: [

0 commit comments

Comments
 (0)