use std::future::Future;
use std::time::Duration;
use sqlx::PgPool;
use crate::error::{OutboxError, Result};
use crate::record::OutboxRecord;
use crate::relay;
#[derive(Debug, Clone)]
pub struct RelayConfig {
pub schema: String,
pub batch: i64,
pub poll_interval: Duration,
}
impl RelayConfig {
pub fn new(schema: impl Into<String>) -> Self {
Self { schema: schema.into(), batch: 100, poll_interval: Duration::from_secs(1) }
}
}
pub async fn run<F, Fut, S>(pool: PgPool, cfg: RelayConfig, publish: F, shutdown: S) -> Result<()>
where
F: Fn(OutboxRecord) -> Fut,
Fut: Future<Output = std::result::Result<(), OutboxError>>,
S: Future<Output = ()>,
{
tokio::pin!(shutdown);
loop {
tokio::select! {
biased;
_ = &mut shutdown => return Ok(()),
res = relay::drain_once(&pool, &cfg.schema, cfg.batch, &publish) => {
let delivered = res?;
if (delivered as i64) < cfg.batch {
tokio::select! {
biased;
_ = &mut shutdown => return Ok(()),
_ = tokio::time::sleep(cfg.poll_interval) => {}
}
}
}
}
}
}