Skip to content

Commit 6f45596

Browse files
committed
Code review
1 parent c3f856d commit 6f45596

File tree

5 files changed

+302
-285
lines changed

5 files changed

+302
-285
lines changed

Diff for: Sources/AsyncHTTPClient/ConnectionPool/HTTPExecutingRequest.swift

+10-16
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,9 @@ import NIOHTTP1
7171
///
7272
/// The request execution will work as follows:
7373
///
74-
/// 1. The request executor will call `willExecuteRequest(_: HTTPRequestExecutor) -> Bool` on the
75-
/// request. The request is expected to return `true`, if it wants to be executed and false if
76-
///     it was cancelled or failed, before this checkpoint. If the request returns `true` it is
77-
/// expected to keep a reference to the `HTTPRequestExecutor` that was passed to the request
78-
/// for further communication. If the request returned false, the executor shall inform the
79-
/// scheduling mechanism that it is ready to execute the a new request.
74+
/// 1. The request executor will call `willExecuteRequest(_: HTTPRequestExecutor)` on the
75+
/// request. The request is expected to keep a reference to the `HTTPRequestExecutor` that was
76+
/// passed to the request for further communication.
8077
/// 2. The request sending is started by the executor accessing the `HTTPExecutingRequest`'s
8178
/// property `requestHead: HTTPRequestHead`. Based on the `requestHead` the executor can
8279
/// determine if the request has a body (Is a "content-length" or "transfer-encoding"
@@ -201,18 +198,15 @@ protocol HTTPExecutingRequest: AnyObject {
201198

202199
/// Will be called by the ChannelHandler to indicate that the request is going to be sent.
203200
///
204-
/// This will be called on the Channel's EventLoop. Do **not block** during your execution!
205-
///
206-
/// - Returns: A bool indicating if the request should be started. Return `false` if the request
207-
/// has already been cancelled. If the request is cancelled after the `willExecuteRequest`
208-
/// method was called. The executing request must call `executor.cancel()` to stop
209-
/// request execution.
210-
func willExecuteRequest(_: HTTPRequestExecutor) -> Bool
201+
/// This will be called on the Channel's EventLoop. Do **not block** during your execution! If the
202+
/// request is cancelled after the `willExecuteRequest` method was called. The executing
203+
/// request must call `executor.cancel()` to stop request execution.
204+
func willExecuteRequest(_: HTTPRequestExecutor)
211205

212206
/// Will be called by the ChannelHandler to indicate that the request head has been sent.
213207
///
214208
/// This will be called on the Channel's EventLoop. Do **not block** during your execution!
215-
func requestHeadSent(_: HTTPRequestHead)
209+
func requestHeadSent()
216210

217211
/// Start or resume request body streaming
218212
///
@@ -238,9 +232,9 @@ protocol HTTPExecutingRequest: AnyObject {
238232
/// be called in quick succession. It is the task's job to buffer those events for the user. Once all
239233
/// buffered data has been consumed the task must call `executor.demandResponseBodyStream`
240234
/// to ask for more data.
241-
func receiveResponseBodyPart(_ buffer: ByteBuffer)
235+
func receiveResponseBodyParts(_ buffer: CircularBuffer<ByteBuffer>)
242236

243-
func receiveResponseEnd()
237+
func succeedRequest(_ buffer: CircularBuffer<ByteBuffer>?)
244238

245239
func fail(_ error: Error)
246240
}

Diff for: Sources/AsyncHTTPClient/RequestBag+StateMachine.swift

+33-16
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ extension RequestBag {
4343

4444
case initialized
4545
case buffering(CircularBuffer<ByteBuffer>, next: Next)
46-
case waitingForRemote(CircularBuffer<ByteBuffer>)
46+
case waitingForRemote
4747
}
4848

4949
private var state: State = .initialized
@@ -282,26 +282,31 @@ extension RequestBag.StateMachine {
282282
}
283283
}
284284

