-
Notifications
You must be signed in to change notification settings - Fork 72
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Introduce GCP PubSub sink (#237)
- Loading branch information
Showing
12 changed files
with
431 additions
and
12 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
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,18 @@ | ||
# Google Cloud PubSub | ||
|
||
A sink that sends each event as a message to a PubSub topic. Each event is json-encoded and sent to a configurable PubSub topic. | ||
|
||
## Configuration | ||
|
||
```toml | ||
[sink] | ||
type = "GcpPubSub" | ||
credentials = "oura-test-347101-ff3f7b2d69cc.json" | ||
topic = "test" | ||
``` | ||
|
||
### Section: `sink` | ||
|
||
- `type`: the literal value `GcpPubSub`. | ||
- `credentials`: the path to the service account json file downloaded from the cloud console. | ||
- `topic`: the short name of the topic to send message to. |
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,7 @@ | ||
use serde::Deserialize; | ||
|
||
#[derive(Debug, Deserialize, Clone)] | ||
pub enum ErrorPolicy { | ||
Continue, | ||
Exit, | ||
} |
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,4 @@ | ||
mod run; | ||
mod setup; | ||
|
||
pub use setup::*; |
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,70 @@ | ||
use std::{sync::Arc, time::Duration}; | ||
|
||
use async_recursion::async_recursion; | ||
use cloud_pubsub::{error::Error, Client, Topic}; | ||
use serde_json::json; | ||
|
||
use crate::{model::Event, pipelining::StageReceiver, sinks::ErrorPolicy, utils::Utils}; | ||
|
||
#[async_recursion] | ||
async fn send_pubsub_msg( | ||
client: &Topic, | ||
event: &Event, | ||
policy: &ErrorPolicy, | ||
retry_quota: usize, | ||
backoff_delay: Duration, | ||
) -> Result<(), Error> { | ||
let body = json!(event).to_string(); | ||
|
||
let result = client.publish(body).await; | ||
|
||
match (result, policy, retry_quota) { | ||
(Ok(_), _, _) => { | ||
log::info!("successful pubsub publish"); | ||
Ok(()) | ||
} | ||
(Err(x), ErrorPolicy::Exit, 0) => Err(x), | ||
(Err(x), ErrorPolicy::Continue, 0) => { | ||
log::warn!("failed to publish to pubsub: {:?}", x); | ||
Ok(()) | ||
} | ||
(Err(x), _, quota) => { | ||
log::warn!("failed attempt to execute pubsub publish: {:?}", x); | ||
std::thread::sleep(backoff_delay); | ||
send_pubsub_msg(client, event, policy, quota - 1, backoff_delay).await | ||
} | ||
} | ||
} | ||
|
||
pub fn writer_loop( | ||
input: StageReceiver, | ||
credentials: String, | ||
topic_name: String, | ||
error_policy: &ErrorPolicy, | ||
max_retries: usize, | ||
backoff_delay: Duration, | ||
utils: Arc<Utils>, | ||
) -> Result<(), crate::Error> { | ||
let rt = tokio::runtime::Builder::new_current_thread() | ||
.enable_time() | ||
.enable_io() | ||
.build()?; | ||
|
||
let publisher = rt.block_on(Client::new(credentials))?; | ||
let topic = publisher.topic(topic_name); | ||
|
||
for event in input.iter() { | ||
// notify the pipeline where we are | ||
utils.track_sink_progress(&event); | ||
|
||
rt.block_on(send_pubsub_msg( | ||
&topic, | ||
&event, | ||
error_policy, | ||
max_retries, | ||
backoff_delay, | ||
))?; | ||
} | ||
|
||
Ok(()) | ||
} |
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,59 @@ | ||
use std::time::Duration; | ||
|
||
use serde::Deserialize; | ||
|
||
use crate::{ | ||
pipelining::{BootstrapResult, SinkProvider, StageReceiver}, | ||
sinks::ErrorPolicy, | ||
utils::WithUtils, | ||
}; | ||
|
||
use super::run::writer_loop; | ||
|
||
#[derive(Debug, Default, Deserialize)] | ||
pub struct Config { | ||
pub topic: String, | ||
pub credentials: String, | ||
pub error_policy: Option<ErrorPolicy>, | ||
pub max_retries: Option<usize>, | ||
pub backoff_delay: Option<u64>, | ||
} | ||
|
||
const DEFAULT_MAX_RETRIES: usize = 20; | ||
const DEFAULT_BACKOFF_DELAY: u64 = 5_000; | ||
|
||
impl SinkProvider for WithUtils<Config> { | ||
fn bootstrap(&self, input: StageReceiver) -> BootstrapResult { | ||
let credentials = self.inner.credentials.to_owned(); | ||
let topic_name = self.inner.topic.to_owned(); | ||
|
||
let error_policy = self | ||
.inner | ||
.error_policy | ||
.as_ref() | ||
.cloned() | ||
.unwrap_or(ErrorPolicy::Exit); | ||
|
||
let max_retries = self.inner.max_retries.unwrap_or(DEFAULT_MAX_RETRIES); | ||
|
||
let backoff_delay = | ||
Duration::from_millis(self.inner.backoff_delay.unwrap_or(DEFAULT_BACKOFF_DELAY)); | ||
|
||
let utils = self.utils.clone(); | ||
|
||
let handle = std::thread::spawn(move || { | ||
writer_loop( | ||
input, | ||
credentials, | ||
topic_name, | ||
&error_policy, | ||
max_retries, | ||
backoff_delay, | ||
utils, | ||
) | ||
.expect("writer loop failed"); | ||
}); | ||
|
||
Ok(handle) | ||
} | ||
} |
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