#[cfg(feature = "jobs")]
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use tideway::{
App, AppContext, ConfigBuilder, InMemoryJobQueue, Job, JobQueue, JobRegistry, Result,
TidewayError,
};
tideway::init_tracing();
#[derive(Debug, Serialize, Deserialize)]
struct SendEmailJob {
to: String,
subject: String,
body: String,
}
#[async_trait]
impl Job for SendEmailJob {
fn job_type(&self) -> &str {
"send_email"
}
fn serialize(&self) -> Result<serde_json::Value> {
serde_json::to_value(self)
.map_err(|e| TidewayError::internal(format!("Failed to serialize job: {}", e)))
}
async fn execute(&self, _ctx: &tideway::AppContext) -> Result<()> {
tracing::info!(
to = %self.to,
subject = %self.subject,
"Processing email job"
);
tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
tracing::info!("Email sent successfully");
Ok(())
}
}
let queue = Arc::new(InMemoryJobQueue::new(3, 60));
let registry = Arc::new(JobRegistry::new());
registry
.register("send_email", |data, ctx| {
Box::pin(async move {
let job: SendEmailJob = serde_json::from_value(data.payload).map_err(|e| {
TidewayError::internal(format!("Failed to deserialize job: {}", e))
})?;
job.execute(&ctx).await
})
})
.await;
let ctx = AppContext::builder().with_job_queue(queue.clone()).build();
let config = ConfigBuilder::new().with_log_level("info").build()?;
let app = App::with_config(config)
.with_context(ctx)
.start_workers(registry);
let job1 = SendEmailJob {
to: "user1@example.com".to_string(),
subject: "Welcome!".to_string(),
body: "Thanks for signing up.".to_string(),
};
let job2 = SendEmailJob {
to: "user2@example.com".to_string(),
subject: "Reminder".to_string(),
body: "Don't forget about our meeting.".to_string(),
};
let job_id1 = queue.enqueue(&job1).await?;
let job_id2 = queue.enqueue(&job2).await?;
tracing::info!(job_id = %job_id1, "Enqueued job 1");
tracing::info!(job_id = %job_id2, "Enqueued job 2");
println!("Background jobs example started!");
println!("Two email jobs have been enqueued.");
println!("Workers will process them in the background.");
println!("Press Ctrl+C to stop...");
app.serve().await?;
Ok(())
}
#[cfg(not(feature = "jobs"))]
fn main() {
println!("This example requires the 'jobs' feature to be enabled.");
println!("Run with: cargo run --example background_jobs --features jobs");
}