2022-12-30 16:23:24 +00:00
|
|
|
//! Persistent background jobs using the [`apalis`] crate with a Redis storage backend.
|
|
|
|
|
|
|
|
use std::time::Duration;
|
|
|
|
|
2024-07-12 22:41:00 +03:00
|
|
|
use apalis::prelude::*;
|
|
|
|
use apalis_redis::{Config, RedisStorage};
|
2024-07-07 02:51:12 +01:00
|
|
|
use rand::distributions::{Alphanumeric, DistString as _};
|
2022-12-30 16:23:24 +00:00
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
|
|
|
|
#[derive(Debug, Deserialize, Serialize)]
|
|
|
|
pub(crate) struct Email {
|
|
|
|
to: String,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Email {
|
|
|
|
pub(crate) fn random() -> Self {
|
2024-07-07 02:51:12 +01:00
|
|
|
let user = Alphanumeric.sample_string(&mut rand::thread_rng(), 10);
|
2022-12-30 16:23:24 +00:00
|
|
|
let to = format!("{user}@fake-mail.com");
|
|
|
|
Self { to }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-12 22:41:00 +03:00
|
|
|
async fn process_email_job(job: Email) {
|
2022-12-30 16:23:24 +00:00
|
|
|
log::info!("sending email to {}", &job.to);
|
|
|
|
|
|
|
|
// simulate time taken to send email
|
|
|
|
tokio::time::sleep(rand_delay_with_jitter()).await;
|
|
|
|
}
|
|
|
|
|
2024-07-07 02:51:12 +01:00
|
|
|
pub(crate) async fn start_processing_email_queue() -> eyre::Result<RedisStorage<Email>> {
|
2022-12-30 16:23:24 +00:00
|
|
|
let redis_url = std::env::var("REDIS_URL").expect("Missing env variable REDIS_URL");
|
2024-07-12 22:41:00 +03:00
|
|
|
let conn = apalis_redis::connect(redis_url).await?;
|
|
|
|
let config = Config::default().set_namespace("send_email");
|
|
|
|
let storage = RedisStorage::new_with_config(conn, config);
|
|
|
|
|
|
|
|
// create unmonitored workers for handling emails
|
2024-12-06 03:29:32 +03:00
|
|
|
let worker = WorkerBuilder::new("job-handler")
|
|
|
|
.concurrency(2)
|
2024-07-12 22:41:00 +03:00
|
|
|
.backend(storage.clone())
|
2024-12-06 03:29:32 +03:00
|
|
|
.build_fn(process_email_job);
|
2024-07-12 22:41:00 +03:00
|
|
|
|
2024-12-06 03:29:32 +03:00
|
|
|
#[allow(clippy::let_underscore_future)]
|
|
|
|
let _ = tokio::spawn(worker.run());
|
2022-12-30 16:23:24 +00:00
|
|
|
|
|
|
|
Ok(storage)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns a duration close to 1 second.
|
|
|
|
fn rand_delay_with_jitter() -> Duration {
|
|
|
|
Duration::from_millis(800_u64 + rand::random::<u8>() as u64 * 2)
|
|
|
|
}
|