From f7d80df6bcecef605ac440acdde70c9299eb8828 Mon Sep 17 00:00:00 2001 From: Susheel Athmakuri Date: Sun, 20 Jun 2021 17:22:25 -0700 Subject: [PATCH 1/8] Added pubsub --- Package.swift | 2 +- .../CloudPubSub/GoogleCloudPubSubAPI.swift | 96 +++++++++++++++++++ 2 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 Sources/CloudPubSub/GoogleCloudPubSubAPI.swift diff --git a/Package.swift b/Package.swift index 04d5f51..de4fcda 100644 --- a/Package.swift +++ b/Package.swift @@ -26,7 +26,7 @@ let package = Package( ], dependencies: [ .package(url: "https://github.com/vapor/vapor.git", from: "4.0.0"), - .package(url: "https://github.com/vapor-community/google-cloud-kit.git", from: "1.0.0-rc") + .package(url: "git@github.com:Clearcals/google-cloud-kit.git", .branch("susheel/master/pubsub_setup")) ], targets: [ .target( diff --git a/Sources/CloudPubSub/GoogleCloudPubSubAPI.swift b/Sources/CloudPubSub/GoogleCloudPubSubAPI.swift new file mode 100644 index 0000000..7c50cd6 --- /dev/null +++ b/Sources/CloudPubSub/GoogleCloudPubSubAPI.swift @@ -0,0 +1,96 @@ +// +// GoogleCloudPubSubAPI.swift +// +// +// Created by Susheel Athmakuri on 6/20/21. +// + +import Vapor +@_exported import PubSub +@_exported import GoogleCloud + +extension Application.GoogleCloudPlatform { + private struct CloudPubSubAPIKey: StorageKey { + typealias Value = GoogleCloudPubSubAPI + } + + private struct CloudSPubSubConfigurationKey: StorageKey { + typealias Value = GoogleCloudPubSubConfiguration + } + + private struct CloudSPubSubHTTPClientKey: StorageKey, LockKey { + typealias Value = HTTPClient + } + + public struct GoogleCloudPubSubAPI { + public let application: Application + public let eventLoop: EventLoop + + /// A client used to interact with the `GoogleCloudPubSub` API. + public var client: GoogleCloudPubSubClient { + do { + let new = try GoogleCloudPubSubClient(credentials: self.application.googleCloud.credentials, config: self.configuration, httpClient: self.http, eventLoop: self.eventLoop) + return new + } catch { + fatalError("\(error.localizedDescription)") + } + } + + /// The configuration for using `GoogleCloudPubSub` APIs. + public var configuration: GoogleCloudStorageConfiguration { + get { + if let configuration = application.storage[CloudSPubSubConfigurationKey.self] { + return configuration + } else { + fatalError("Cloud PubSub configuration has not been set. Use app.googleCloud.pubsub.configuration = ...") + } + } + set { + if application.storage[CloudSPubSubConfigurationKey.self] == nil { + application.storage[CloudSPubSubConfigurationKey.self] = newValue + } else { + fatalError("Attempting to override credentials configuration after being set is not allowed.") + } + } + } + + /// Custom `HTTPClient` that ignores unclean SSL shutdown. + public var http: HTTPClient { + if let existing = application.storage[CloudSPubSubHTTPClientKey.self] { + return existing + } else { + let lock = application.locks.lock(for: CloudSPubSubHTTPClientKey.self) + lock.lock() + defer { lock.unlock() } + if let existing = application.storage[CloudSPubSubHTTPClientKey.self] { + return existing + } + let new = HTTPClient( + eventLoopGroupProvider: .shared(application.eventLoopGroup), + configuration: HTTPClient.Configuration(ignoreUncleanSSLShutdown: true) + ) + application.storage.set(CloudSPubSubHTTPClientKey.self, to: new) { + try $0.syncShutdown() + } + return new + } + } + } +} + +extension Request { + private struct GoogleCloudPubSubKey: StorageKey { + typealias Value = GoogleCloudPubSubClient + } + + /// A client used to interact with the `GoogleCloudTranslation` API + public var gcPubSub: GoogleCloudPubSubClient { + if let existing = application.storage[GoogleCloudPubSubKey.self] { + return existing.hopped(to: self.eventLoop) + } else { + let new = Application.GoogleCloudPlatform.GoogleCloudPubSubAPI(application: self.application, eventLoop: self.eventLoop).client + application.storage[GoogleCloudPubSubKey.self] = new + return new + } + } +} From 1e4a37b1c703917fd3d6efb3ac44bc4ae9b1cc36 Mon Sep 17 00:00:00 2001 From: Susheel Athmakuri Date: Sun, 20 Jun 2021 17:27:28 -0700 Subject: [PATCH 2/8] Added PubSub library target --- Package.swift | 10 ++++++++++ Sources/CloudPubSub/GoogleCloudPubSubAPI.swift | 10 +++++----- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/Package.swift b/Package.swift index de4fcda..f87b660 100644 --- a/Package.swift +++ b/Package.swift @@ -23,6 +23,9 @@ let package = Package( .library( name: "CloudTranslation", targets: ["CloudTranslation"]), + .library( + name: "CloudPubSub", + targets: ["CloudPubSub"]), ], dependencies: [ .package(url: "https://github.com/vapor/vapor.git", from: "4.0.0"), @@ -64,5 +67,12 @@ let package = Package( .product(name: "GoogleCloudTranslation", package: "google-cloud-kit"), .target(name: "GoogleCloud") ]), + .target( + name: "CloudPubSub", + dependencies: [ + .product(name: "Vapor", package: "vapor"), + .product(name: "GoogleCloudPubSub", package: "google-cloud-kit"), + .target(name: "GoogleCloud") + ]), ] ) diff --git a/Sources/CloudPubSub/GoogleCloudPubSubAPI.swift b/Sources/CloudPubSub/GoogleCloudPubSubAPI.swift index 7c50cd6..aed43ce 100644 --- a/Sources/CloudPubSub/GoogleCloudPubSubAPI.swift +++ b/Sources/CloudPubSub/GoogleCloudPubSubAPI.swift @@ -14,7 +14,7 @@ extension Application.GoogleCloudPlatform { typealias Value = GoogleCloudPubSubAPI } - private struct CloudSPubSubConfigurationKey: StorageKey { + private struct CloudPubSubConfigurationKey: StorageKey { typealias Value = GoogleCloudPubSubConfiguration } @@ -37,17 +37,17 @@ extension Application.GoogleCloudPlatform { } /// The configuration for using `GoogleCloudPubSub` APIs. - public var configuration: GoogleCloudStorageConfiguration { + public var configuration: GoogleCloudPubSubConfiguration { get { - if let configuration = application.storage[CloudSPubSubConfigurationKey.self] { + if let configuration = application.storage[CloudPubSubConfigurationKey.self] { return configuration } else { fatalError("Cloud PubSub configuration has not been set. Use app.googleCloud.pubsub.configuration = ...") } } set { - if application.storage[CloudSPubSubConfigurationKey.self] == nil { - application.storage[CloudSPubSubConfigurationKey.self] = newValue + if application.storage[CloudPubSubConfigurationKey.self] == nil { + application.storage[CloudPubSubConfigurationKey.self] = newValue } else { fatalError("Attempting to override credentials configuration after being set is not allowed.") } From 2e749c54089e09485aac284b3c810f4414ba9877 Mon Sep 17 00:00:00 2001 From: Susheel Athmakuri Date: Sun, 20 Jun 2021 18:32:59 -0700 Subject: [PATCH 3/8] Attach pubsub to application --- Sources/CloudPubSub/GoogleCloudPubSubAPI.swift | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Sources/CloudPubSub/GoogleCloudPubSubAPI.swift b/Sources/CloudPubSub/GoogleCloudPubSubAPI.swift index aed43ce..7fbd3c6 100644 --- a/Sources/CloudPubSub/GoogleCloudPubSubAPI.swift +++ b/Sources/CloudPubSub/GoogleCloudPubSubAPI.swift @@ -22,6 +22,21 @@ extension Application.GoogleCloudPlatform { typealias Value = HTTPClient } + private var pubsub: GoogleCloudPubSubAPI { + get { + if let existing = self.application.storage[CloudPubSubAPIKey.self] { + return existing + } else { + return .init(application: self.application, + eventLoop: self.application.eventLoopGroup.next()) + } + } + + nonmutating set { + self.application.storage[CloudPubSubAPIKey.self] = newValue + } + } + public struct GoogleCloudPubSubAPI { public let application: Application public let eventLoop: EventLoop From 7f87630e00fe8d1ddd13df153ad3139014e52aea Mon Sep 17 00:00:00 2001 From: Susheel Athmakuri Date: Sun, 20 Jun 2021 18:35:24 -0700 Subject: [PATCH 4/8] Minor fix --- Sources/CloudPubSub/GoogleCloudPubSubAPI.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/CloudPubSub/GoogleCloudPubSubAPI.swift b/Sources/CloudPubSub/GoogleCloudPubSubAPI.swift index 7fbd3c6..02e9feb 100644 --- a/Sources/CloudPubSub/GoogleCloudPubSubAPI.swift +++ b/Sources/CloudPubSub/GoogleCloudPubSubAPI.swift @@ -22,7 +22,7 @@ extension Application.GoogleCloudPlatform { typealias Value = HTTPClient } - private var pubsub: GoogleCloudPubSubAPI { + public var pubsub: GoogleCloudPubSubAPI { get { if let existing = self.application.storage[CloudPubSubAPIKey.self] { return existing From 4cf497cf589ba9ed340937cc289b3d16bdf013fe Mon Sep 17 00:00:00 2001 From: Susheel Athmakuri Date: Wed, 23 Jun 2021 13:49:45 -0700 Subject: [PATCH 5/8] Added readme --- .../CloudPubSub/GoogleCloudPubSubAPI.swift | 2 +- Sources/CloudPubSub/README.md | 64 +++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 Sources/CloudPubSub/README.md diff --git a/Sources/CloudPubSub/GoogleCloudPubSubAPI.swift b/Sources/CloudPubSub/GoogleCloudPubSubAPI.swift index 02e9feb..78aa018 100644 --- a/Sources/CloudPubSub/GoogleCloudPubSubAPI.swift +++ b/Sources/CloudPubSub/GoogleCloudPubSubAPI.swift @@ -98,7 +98,7 @@ extension Request { typealias Value = GoogleCloudPubSubClient } - /// A client used to interact with the `GoogleCloudTranslation` API + /// A client used to interact with the `GoogleCloudPubSub` API public var gcPubSub: GoogleCloudPubSubClient { if let existing = application.storage[GoogleCloudPubSubKey.self] { return existing.hopped(to: self.eventLoop) diff --git a/Sources/CloudPubSub/README.md b/Sources/CloudPubSub/README.md new file mode 100644 index 0000000..6094072 --- /dev/null +++ b/Sources/CloudPubSub/README.md @@ -0,0 +1,64 @@ +# GoogleCloudPubSubAPI + +## Getting Started +If you only need to use the [Google Cloud PubSub API](https://cloud.google.com/pubsub), then this guide will help you get started. + +In your `Package.swift` file, make sure you have the following dependencies and targets + +```swift +dependencies: [ + //... + .package(url: "https://github.com/vapor-community/google-cloud.git", from: "1.0.0"), + ], + targets: [ + .target(name: "MyAppName", dependencies: [ + //... + .product(name: "CloudPubSub", package: "google-cloud"), + ]), + ] +``` + +Now you can setup the configuration for any GCP API globally via `Application`. + +In `configure.swift` + +```swift +import CloudPubSub + + app.googleCloud.credentials = try GoogleCloudCredentialsConfiguration(projectId: "myprojectid-12345", + credentialsFile: "~/path/to/service-account.json") +``` +Next we setup the CloudlPubSub API configuration (specific to this API). + +```swift +app.googleCloud.pubsub.configuration = .default() +``` + +Now we can start using the GoogleCloudPubSub API +There's a handy extension on `Request` that you can use to get access to a pubsub client via a property named `gcPubsub`. + +```swift +func publishMessage(_ req: Request) throws -> EventLoopFuture<[String]> { + guard let topicId = req.parameters.get("topicId") else { + throw Abort(.badRequest, reason:"Missing Topic ID from the request") + } + + try PubSubMessage.validate(content: req) + let message = try req.content.decode(PubSubMessage.self) + + return req.gcPubSub.pubSubTopic.publish(topicId: topicId, + data: message.data, + attributes: nil, + orderingKey: nil) + .map { response in + return response.messageIds + } +} + +struct PubSubMessage: Content { + let data: String + let attributes: [String: String]? + let orderingKey: String? +} +``` + From e0b7a1c1b0a482415b88ea829e5c1d77c70eb810 Mon Sep 17 00:00:00 2001 From: Susheel Athmakuri Date: Wed, 23 Jun 2021 13:53:45 -0700 Subject: [PATCH 6/8] Updated read me with pubsub read me reference --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index f16d0e7..c9cf95c 100644 --- a/README.md +++ b/README.md @@ -26,5 +26,7 @@ You can check each supported API's README for a getting started guide. [x] [CloudTranslation](/Sources/CloudTranslation/README.md) +[x] [CloudPubSub](/Sources/CloudPubSub/README.md) + ### A More detailed guide can be found [here](https://github.com/vapor-community/google-cloud-kit). From c357c7a638ed401aa44b870c0a9fa0b74a0a16f1 Mon Sep 17 00:00:00 2001 From: Susheel Athmakuri Date: Mon, 28 Jun 2021 22:23:03 -0700 Subject: [PATCH 7/8] Update Package.swift --- Package.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Package.swift b/Package.swift index f87b660..8d9d7d9 100644 --- a/Package.swift +++ b/Package.swift @@ -29,7 +29,7 @@ let package = Package( ], dependencies: [ .package(url: "https://github.com/vapor/vapor.git", from: "4.0.0"), - .package(url: "git@github.com:Clearcals/google-cloud-kit.git", .branch("susheel/master/pubsub_setup")) + .package(url: "git@github.com:Clearcals/google-cloud-kit.git", .branch("master")) ], targets: [ .target( From 7d2c7176c776dd529a4538ab4718f5b18a0a03c4 Mon Sep 17 00:00:00 2001 From: Susheel Athmakuri Date: Wed, 4 Aug 2021 05:55:54 +0530 Subject: [PATCH 8/8] Update Package.swift --- Package.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Package.swift b/Package.swift index 8d9d7d9..5b45a71 100644 --- a/Package.swift +++ b/Package.swift @@ -29,7 +29,7 @@ let package = Package( ], dependencies: [ .package(url: "https://github.com/vapor/vapor.git", from: "4.0.0"), - .package(url: "git@github.com:Clearcals/google-cloud-kit.git", .branch("master")) + .package(url: "https://github.com/vapor-community/google-cloud-kit.git", from: "1.0.0-rc.7") ], targets: [ .target(