use serde::{Deserialize, Serialize};
use std::sync::Arc;
use std::time::Duration;
use tokio_util::sync::CancellationToken;
use venturi::postgres::PostgresStore;
use venturi::store::Store;
use venturi::{Context, Handler, Outcome, Task, TaskError, Worker};
#[derive(Clone)]
struct App;
#[derive(Serialize, Deserialize)]
struct SendEmail {
to: String,
subject: String,
}
impl Task for SendEmail {
const KIND: &'static str = "send_email";
type Carry = ();
}
impl Handler<App> for SendEmail {
async fn handle(&self, _ctx: &mut Context<()>, _app: &App) -> Result<Outcome, TaskError> {
println!("sending {:?} to {}", self.subject, self.to);
tokio::time::sleep(Duration::from_millis(100)).await;
Ok(Outcome::completed_with("sent"))
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let dsn = std::env::var("DATABASE_URL").unwrap_or_else(|_| {
"host=localhost user=postgres password=postgres dbname=postgres".to_owned()
});
let store = Arc::new(PostgresStore::connect(&dsn, "venturi")?);
store.migrate().await?;
let worker = Worker::builder(App, store)
.register::<SendEmail>()
.concurrency(8)
.build();
let shutdown = CancellationToken::new();
{
let shutdown = shutdown.clone();
tokio::spawn(async move {
tokio::signal::ctrl_c().await.ok();
shutdown.cancel();
});
}
println!("worker running; press Ctrl-C to stop");
worker.run(shutdown).await;
println!("worker stopped");
Ok(())
}