285-
mutating func receiveResponseBodyPart(_ byteBuffer: ByteBuffer) -> ByteBuffer? {
285+
mutating func receiveResponseBodyParts(_ buffer: CircularBuffer<ByteBuffer>) -> ByteBuffer? {
286286
switch self.state {
287287
case .initialized, .queued:
288288
preconditionFailure("How can we receive a response body part, if the request hasn't started yet.")
289289
case .executing(_, _, .initialized):
290290
preconditionFailure("If we receive a response body, we must have received a head before")
291291

292-
case .executing(let executor, let requestState, .buffering(var buffer, next: let next)):
292+
case .executing(let executor, let requestState, .buffering(var currentBuffer, next: let next)):
293293
guard case .askExecutorForMore = next else {
294294
preconditionFailure("If we have received an error or eof before, why did we get another body part? Next: \(next)")
295295
}
296296

297297
self.state = .modifying
298-
buffer.append(byteBuffer)
299-
self.state = .executing(executor, requestState, .buffering(buffer, next: next))
298+
if currentBuffer.isEmpty {
299+
currentBuffer = buffer
300+
} else {
301+
currentBuffer.append(contentsOf: buffer)
302+
}
303+
self.state = .executing(executor, requestState, .buffering(currentBuffer, next: next))
300304
return nil
301-
case .executing(let executor, let requestState, .waitingForRemote(let buffer)):
302-
assert(buffer.isEmpty, "If we wait for remote, the buffer must be empty")
305+
case .executing(let executor, let requestState, .waitingForRemote):
306+
var buffer = buffer
307+
let first = buffer.removeFirst()
303308
self.state = .executing(executor, requestState, .buffering(buffer, next: .askExecutorForMore))
304-
return byteBuffer
309+
return first
305310
case .redirected:
306311
// ignore body
307312
return nil
@@ -315,30 +320,42 @@ extension RequestBag.StateMachine {
315320
}
316321

317322
enum ReceiveResponseEndAction {
323+
case consume(ByteBuffer)
318324
case redirect(RedirectHandler<Delegate.Response>, HTTPResponseHead, URL)
319325
case succeedRequest
320326
case none
321327
}
322328

323-
mutating func receiveResponseEnd() -> ReceiveResponseEndAction {
329+
mutating func succeedRequest(_ newChunks: CircularBuffer<ByteBuffer>?) -> ReceiveResponseEndAction {
324330
switch self.state {
325331
case .initialized, .queued:
326332
preconditionFailure("How can we receive a response body part, if the request hasn't started yet.")
327333
case .executing(_, _, .initialized):
328334
preconditionFailure("If we receive a response body, we must have received a head before")
329335

330-
case .executing(let executor, let requestState, .buffering(let buffer, next: let next)):
336+
case .executing(let executor, let requestState, .buffering(var buffer, next: let next)):
331337
guard case .askExecutorForMore = next else {
332338
preconditionFailure("If we have received an error or eof before, why did we get another body part? Next: \(next)")
333339
}
334340

341+
if buffer.isEmpty, let newChunks = newChunks {
342+
buffer = newChunks
343+
} else if let newChunks = newChunks {
344+
buffer.append(contentsOf: newChunks)
345+
}
346+
335347
self.state = .executing(executor, requestState, .buffering(buffer, next: .eof))
336348
return .none
337349

338-
case .executing(_, _, .waitingForRemote(let buffer)):
339-
assert(buffer.isEmpty, "If we wait for remote, the buffer must be empty")
340-
self.state = .finished(error: nil)
341-
return .succeedRequest
350+
case .executing(let executor, let requestState, .waitingForRemote):
351+
guard var newChunks = newChunks, !newChunks.isEmpty else {
352+
self.state = .finished(error: nil)
353+
return .succeedRequest
354+
}
355+
356+
let first = newChunks.removeFirst()
357+
self.state = .executing(executor, requestState, .buffering(newChunks, next: .eof))
358+
return .consume(first)
342359

343360
case .redirected(let head, let redirectURL):
344361
self.state = .finished(error: nil)
@@ -421,7 +438,7 @@ extension RequestBag.StateMachine {
421438
}
422439

423440
// buffer is empty, wait for more
424-
self.state = .executing(executor, requestState, .waitingForRemote(buffer))
441+
self.state = .executing(executor, requestState, .waitingForRemote)
425442
return .requestMoreFromExecutor(executor)
426443

427444
case .executing(let executor, let requestState, .buffering(var buffer, next: .eof)):
@@ -482,7 +499,7 @@ extension RequestBag.StateMachine {
482499
case .executing(let executor, _, .initialized):
483500
self.state = .finished(error: error)
484501
return .failTask(nil, executor)
485-
case .executing(let executor, _, .waitingForRemote(_)):
502+
case .executing(let executor, _, .waitingForRemote):
486503
self.state = .finished(error: error)
487504
return .failTask(nil, executor)
488505
case .redirected:

0 commit comments

Comments
 (0)