Skip to content

Commit 181ff65

Browse files
committed
Move postPlausibleEvent to httpClient
1 parent abb8f46 commit 181ff65

File tree

8 files changed

+45
-51
lines changed

8 files changed

+45
-51
lines changed

Sources/App/Core/AppEnvironment.swift

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ struct AppEnvironment: Sendable {
4141
var logger: @Sendable () -> Logger
4242
var metricsPushGatewayUrl: @Sendable () -> String?
4343
var plausibleBackendReportingSiteID: @Sendable () -> String?
44-
var postPlausibleEvent: @Sendable (Client, Plausible.Event.Kind, Plausible.Path, User?) async throws -> Void
4544
var processingBuildBacklog: @Sendable () -> Bool
4645
var runnerIds: @Sendable () -> [String]
4746
var setHTTPClient: @Sendable (Client) -> Void
@@ -65,19 +64,6 @@ struct AppEnvironment: Sendable {
6564
}
6665

6766

68-
extension AppEnvironment {
69-
func postPlausibleEvent(_ event: Plausible.Event.Kind, path: Plausible.Path, user: User?) {
70-
Task {
71-
do {
72-
try await Current.postPlausibleEvent(Current.httpClient(), event, path, user)
73-
} catch {
74-
Current.logger().warning("Plausible.postEvent failed: \(error)")
75-
}
76-
}
77-
}
78-
}
79-
80-
8167
extension AppEnvironment {
8268
nonisolated(unsafe) static var httpClient: Client!
8369
nonisolated(unsafe) static var logger: Logger!
@@ -115,7 +101,6 @@ extension AppEnvironment {
115101
logger: { logger },
116102
metricsPushGatewayUrl: { Environment.get("METRICS_PUSHGATEWAY_URL") },
117103
plausibleBackendReportingSiteID: { Environment.get("PLAUSIBLE_BACKEND_REPORTING_SITE_ID") },
118-
postPlausibleEvent: { client, kind, path, user in try await Plausible.postEvent(client: client, kind: kind, path: path, user: user) },
119104
processingBuildBacklog: {
120105
Environment.get("PROCESSING_BUILD_BACKLOG").flatMap(\.asBool) ?? false
121106
},

Sources/App/Core/BackendReportingMiddleware.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
import Dependencies
1516
import Vapor
1617

1718

@@ -23,7 +24,8 @@ struct BackendReportingMiddleware: AsyncMiddleware {
2324
let response = try await next.respond(to: request)
2425
guard isActive else { return response }
2526
let user = try? request.auth.require(User.self)
26-
Current.postPlausibleEvent(.pageview, path: path, user: user)
27+
@Dependency(\.httpClient) var httpClient
28+
try await httpClient.postPlausibleEvent(kind: .pageview, path: path, user: user)
2729
return response
2830
}
2931
}

Sources/App/Core/Dependencies/EnvironmentClient.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import Vapor
2121
struct EnvironmentClient {
2222
// See https://swiftpackageindex.com/pointfreeco/swift-dependencies/main/documentation/dependenciesmacros/dependencyclient()#Restrictions
2323
// regarding the use of XCTFail here.
24-
// Closures returning optionals or Void don't need this, because they automatically get the default failing
24+
// Closures that are throwing or return Void don't need this, because they automatically get the default failing
2525
// mechanism when they're not set up in a test.
2626
var allowBuildTriggers: @Sendable () -> Bool = { XCTFail("allowBuildTriggers"); return true }
2727
var allowSocialPosts: @Sendable () -> Bool = { XCTFail("allowSocialPosts"); return true }

Sources/App/Core/Dependencies/HTTPClient.swift

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,16 @@ import Vapor
2222
struct HTTPClient {
2323
typealias Response = Vapor.HTTPClient.Response
2424

25-
var fetchDocumentation: @Sendable (_ url: URI) async throws -> Response = { _ in XCTFail("fetchDocumentation"); return .ok }
26-
var fetchHTTPStatusCode: @Sendable (_ url: String) async throws -> HTTPStatus = { _ in XCTFail("fetchHTTPStatusCode"); return .ok }
25+
var client: @Sendable () -> Vapor.HTTPClient = { XCTFail("client"); return .shared }
26+
var fetchDocumentation: @Sendable (_ url: URI) async throws -> Response
27+
var fetchHTTPStatusCode: @Sendable (_ url: String) async throws -> HTTPStatus
28+
var postPlausibleEvent: @Sendable (_ kind: Plausible.Event.Kind, _ path: Plausible.Path, _ user: User?) async throws -> Void
2729
}
2830

2931
extension HTTPClient: DependencyKey {
3032
static var liveValue: HTTPClient {
3133
.init(
34+
client: { .shared },
3235
fetchDocumentation: { url in
3336
try await Vapor.HTTPClient.shared.get(url: url.string).get()
3437
},
@@ -45,6 +48,9 @@ extension HTTPClient: DependencyKey {
4548
} defer: {
4649
try await client.shutdown()
4750
}
51+
},
52+
postPlausibleEvent: { kind, path, user in
53+
try await Plausible.postEvent(kind: kind, path: path, user: user)
4854
}
4955
)
5056
}
@@ -74,6 +80,10 @@ extension HTTPClient {
7480
.init(status: .ok, headers: headers, body: .init(string: url.path))
7581
}
7682
}
83+
84+
static var noop: @Sendable (_ kind: Plausible.Event.Kind, _ path: Plausible.Path, _ user: User?) async throws -> Void {
85+
{ _, _, _ in }
86+
}
7787
}
7888

7989
extension HTTPClient.Response {

Sources/App/Core/Plausible.swift

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,18 +43,22 @@ enum Plausible {
4343
var message: String
4444
}
4545

46-
static let postEventURI = URI(string: "https://plausible.io/api/event")
46+
static let postEventURL = "https://plausible.io/api/event"
4747

48-
static func postEvent(client: Client, kind: Event.Kind, path: Path, user: User?) async throws {
48+
static func postEvent(kind: Event.Kind, path: Path, user: User?) async throws {
49+
#warning("FIXME: need to inject a http client here to so we can test this in PlausibleTests")
4950
guard let siteID = Current.plausibleBackendReportingSiteID() else {
5051
throw Error(message: "PLAUSIBLE_BACKEND_REPORTING_SITE_ID not set")
5152
}
52-
let res = try await client.post(postEventURI, headers: .applicationJSON) { req in
53-
try req.content.encode(Event(name: .pageview,
54-
url: "https://\(siteID)\(path.rawValue)",
55-
domain: siteID,
56-
props: user.props))
57-
}
53+
let data = try JSONEncoder().encode(Event(name: .pageview,
54+
url: "https://\(siteID)\(path.rawValue)",
55+
domain: siteID,
56+
props: user.props))
57+
let req = try Vapor.HTTPClient.Request(url: postEventURL,
58+
method: .POST,
59+
headers: .applicationJSON,
60+
body: .data(data))
61+
let res = try await Vapor.HTTPClient.shared.execute(request: req).get()
5862
guard res.status.succeeded else {
5963
throw Error(message: "Request failed with status code: \(res.status)")
6064
}

Tests/AppTests/ApiTests.swift

Lines changed: 15 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class ApiTests: AppTestCase {
3232
func test_search_noQuery() throws {
3333
try withDependencies {
3434
$0.environment.apiSigningKey = { "secret" }
35+
$0.httpClient.postPlausibleEvent = App.HTTPClient.noop
3536
} operation: {
3637
// MUT
3738
try app.test(.GET, "api/search",
@@ -48,8 +49,12 @@ class ApiTests: AppTestCase {
4849
}
4950

5051
func test_search_basic_param() async throws {
52+
let event = App.ActorIsolated<TestEvent?>(nil)
5153
try await withDependencies {
5254
$0.environment.apiSigningKey = { "secret" }
55+
$0.httpClient.postPlausibleEvent = { @Sendable kind, path, _ in
56+
await event.setValue(.init(kind: kind, path: path))
57+
}
5358
} operation: {
5459
let p1 = Package(id: .id0, url: "1")
5560
try await p1.save(on: app.db)
@@ -69,11 +74,6 @@ class ApiTests: AppTestCase {
6974
try await Version(package: p2, packageName: "Bar", reference: .branch("main")).save(on: app.db)
7075
try await Search.refresh(on: app.db)
7176

72-
let event = App.ActorIsolated<TestEvent?>(nil)
73-
Current.postPlausibleEvent = { @Sendable _, kind, path, _ in
74-
await event.setValue(.init(kind: kind, path: path))
75-
}
76-
7777
// MUT
7878
try await app.test(.GET, "api/search?query=foo%20bar",
7979
headers: .bearerApplicationJSON(try .apiToken(secretKey: "secret", tier: .tier1)),
@@ -765,6 +765,7 @@ class ApiTests: AppTestCase {
765765
}
766766

767767
func test_get_badge() async throws {
768+
// sas 2024-12-20: Badges are not reporting plausbile events, because they triggered way too many events. (This is an old changes, just adding this comment today as I'm removing the old, commented out test remnants we still had in place.)
768769
// setup
769770
let owner = "owner"
770771
let repo = "repo"
@@ -782,11 +783,6 @@ class ApiTests: AppTestCase {
782783
try await Build(version: v, platform: .macosXcodebuild, status: .ok, swiftVersion: .v1)
783784
.save(on: app.db)
784785

785-
let event = App.ActorIsolated<TestEvent?>(nil)
786-
Current.postPlausibleEvent = { @Sendable _, kind, path, _ in
787-
await event.setValue(.init(kind: kind, path: path))
788-
}
789-
790786
// MUT - swift versions
791787
try await app.test(
792788
.GET,
@@ -822,21 +818,20 @@ class ApiTests: AppTestCase {
822818
XCTAssertEqual(badge.cacheSeconds, 6*3600)
823819
XCTAssertNotNil(badge.logoSvg)
824820
})
825-
826-
// ensure API event has been reported
827-
// API reporting for badges is currently disabled, because it is very noisy
828-
// await event.withValue {
829-
// XCTAssertEqual($0, .some(.init(kind: .pageview, path: .badge)))
830-
// }
831821
}
832822

833823
func test_package_collections_owner() async throws {
834824
try XCTSkipIf(!isRunningInCI && EnvironmentClient.liveValue.collectionSigningPrivateKey() == nil, "Skip test for local user due to unset COLLECTION_SIGNING_PRIVATE_KEY env variable")
825+
826+
let event = App.ActorIsolated<TestEvent?>(nil)
835827
try await withDependencies {
836828
$0.date.now = .t0
837829
$0.environment.apiSigningKey = { "secret" }
838830
$0.environment.collectionSigningCertificateChain = EnvironmentClient.liveValue.collectionSigningCertificateChain
839831
$0.environment.collectionSigningPrivateKey = EnvironmentClient.liveValue.collectionSigningPrivateKey
832+
$0.httpClient.postPlausibleEvent = { @Sendable kind, path, _ in
833+
await event.setValue(.init(kind: kind, path: path))
834+
}
840835
} operation: {
841836
// setup
842837
let p1 = Package(id: .id1, url: "1")
@@ -855,11 +850,6 @@ class ApiTests: AppTestCase {
855850
try await Product(version: v, type: .library(.automatic), name: "lib")
856851
.save(on: app.db)
857852

858-
let event = App.ActorIsolated<TestEvent?>(nil)
859-
Current.postPlausibleEvent = { @Sendable _, kind, path, _ in
860-
await event.setValue(.init(kind: kind, path: path))
861-
}
862-
863853
do { // MUT
864854
let body: ByteBuffer = .init(string: """
865855
{
@@ -901,12 +891,14 @@ class ApiTests: AppTestCase {
901891

902892
func test_package_collections_packageURLs() async throws {
903893
try XCTSkipIf(!isRunningInCI && EnvironmentClient.liveValue.collectionSigningPrivateKey() == nil, "Skip test for local user due to unset COLLECTION_SIGNING_PRIVATE_KEY env variable")
894+
904895
let refDate = Date(timeIntervalSince1970: 0)
905896
try await withDependencies {
906897
$0.date.now = refDate
907898
$0.environment.apiSigningKey = { "secret" }
908899
$0.environment.collectionSigningCertificateChain = EnvironmentClient.liveValue.collectionSigningCertificateChain
909900
$0.environment.collectionSigningPrivateKey = EnvironmentClient.liveValue.collectionSigningPrivateKey
901+
$0.httpClient.postPlausibleEvent = App.HTTPClient.noop
910902
} operation: {
911903
// setup
912904
let p1 = Package(id: UUID(uuidString: "442cf59f-0135-4d08-be00-bc9a7cebabd3")!,
@@ -1049,6 +1041,7 @@ class ApiTests: AppTestCase {
10491041
try await withDependencies {
10501042
$0.environment.apiSigningKey = { "secret" }
10511043
$0.environment.dbId = { nil }
1044+
$0.httpClient.postPlausibleEvent = App.HTTPClient.noop
10521045
} operation: {
10531046
let owner = "owner"
10541047
let repo = "repo"
@@ -1112,6 +1105,7 @@ class ApiTests: AppTestCase {
11121105
func test_dependencies_get() async throws {
11131106
try await withDependencies {
11141107
$0.environment.apiSigningKey = { "secret" }
1108+
$0.httpClient.postPlausibleEvent = App.HTTPClient.noop
11151109
} operation: {
11161110
let pkg = try await savePackage(on: app.db, id: .id0, "http://github.com/foo/bar")
11171111
try await Repository(package: pkg,

Tests/AppTests/Mocks/AppEnvironment+mock.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ extension AppEnvironment {
4040
logger: { logger },
4141
metricsPushGatewayUrl: { "http://pushgateway:9091" },
4242
plausibleBackendReportingSiteID: { nil },
43-
postPlausibleEvent: { _, _, _, _ in },
4443
processingBuildBacklog: { false },
4544
runnerIds: { [] },
4645
setHTTPClient: { client in Self.httpClient = client },

Tests/AppTests/PlausibleTests.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ final class PlausibleTests: XCTestCase {
4343
}
4444

4545
// MUT
46-
_ = try await Plausible.postEvent(client: client, kind: .pageview, path: .search, user: nil)
46+
_ = try await Plausible.postEvent(kind: .pageview, path: .search, user: nil)
4747

4848
XCTAssertTrue(called)
4949
}
@@ -64,7 +64,7 @@ final class PlausibleTests: XCTestCase {
6464
}
6565

6666
// MUT
67-
_ = try await Plausible.postEvent(client: client, kind: .pageview, path: .package, user: user)
67+
_ = try await Plausible.postEvent(kind: .pageview, path: .package, user: user)
6868

6969
XCTAssertTrue(called)
7070
}

0 commit comments

Comments
 (0)