use chrono::{prelude::*, Duration}; // use once_cell::sync::Lazy; use sqlx::{postgres::PgPoolOptions, PgPool, Pool, Postgres}; use std::env; mod tasks; pub struct TaskManager<'a> { pool: Pool<Postgres>, jobs: Vec<TaskJob>, last_activated: Option<chrono::DateTime<Utc>>, last_job: Option<TaskJob>, scheduler: job_scheduler::JobScheduler<'a>, } pub struct TaskLog { task_log_id: u8, task_id: u8, created_at: chrono::DateTime<Utc>, task_status: TaskStatus, } enum TaskStatus { Pending, Completed, Failed, } #[derive(Debug, sqlx::FromRow)] pub struct TaskJob { pub task_id: i32, pub task_name: String, pub schedule: String, pub is_active: bool, pub created_at: chrono::DateTime<Utc>, pub deleted_at: Option<chrono::DateTime<Utc>>, } #[tokio::main] async fn main() { println!("Hello, world!"); dotenvy::dotenv().unwrap(); let database_url = env::var("DATABASE_URL").expect("Environment variable DATABASE_URL is not found"); let pool = PgPoolOptions::new() .max_connections(10) .connect(&database_url) .await .expect("Failed to connect to the database"); let mut manager = TaskManager::new(pool); manager.register_jobs().await; loop { manager.scheduler.tick(); std::thread::sleep(std::time::Duration::from_millis(1000)); } } impl<'a> TaskManager<'a> { fn new(pool: Pool<Postgres>) -> Self { TaskManager { pool, jobs: Vec::new(), last_activated: None, last_job: None, scheduler: job_scheduler::JobScheduler::new(), } } pub async fn register_jobs(&self) { // let jobs: Vec<Job> = Vec::new(); let results = sqlx::query_as::<_, TaskJob>("SELECT task_id, task_name, schedule, is_active, created_at, deleted_at FROM tasks WHERE is_active = true AND deleted_at IS NULL") .fetch_all(&self.pool) .await .unwrap(); let mut scheduler = job_scheduler::JobScheduler::new(); results .iter() .map(|j| { scheduler.add(job_scheduler::Job::new(j.schedule.parse().unwrap(), || { println!("Starting task name: {:?}", j.task_name); match j.task_id { 1 => tasks::import_posts::import_posts("/app", &self.pool), _ => panic!(), } })); }) .collect::<Vec<_>>(); } }