Skip to content

Commit cb05b24

Browse files
committed
Communicate side effects of checkBackendCanReceiveCopyData via an action
1 parent cca91b8 commit cb05b24

File tree

3 files changed

+27
-7
lines changed

3 files changed

+27
-7
lines changed

Sources/PostgresNIO/New/Connection State Machine/ConnectionStateMachine.swift

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,17 @@ struct ConnectionStateMachine {
141141
case succeedPromise(EventLoopPromise<Void>)
142142
}
143143

144+
enum CheckBackendCanReceiveCopyDataAction {
145+
/// Don't perform any action.
146+
case none
147+
148+
/// Succeed the promise with a Void result.
149+
case succeedPromise(EventLoopPromise<Void>)
150+
151+
/// Fail the promise with the given error.
152+
case failPromise(EventLoopPromise<Void>, error: any Error)
153+
}
154+
144155
private var state: State
145156
private let requireBackendKeyData: Bool
146157
private var taskQueue = CircularBuffer<PSQLTask>()
@@ -815,14 +826,15 @@ struct ConnectionStateMachine {
815826
/// The promise may be failed if the backend indicated that it can't handle any more data by sending an
816827
/// `ErrorResponse`. This is mostly the case when malformed data is sent to it. In that case, the data transfer
817828
/// should be aborted to avoid unnecessary work.
818-
mutating func checkBackendCanReceiveCopyData(channelIsWritable: Bool, promise: EventLoopPromise<Void>) {
829+
mutating func checkBackendCanReceiveCopyData(channelIsWritable: Bool, promise: EventLoopPromise<Void>) -> CheckBackendCanReceiveCopyDataAction {
819830
guard case .extendedQuery(var queryState, let connectionContext) = self.state else {
820831
preconditionFailure("Copy mode is only supported for extended queries")
821832
}
822833

823834
self.state = .modifying // avoid CoW
824-
queryState.checkBackendCanReceiveCopyData(channelIsWritable: channelIsWritable, promise: promise)
835+
let action = queryState.checkBackendCanReceiveCopyData(channelIsWritable: channelIsWritable, promise: promise)
825836
self.state = .extendedQuery(queryState, connectionContext)
837+
return action
826838
}
827839

828840
/// Put the state machine out of the copying mode and send a `CopyDone` message to the backend.

Sources/PostgresNIO/New/Connection State Machine/ExtendedQueryStateMachine.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -423,22 +423,22 @@ struct ExtendedQueryStateMachine {
423423
/// The promise may be failed if the backend indicated that it can't handle any more data by sending an
424424
/// `ErrorResponse`. This is mostly the case when malformed data is sent to it. In that case, the data transfer
425425
/// should be aborted to avoid unnecessary work.
426-
mutating func checkBackendCanReceiveCopyData(channelIsWritable: Bool, promise: EventLoopPromise<Void>) {
426+
mutating func checkBackendCanReceiveCopyData(channelIsWritable: Bool, promise: EventLoopPromise<Void>) -> ConnectionStateMachine.CheckBackendCanReceiveCopyDataAction {
427427
if case .error(let error) = self.state {
428428
// The backend sent us an ErrorResponse during the copy operation. Indicate to the client that it should
429429
// abort the data transfer.
430430
promise.fail(error)
431-
return
431+
return . failPromise(promise, error: error)
432432
}
433433
guard case .copyingData(.readyToSend) = self.state else {
434434
preconditionFailure("Not ready to send data")
435435
}
436436
if channelIsWritable {
437-
promise.succeed()
438-
return
437+
return .succeedPromise(promise)
439438
}
440439
return avoidingStateMachineCoW { state in
441440
state = .copyingData(.pendingBackpressureRelieve(promise))
441+
return .none
442442
}
443443
}
444444

Sources/PostgresNIO/New/PostgresChannelHandler.swift

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,15 @@ final class PostgresChannelHandler: ChannelDuplexHandler {
181181
promise.fail(PostgresError.connectionClosed)
182182
return
183183
}
184-
self.state.checkBackendCanReceiveCopyData(channelIsWritable: handlerContext.channel.isWritable, promise: promise)
184+
let action = self.state.checkBackendCanReceiveCopyData(channelIsWritable: handlerContext.channel.isWritable, promise: promise)
185+
switch action {
186+
case .none:
187+
break
188+
case .succeedPromise(let promise):
189+
promise.succeed()
190+
case .failPromise(let promise, error: let error):
191+
promise.fail(error)
192+
}
185193
}
186194

187195
/// Cancel the currently executing operation, if it is cancellable.

0 commit comments

Comments
 (0)