use std::sync::RwLock;
use async_trait::async_trait;
use boson_core::{
Job, JobEnqueueDisposition, JobStatus, QueueBackend, Result, Run, RunStatus, TaskConfig,
TaskRunStats,
};
use chrono::{DateTime, Utc};
use crate::enqueue_rate::EnqueueRateLimiter;
use crate::store::{read, write, write_fallible, Inner};
#[derive(Debug)]
pub struct MemQueueBackend {
inner: RwLock<Inner>,
enqueue_rate: EnqueueRateLimiter,
}
impl Default for MemQueueBackend {
fn default() -> Self {
Self::new()
}
}
impl MemQueueBackend {
#[must_use]
pub fn new() -> Self {
Self {
inner: RwLock::new(Inner::new()),
enqueue_rate: EnqueueRateLimiter::new(),
}
}
}
#[async_trait]
impl QueueBackend for MemQueueBackend {
async fn upsert_job(&self, job: &Job) -> Result<()> {
write(&self.inner, |inner| crate::jobs::upsert_job(inner, job))
}
async fn enqueue_with_policies(
&self,
job: Job,
task_config: &TaskConfig,
) -> Result<(String, JobEnqueueDisposition)> {
write_fallible(&self.inner, |inner| {
crate::jobs::enqueue_with_policies(inner, &self.enqueue_rate, &job, task_config)
})
}
async fn get_job(&self, job_id: &str) -> Result<Option<Job>> {
read(&self.inner, |inner| crate::jobs::get_job(inner, job_id))
}
async fn list_jobs(
&self,
status_filter: Option<JobStatus>,
offset: usize,
limit: usize,
) -> Result<Vec<Job>> {
read(&self.inner, |inner| {
crate::jobs::list_jobs(inner, status_filter, offset, limit)
})
}
async fn cancel_job_if_active(&self, job_id: &str) -> Result<()> {
write_fallible(&self.inner, |inner| crate::jobs::cancel_job_if_active(inner, job_id))
}
async fn try_claim_job(&self, job_id: &str) -> Result<Option<Job>> {
write(&self.inner, |inner| crate::jobs::try_claim_job(inner, job_id))
}
async fn revert_job_to_queued(&self, job_id: &str) -> Result<()> {
write(&self.inner, |inner| crate::jobs::revert_job_to_queued(inner, job_id))
}
async fn distinct_pools_queued(&self) -> Result<Vec<String>> {
read(&self.inner, crate::jobs::distinct_pools_queued)
}
async fn list_queued_for_pool_sorted(
&self,
pool: &str,
limit: usize,
) -> Result<Vec<Job>> {
read(&self.inner, |inner| {
crate::jobs::list_queued_for_pool_sorted(inner, pool, limit)
})
}
async fn pop_claim_from_pool(&self, pool: &str) -> Result<Option<Job>> {
write(&self.inner, |inner| crate::jobs::pop_claim_from_pool(inner, pool))
}
async fn count_jobs(&self, status_filter: Option<JobStatus>) -> Result<u64> {
read(&self.inner, |inner| crate::jobs::count_jobs(inner, status_filter))
}
async fn count_jobs_for_task(
&self,
task_name: &str,
status: Option<JobStatus>,
) -> Result<u64> {
read(&self.inner, |inner| {
crate::jobs::count_jobs_for_task(inner, task_name, status)
})
}
async fn count_active_jobs_for_task(&self, task_name: &str) -> Result<u32> {
read(&self.inner, |inner| {
crate::jobs::count_active_jobs_for_task(inner, task_name)
})
}
async fn find_nonterminal_by_idempotency_key(&self, key: &str) -> Result<Option<String>> {
read(&self.inner, |inner| {
crate::jobs::find_nonterminal_by_idempotency_key(inner, key)
})
}
async fn upsert_run(&self, run: &Run) -> Result<()> {
write(&self.inner, |inner| crate::runs::upsert_run(inner, run))
}
async fn get_run(&self, run_id: &str) -> Result<Option<Run>> {
read(&self.inner, |inner| crate::runs::get_run(inner, run_id))
}
async fn list_runs(
&self,
job_id_filter: Option<&str>,
offset: usize,
limit: usize,
) -> Result<Vec<Run>> {
read(&self.inner, |inner| {
crate::runs::list_runs(inner, job_id_filter, offset, limit)
})
}
async fn finish_run(
&self,
run_id: &str,
status: RunStatus,
duration_ms: Option<i64>,
error_message: Option<String>,
) -> Result<()> {
write(&self.inner, |inner| {
crate::runs::finish_run(inner, run_id, status, duration_ms, error_message);
})
}
async fn count_runs(&self, job_id_filter: Option<&str>) -> Result<u64> {
read(&self.inner, |inner| crate::runs::count_runs(inner, job_id_filter))
}
async fn count_runs_since(&self, since: DateTime<Utc>) -> Result<u64> {
read(&self.inner, |inner| crate::runs::count_runs_since(inner, since))
}
async fn task_run_stats(&self, task_name: &str) -> Result<TaskRunStats> {
read(&self.inner, |inner| crate::runs::task_run_stats(inner, task_name))
}
async fn get_task_config(&self, task_name: &str) -> Result<Option<TaskConfig>> {
read(&self.inner, |inner| crate::task_config::get_task_config(inner, task_name))
}
async fn upsert_task_config(&self, config: &TaskConfig) -> Result<()> {
write(&self.inner, |inner| crate::task_config::upsert_task_config(inner, config))
}
async fn try_claim_run_lease(
&self,
job_id: &str,
worker_id: &str,
ttl_secs: i64,
) -> Result<Option<String>> {
write(&self.inner, |inner| {
crate::leases::try_claim_run_lease(inner, job_id, worker_id, ttl_secs)
})
}
async fn extend_lease(&self, lease_id: &str, ttl_secs: i64) -> Result<()> {
write(&self.inner, |inner| crate::leases::extend_lease(inner, lease_id, ttl_secs))
}
async fn release_lease(&self, lease_id: &str) -> Result<()> {
write(&self.inner, |inner| crate::leases::release_lease(inner, lease_id))
}
async fn expired_lease_job_pairs(&self) -> Result<Vec<(String, String)>> {
read(&self.inner, crate::leases::expired_lease_job_pairs)
}
}