-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #31 from Clearcals/susheel/master/pubsub_setup
Added support for Google PubSub
- Loading branch information
Showing
4 changed files
with
188 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
// | ||
// 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 CloudPubSubConfigurationKey: StorageKey { | ||
typealias Value = GoogleCloudPubSubConfiguration | ||
} | ||
|
||
private struct CloudSPubSubHTTPClientKey: StorageKey, LockKey { | ||
typealias Value = HTTPClient | ||
} | ||
|
||
public 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 | ||
|
||
/// 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: GoogleCloudPubSubConfiguration { | ||
get { | ||
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[CloudPubSubConfigurationKey.self] == nil { | ||
application.storage[CloudPubSubConfigurationKey.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 `GoogleCloudPubSub` 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 | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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? | ||
} | ||
``` | ||
|