Skip to content

Commit 64ae9ff

Browse files
committed
test immediat request execution on required event loop
1 parent 960796c commit 64ae9ff

File tree

3 files changed

+47
-11
lines changed

3 files changed

+47
-11
lines changed

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

+5
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,11 @@ extension HTTPConnectionPool {
576576
/// true if no stream is leased
577577
var isIdle: Bool
578578
}
579+
580+
struct LeasedStreamContext {
581+
/// true if the connection was idle before leasing the stream
582+
var wasIdle: Bool
583+
}
579584

580585
struct LeasedStreamContext {
581586
/// true if the connection was idle before leasing the stream

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

+25-11
Original file line numberDiff line numberDiff line change
@@ -102,12 +102,19 @@ extension HTTPConnectionPool {
102102
_ request: Request,
103103
onRequired eventLoop: EventLoop
104104
) -> Action {
105-
if let connection = self.connections.leaseStream(onRequired: eventLoop) {
105+
if let (connection, context) = self.connections.leaseStream(onRequired: eventLoop) {
106106
/// 1. we have a stream available and can execute the request immediately
107-
return .init(
108-
request: .executeRequest(request, connection, cancelTimeout: false),
109-
connection: .cancelTimeoutTimer(connection.id)
110-
)
107+
if context.wasIdle {
108+
return .init(
109+
request: .executeRequest(request, connection, cancelTimeout: false),
110+
connection: .cancelTimeoutTimer(connection.id)
111+
)
112+
} else {
113+
return .init(
114+
request: .executeRequest(request, connection, cancelTimeout: false),
115+
connection: .none
116+
)
117+
}
111118
}
112119
/// 2. No available stream so we definitely need to wait until we have one
113120
self.requests.push(request)
@@ -132,12 +139,19 @@ extension HTTPConnectionPool {
132139
_ request: Request,
133140
onPreferred eventLoop: EventLoop
134141
) -> Action {
135-
if let connection = self.connections.leaseStream(onPreferred: eventLoop) {
142+
if let (connection, context) = self.connections.leaseStream(onPreferred: eventLoop) {
136143
/// 1. we have a stream available and can execute the request immediately
137-
return .init(
138-
request: .executeRequest(request, connection, cancelTimeout: false),
139-
connection: .cancelTimeoutTimer(connection.id)
140-
)
144+
if context.wasIdle {
145+
return .init(
146+
request: .executeRequest(request, connection, cancelTimeout: false),
147+
connection: .cancelTimeoutTimer(connection.id)
148+
)
149+
} else {
150+
return .init(
151+
request: .executeRequest(request, connection, cancelTimeout: false),
152+
connection: .none
153+
)
154+
}
141155
}
142156
/// 2. No available stream so we definitely need to wait until we have one
143157
self.requests.push(request)
@@ -182,7 +196,7 @@ extension HTTPConnectionPool {
182196
let remainingAvailableStreams = context.availableStreams - requestsToExecute.count
183197
// use the remaining available streams for requests without a required event loop
184198
requestsToExecute += self.requests.popFirst(max: remainingAvailableStreams, for: nil)
185-
let connection = self.connections.leaseStreams(at: index, count: requestsToExecute.count)
199+
let (connection, _) = self.connections.leaseStreams(at: index, count: requestsToExecute.count)
186200

187201
let requestAction = { () -> RequestAction in
188202
if requestsToExecute.isEmpty {

Diff for: Tests/AsyncHTTPClientTests/HTTPConnectionPool+HTTP2StateMachineTests.swift

+17
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,23 @@ class HTTPConnectionPool_HTTP2StateMachineTests: XCTestCase {
9090
}
9191
XCTAssertTrue(queuer.isEmpty)
9292

93+
/// closing streams without any queued requests shouldn't do anything if it's *not* the last stream
94+
for _ in 0..<4 {
95+
let action = state.http2ConnectionStreamClosed(connID)
96+
XCTAssertEqual(action.request, .none)
97+
XCTAssertEqual(action.connection, .none)
98+
}
99+
100+
/// 4 streams are available and therefore request should be executed immediately
101+
for _ in 0..<4 {
102+
let mockRequest = MockHTTPRequest(eventLoop: el1, requiresEventLoopForChannel: true)
103+
let request = HTTPConnectionPool.Request(mockRequest)
104+
let action = state.executeRequest(request)
105+
106+
XCTAssertEqual(action.connection, .none)
107+
XCTAssertEqual(action.request, .executeRequest(request, conn, cancelTimeout: false))
108+
}
109+
93110
/// closing streams without any queued requests shouldn't do anything if it's *not* the last stream
94111
for _ in 0..<4 {
95112
let action = state.http2ConnectionStreamClosed(connID)

0 commit comments

Comments
 (0)