Skip to content

Commit f90b4e5

Browse files
Propagate errors
1 parent 58b4703 commit f90b4e5

File tree

2 files changed

+51
-20
lines changed

2 files changed

+51
-20
lines changed

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

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,14 @@ struct PreparedStatementStateMachine {
44
enum State {
55
case preparing([PreparedStatementContext])
66
case prepared(RowDescription?)
7-
// TODO: store errors
8-
// case error(PostgresBackendMessage.ErrorResponse)
7+
case error(PSQLError)
98
}
109

1110
enum Action {
12-
case none
1311
case prepareStatement
1412
case waitForAlreadyInFlightPreparation
1513
case executePendingStatements([PreparedStatementContext], RowDescription?)
14+
case returnError([PreparedStatementContext], PSQLError)
1615
}
1716

1817
var preparedStatements: [String: State]
@@ -30,6 +29,8 @@ struct PreparedStatementStateMachine {
3029
return .waitForAlreadyInFlightPreparation
3130
case .prepared(let rowDescription):
3231
return .executePendingStatements([context], rowDescription)
32+
case .error(let error):
33+
return .returnError([context], error)
3334
}
3435
} else {
3536
self.preparedStatements[name] = .preparing([context])
@@ -41,24 +42,27 @@ struct PreparedStatementStateMachine {
4142
name: String,
4243
rowDescription: RowDescription?
4344
) -> Action {
44-
guard let state = self.preparedStatements[name] else {
45+
guard case .preparing(let statements) = self.preparedStatements[name] else {
4546
preconditionFailure("Preparation completed for an unexpected statement")
4647
}
47-
switch state {
48-
case .preparing(let statements):
49-
// When sending the bindings we are going to ask for binary data.
50-
if var rowDescription {
51-
for i in 0..<rowDescription.columns.count {
52-
rowDescription.columns[i].format = .binary
53-
}
54-
self.preparedStatements[name] = .prepared(rowDescription)
55-
return .executePendingStatements(statements, rowDescription)
56-
} else {
57-
self.preparedStatements[name] = .prepared(nil)
58-
return .executePendingStatements(statements, nil)
48+
// When sending the bindings we are going to ask for binary data.
49+
if var rowDescription {
50+
for i in 0..<rowDescription.columns.count {
51+
rowDescription.columns[i].format = .binary
5952
}
60-
case .prepared(_):
61-
return .none
53+
self.preparedStatements[name] = .prepared(rowDescription)
54+
return .executePendingStatements(statements, rowDescription)
55+
} else {
56+
self.preparedStatements[name] = .prepared(nil)
57+
return .executePendingStatements(statements, nil)
58+
}
59+
}
60+
61+
mutating func errorHappened(name: String, error: PSQLError) -> Action {
62+
guard case .preparing(let statements) = self.preparedStatements[name] else {
63+
preconditionFailure("Preparation completed for an unexpected statement")
6264
}
65+
self.preparedStatements[name] = .error(error)
66+
return .returnError(statements, error)
6367
}
6468
}

Sources/PostgresNIO/New/PostgresChannelHandler.swift

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,8 +243,6 @@ final class PostgresChannelHandler: ChannelDuplexHandler {
243243
name: preparedStatement.name,
244244
context: preparedStatement
245245
) {
246-
case .none:
247-
return
248246
case .prepareStatement:
249247
let promise = self.eventLoop.makePromise(of: RowDescription?.self)
250248
promise.futureResult.whenSuccess { rowDescription in
@@ -254,6 +252,13 @@ final class PostgresChannelHandler: ChannelDuplexHandler {
254252
context: context
255253
)
256254
}
255+
promise.futureResult.whenFailure { error in
256+
self.prepareStatementFailed(
257+
name: preparedStatement.name,
258+
error: error as! PSQLError,
259+
context: context
260+
)
261+
}
257262
psqlTask = .preparedStatement(.init(
258263
name: preparedStatement.name,
259264
query: preparedStatement.sql,
@@ -277,6 +282,11 @@ final class PostgresChannelHandler: ChannelDuplexHandler {
277282
self.run(action, with: context)
278283
}
279284
return
285+
case .returnError(let pendingStatements, let error):
286+
for statement in pendingStatements {
287+
statement.promise.fail(error)
288+
}
289+
return
280290
}
281291
}
282292

@@ -735,6 +745,23 @@ final class PostgresChannelHandler: ChannelDuplexHandler {
735745
self.run(action, with: context)
736746
}
737747
}
748+
749+
private func prepareStatementFailed(
750+
name: String,
751+
error: PSQLError,
752+
context: ChannelHandlerContext
753+
) {
754+
let action = self.preparedStatementState.errorHappened(
755+
name: name,
756+
error: error
757+
)
758+
guard case .returnError(let statements, let error) = action else {
759+
preconditionFailure("Expected to have pending statements to execute")
760+
}
761+
for statement in statements {
762+
statement.promise.fail(error)
763+
}
764+
}
738765
}
739766

740767
extension PostgresChannelHandler: PSQLRowsDataSource {

0 commit comments

Comments
 (0)