Skip to content

Commit

Permalink
Work around API issue
Browse files Browse the repository at this point in the history
  • Loading branch information
0xTim committed May 21, 2024
1 parent a3e8acc commit c3da864
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 27 deletions.
26 changes: 1 addition & 25 deletions Sources/Vapor/HTTP/Client/Application+HTTP+Client.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import AsyncHTTPClient

extension Application.Clients.Provider {
@available(*, noasync, message: "Don't use from an async context")
public static var http: Self {
.init {
$0.clients.use {
Expand All @@ -19,7 +18,6 @@ extension Application.HTTP {
public struct Client {
let application: Application

@available(*, noasync, renamed: "asyncShared", message: "Use the async property instead.")
public var shared: HTTPClient {
self.application.locks.lock(for: Key.self).withLock {
if let existing = self.application.storage[Key.self] {
Expand All @@ -30,31 +28,9 @@ extension Application.HTTP {
configuration: self.configuration,
backgroundActivityLogger: self.application.logger
)
self.application.storage.set(Key.self, to: new) {
try $0.syncShutdown()
}
return new
}
}

public var asyncShared: HTTPClient {
get async {
let lock = self.application.locks.lock(for: Key.self)
lock.lock()
if let existing = self.application.storage[Key.self] {
lock.unlock()
return existing
}

let new = HTTPClient(
eventLoopGroupProvider: .shared(self.application.eventLoopGroup),
configuration: self.configuration,
backgroundActivityLogger: self.application.logger
)
await self.application.storage.setWithAsyncShutdown(Key.self, to: new) {
self.application.storage.setFirstTime(Key.self, to: new, onShutdown: { try $0.syncShutdown() }) {
try await $0.shutdown()
}
lock.unlock()
return new
}
}
Expand Down
17 changes: 17 additions & 0 deletions Sources/Vapor/Utilities/Storage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,23 @@ public struct Storage: Sendable {
await existing.asyncShutdown(logger: self.logger)
}
}

// Provides a way to set an async shutdown with an async call to avoid breaking the API
// This must not be called when a value alraedy exists in storage
mutating func setFirstTime<Key>(
_ key: Key.Type,
to value: Key.Value?,
onShutdown: (@Sendable (Key.Value) throws -> ())? = nil,
onAsyncShutdown: (@Sendable (Key.Value) async throws -> ())? = nil
)
where Key: StorageKey
{
let key = ObjectIdentifier(Key.self)
precondition(self.storage[key] == nil, "You must not call this when a value already exists in storage")
if let value {
self.storage[key] = Value(value: value, onShutdown: onShutdown, onAsyncShutdown: onAsyncShutdown)
}
}

/// For every key in the container having a shutdown closure, invoke the closure. Designed to
/// be invoked during an explicit app shutdown process or in a reference type's `deinit`.
Expand Down
4 changes: 2 additions & 2 deletions Tests/VaporTests/AsyncRequestTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ final class AsyncRequestTests: XCTestCase {
request.method = .POST
request.body = .stream(testValue.utf8.async, length: .unknown)

let response: HTTPClientResponse = try await app.http.client.asyncShared.execute(request, timeout: .seconds(5))
let response: HTTPClientResponse = try await app.http.client.shared.execute(request, timeout: .seconds(5))
XCTAssertEqual(response.status, .ok)
let body = try await response.body.collect(upTo: 1024 * 1024)
XCTAssertEqual(body.string, testValue)
Expand Down Expand Up @@ -94,7 +94,7 @@ final class AsyncRequestTests: XCTestCase {
var request = HTTPClientRequest(url: "http://\(ip):\(port)/hello")
request.method = .POST
request.body = .stream(oneMB.async, length: .known(oneMB.count))
if let response = try? await app.http.client.asyncShared.execute(request, timeout: .seconds(5)) {
if let response = try? await app.http.client.shared.execute(request, timeout: .seconds(5)) {
XCTAssertGreaterThan(bytesTheServerRead.load(ordering: .relaxed), 0)
XCTAssertEqual(response.status, .internalServerError)
}
Expand Down

0 comments on commit c3da864

Please sign in to comment.