use async_trait::async_trait;
use alun_core::{Plugin, Result};
use std::sync::Arc;
use tokio::sync::Semaphore;
pub struct AsyncTaskPlugin {
workers: usize,
semaphore: Arc<Semaphore>,
running: Arc<parking_lot::Mutex<bool>>,
}
impl AsyncTaskPlugin {
pub fn new(workers: usize) -> Self {
let w = if workers == 0 { 4 } else { workers };
Self {
workers: w,
semaphore: Arc::new(Semaphore::new(w)),
running: Arc::new(parking_lot::Mutex::new(false)),
}
}
pub async fn submit<F>(&self, task: F)
where
F: std::future::Future<Output = ()> + Send + 'static,
{
let sem = self.semaphore.clone();
tokio::spawn(async move {
let _permit = sem.acquire().await.expect("AsyncTask semaphore 异常");
task.await;
});
}
pub fn worker_count(&self) -> usize { self.workers }
}
#[async_trait]
impl Plugin for AsyncTaskPlugin {
fn name(&self) -> &str { "async-task" }
async fn start(&self) -> Result<()> {
*self.running.lock() = true;
tracing::info!("异步任务插件: workers={} 已就绪", self.workers);
Ok(())
}
async fn stop(&self) -> Result<()> {
*self.running.lock() = false;
tracing::info!("异步任务插件: 等待任务完成...");
let _permits = self.semaphore.acquire_many(self.workers as u32).await;
Ok(())
}
}