Skip to content

Commit 5b7c946

Browse files
committed
handle http1 connection release and close
1 parent cf30758 commit 5b7c946

File tree

1 file changed

+45
-7
lines changed

1 file changed

+45
-7
lines changed

Diff for: Sources/AsyncHTTPClient/ConnectionPool/State Machine/HTTPConnectionPool+HTTP2StateMachine.swift

+45-7
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,9 @@ extension HTTPConnectionPool {
236236

237237
mutating func http2ConnectionClosed(_ connectionID: Connection.ID) -> Action {
238238
guard let (index, context) = self.connections.failConnection(connectionID) else {
239+
// When a connection close is initiated by the connection pool, the connection will
240+
// still report its close to the state machine. In those cases we must ignore the
241+
// event.
239242
return .none
240243
}
241244
return self.nextActionForFailedConnection(at: index, on: context.eventLoop)
@@ -367,17 +370,52 @@ extension HTTPConnectionPool {
367370
}
368371

369372
mutating func connectionClosed(_ connectionID: Connection.ID) -> Action {
370-
guard let (index, context) = self.connections.failConnection(connectionID) else {
371-
// When a connection close is initiated by the connection pool, the connection will
372-
// still report its close to the state machine. In those cases we must ignore the
373-
// event.
373+
guard let index = self.http1Connections?.failConnection(connectionID)?.0 else {
374374
return .none
375375
}
376-
return self.nextActionForFailedConnection(at: index, on: context.eventLoop)
376+
self.http1Connections!.removeConnection(at: index)
377+
if self.http1Connections!.isEmpty {
378+
self.http1Connections = nil
379+
}
380+
switch state {
381+
case .running:
382+
return .none
383+
case .shuttingDown(let unclean):
384+
if self.http1Connections == nil && self.connections.isEmpty {
385+
return .init(
386+
request: .none,
387+
connection: .cleanupConnections(.init(), isShutdown: .yes(unclean: unclean))
388+
)
389+
} else {
390+
return .none
391+
}
392+
case .shutDown:
393+
preconditionFailure("If the pool is already shutdown, all connections must have been torn down.")
394+
}
377395
}
378396

379-
mutating func http1ConnectionReleased(_: Connection.ID) -> Action {
380-
fatalError("TODO: implement \(#function)")
397+
mutating func http1ConnectionReleased(_ connectionID: Connection.ID) -> Action {
398+
// It is save to bang the http1Connections here. If we get this callback but we don't have
399+
// http1 connections something has gone terribly wrong.
400+
let (index, _) = self.http1Connections!.releaseConnection(connectionID)
401+
// Any http1 connection that becomes idle should be closed right away after the transition
402+
// to http2.
403+
let connection = self.http1Connections!.closeConnection(at: index)
404+
if self.http1Connections!.isEmpty {
405+
self.http1Connections = nil
406+
}
407+
switch state {
408+
case .running:
409+
return .init(request: .none, connection: .closeConnection(connection, isShutdown: .no))
410+
case .shuttingDown(let unclean):
411+
if self.http1Connections == nil && self.connections.isEmpty {
412+
return .init(request: .none, connection: .closeConnection(connection, isShutdown: .yes(unclean: unclean)))
413+
} else {
414+
return .init(request: .none, connection: .closeConnection(connection, isShutdown: .no))
415+
}
416+
case .shutDown:
417+
preconditionFailure("If the pool is already shutdown, all connections must have been torn down.")
418+
}
381419
}
382420

383421
mutating func shutdown() -> Action {

0 commit comments

Comments
 (0)