2022-08-29 16:59:22 +00:00
|
|
|
use crate::runnable::Runnable;
|
2021-06-06 08:44:46 +00:00
|
|
|
use crate::schema::fang_tasks;
|
2021-06-12 12:59:09 +00:00
|
|
|
use crate::schema::FangTaskState;
|
2022-08-29 16:59:22 +00:00
|
|
|
use crate::CronError;
|
|
|
|
use crate::Scheduled::*;
|
2021-07-18 19:09:30 +00:00
|
|
|
use chrono::DateTime;
|
|
|
|
use chrono::Utc;
|
2022-08-29 16:59:22 +00:00
|
|
|
use cron::Schedule;
|
2021-06-06 08:44:46 +00:00
|
|
|
use diesel::pg::PgConnection;
|
|
|
|
use diesel::prelude::*;
|
2021-07-25 12:20:16 +00:00
|
|
|
use diesel::r2d2;
|
2022-08-29 16:59:22 +00:00
|
|
|
use diesel::r2d2::ConnectionManager;
|
|
|
|
use diesel::r2d2::PoolError;
|
|
|
|
use diesel::r2d2::PooledConnection;
|
|
|
|
use diesel::result::Error as DieselError;
|
|
|
|
use sha2::Digest;
|
|
|
|
use sha2::Sha256;
|
|
|
|
use std::str::FromStr;
|
|
|
|
use thiserror::Error;
|
|
|
|
use typed_builder::TypedBuilder;
|
|
|
|
use uuid::Uuid;
|
|
|
|
|
|
|
|
#[cfg(test)]
|
2021-06-06 08:44:46 +00:00
|
|
|
use dotenv::dotenv;
|
2022-08-29 16:59:22 +00:00
|
|
|
#[cfg(test)]
|
2021-06-06 08:44:46 +00:00
|
|
|
use std::env;
|
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
pub type PoolConnection = PooledConnection<ConnectionManager<PgConnection>>;
|
|
|
|
|
|
|
|
#[derive(Queryable, Identifiable, Debug, Eq, PartialEq, Clone, TypedBuilder)]
|
2022-09-01 15:54:04 +00:00
|
|
|
#[diesel(table_name = fang_tasks)]
|
2022-07-19 13:49:43 +00:00
|
|
|
pub struct Task {
|
2022-08-29 16:59:22 +00:00
|
|
|
#[builder(setter(into))]
|
2022-07-19 13:49:43 +00:00
|
|
|
pub id: Uuid,
|
2022-08-29 16:59:22 +00:00
|
|
|
#[builder(setter(into))]
|
2022-07-19 13:49:43 +00:00
|
|
|
pub metadata: serde_json::Value,
|
2022-08-29 16:59:22 +00:00
|
|
|
#[builder(setter(into))]
|
2022-07-19 13:49:43 +00:00
|
|
|
pub error_message: Option<String>,
|
2022-08-29 16:59:22 +00:00
|
|
|
#[builder(setter(into))]
|
2022-07-19 13:49:43 +00:00
|
|
|
pub state: FangTaskState,
|
2022-08-29 16:59:22 +00:00
|
|
|
#[builder(setter(into))]
|
2022-07-19 13:49:43 +00:00
|
|
|
pub task_type: String,
|
2022-08-29 16:59:22 +00:00
|
|
|
#[builder(setter(into))]
|
|
|
|
pub uniq_hash: Option<String>,
|
|
|
|
#[builder(setter(into))]
|
|
|
|
pub scheduled_at: DateTime<Utc>,
|
|
|
|
#[builder(setter(into))]
|
2022-07-19 13:49:43 +00:00
|
|
|
pub created_at: DateTime<Utc>,
|
2022-08-29 16:59:22 +00:00
|
|
|
#[builder(setter(into))]
|
2022-07-19 13:49:43 +00:00
|
|
|
pub updated_at: DateTime<Utc>,
|
|
|
|
}
|
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
#[derive(Insertable, Debug, Eq, PartialEq, Clone, TypedBuilder)]
|
2022-09-01 15:54:04 +00:00
|
|
|
#[diesel(table_name = fang_tasks)]
|
2022-07-19 13:49:43 +00:00
|
|
|
pub struct NewTask {
|
2022-08-29 16:59:22 +00:00
|
|
|
#[builder(setter(into))]
|
|
|
|
metadata: serde_json::Value,
|
|
|
|
#[builder(setter(into))]
|
|
|
|
task_type: String,
|
|
|
|
#[builder(setter(into))]
|
|
|
|
uniq_hash: Option<String>,
|
|
|
|
#[builder(setter(into))]
|
|
|
|
scheduled_at: DateTime<Utc>,
|
2022-07-19 13:49:43 +00:00
|
|
|
}
|
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
#[derive(Debug, Error)]
|
|
|
|
pub enum QueueError {
|
|
|
|
#[error(transparent)]
|
|
|
|
DieselError(#[from] DieselError),
|
|
|
|
#[error(transparent)]
|
|
|
|
PoolError(#[from] PoolError),
|
|
|
|
#[error(transparent)]
|
|
|
|
CronError(#[from] CronError),
|
2022-07-19 13:49:43 +00:00
|
|
|
}
|
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
impl From<cron::error::Error> for QueueError {
|
|
|
|
fn from(error: cron::error::Error) -> Self {
|
|
|
|
QueueError::CronError(CronError::LibraryError(error))
|
|
|
|
}
|
2021-06-06 08:44:46 +00:00
|
|
|
}
|
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
pub trait Queueable {
|
|
|
|
fn fetch_and_touch_task(&self, task_type: String) -> Result<Option<Task>, QueueError>;
|
|
|
|
|
|
|
|
fn insert_task(&self, params: &dyn Runnable) -> Result<Task, QueueError>;
|
|
|
|
|
|
|
|
fn remove_all_tasks(&self) -> Result<usize, QueueError>;
|
|
|
|
|
2022-08-31 23:01:15 +00:00
|
|
|
fn remove_all_scheduled_tasks(&self) -> Result<usize, QueueError>;
|
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
fn remove_tasks_of_type(&self, task_type: &str) -> Result<usize, QueueError>;
|
|
|
|
|
|
|
|
fn remove_task(&self, id: Uuid) -> Result<usize, QueueError>;
|
|
|
|
|
|
|
|
fn find_task_by_id(&self, id: Uuid) -> Option<Task>;
|
|
|
|
|
|
|
|
fn update_task_state(&self, task: &Task, state: FangTaskState) -> Result<Task, QueueError>;
|
|
|
|
|
|
|
|
fn fail_task(&self, task: &Task, error: String) -> Result<Task, QueueError>;
|
|
|
|
|
|
|
|
fn schedule_task(&self, task: &dyn Runnable) -> Result<Task, QueueError>;
|
2021-07-11 10:17:02 +00:00
|
|
|
}
|
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
#[derive(Clone, TypedBuilder)]
|
|
|
|
pub struct Queue {
|
|
|
|
#[builder(setter(into))]
|
|
|
|
pub connection_pool: r2d2::Pool<r2d2::ConnectionManager<PgConnection>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Queueable for Queue {
|
|
|
|
fn fetch_and_touch_task(&self, task_type: String) -> Result<Option<Task>, QueueError> {
|
2022-09-01 15:54:04 +00:00
|
|
|
let mut connection = self.get_connection()?;
|
2021-07-03 12:18:41 +00:00
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
Self::fetch_and_touch_query(&mut connection, task_type)
|
2021-07-03 12:18:41 +00:00
|
|
|
}
|
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
fn insert_task(&self, params: &dyn Runnable) -> Result<Task, QueueError> {
|
2022-09-01 15:54:04 +00:00
|
|
|
let mut connection = self.get_connection()?;
|
2021-06-06 08:44:46 +00:00
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
Self::insert_query(&mut connection, params, Utc::now())
|
2021-06-06 08:44:46 +00:00
|
|
|
}
|
2022-08-29 16:59:22 +00:00
|
|
|
fn schedule_task(&self, params: &dyn Runnable) -> Result<Task, QueueError> {
|
2022-09-01 15:54:04 +00:00
|
|
|
let mut connection = self.get_connection()?;
|
2021-06-06 08:44:46 +00:00
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
Self::schedule_task_query(&mut connection, params)
|
2021-07-25 12:20:16 +00:00
|
|
|
}
|
2022-08-31 23:01:15 +00:00
|
|
|
|
|
|
|
fn remove_all_scheduled_tasks(&self) -> Result<usize, QueueError> {
|
2022-09-01 15:54:04 +00:00
|
|
|
let mut connection = self.get_connection()?;
|
2022-08-31 23:01:15 +00:00
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
Self::remove_all_scheduled_tasks_query(&mut connection)
|
2022-08-31 23:01:15 +00:00
|
|
|
}
|
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
fn remove_all_tasks(&self) -> Result<usize, QueueError> {
|
2022-09-01 15:54:04 +00:00
|
|
|
let mut connection = self.get_connection()?;
|
2021-07-25 12:20:16 +00:00
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
Self::remove_all_tasks_query(&mut connection)
|
2021-07-25 12:20:16 +00:00
|
|
|
}
|
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
fn remove_tasks_of_type(&self, task_type: &str) -> Result<usize, QueueError> {
|
2022-09-01 15:54:04 +00:00
|
|
|
let mut connection = self.get_connection()?;
|
2021-06-23 10:48:03 +00:00
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
Self::remove_tasks_of_type_query(&mut connection, task_type)
|
2022-08-29 16:59:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn remove_task(&self, id: Uuid) -> Result<usize, QueueError> {
|
2022-09-01 15:54:04 +00:00
|
|
|
let mut connection = self.get_connection()?;
|
2022-08-29 16:59:22 +00:00
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
Self::remove_task_query(&mut connection, id)
|
2021-07-18 19:09:30 +00:00
|
|
|
}
|
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
fn update_task_state(&self, task: &Task, state: FangTaskState) -> Result<Task, QueueError> {
|
2022-09-01 15:54:04 +00:00
|
|
|
let mut connection = self.get_connection()?;
|
2022-08-29 16:59:22 +00:00
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
Self::update_task_state_query(&mut connection, task, state)
|
2021-07-25 12:20:16 +00:00
|
|
|
}
|
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
fn fail_task(&self, task: &Task, error: String) -> Result<Task, QueueError> {
|
2022-09-01 15:54:04 +00:00
|
|
|
let mut connection = self.get_connection()?;
|
2021-06-23 10:48:03 +00:00
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
Self::fail_task_query(&mut connection, task, error)
|
2021-06-23 10:48:03 +00:00
|
|
|
}
|
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
fn find_task_by_id(&self, id: Uuid) -> Option<Task> {
|
2022-09-01 15:54:04 +00:00
|
|
|
let mut connection = self.get_connection().unwrap();
|
2022-08-29 16:59:22 +00:00
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
Self::find_task_by_id_query(&mut connection, id)
|
2021-06-24 09:58:02 +00:00
|
|
|
}
|
2022-08-29 16:59:22 +00:00
|
|
|
}
|
2021-06-24 09:58:02 +00:00
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
impl Queue {
|
|
|
|
pub fn get_connection(&self) -> Result<PoolConnection, QueueError> {
|
|
|
|
let result = self.connection_pool.get();
|
|
|
|
|
|
|
|
if let Err(err) = result {
|
|
|
|
log::error!("Failed to get a db connection {:?}", err);
|
|
|
|
return Err(QueueError::PoolError(err));
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(result.unwrap())
|
2021-07-25 12:20:16 +00:00
|
|
|
}
|
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
pub fn schedule_task_query(
|
2022-09-01 15:54:04 +00:00
|
|
|
connection: &mut PgConnection,
|
2022-08-29 16:59:22 +00:00
|
|
|
params: &dyn Runnable,
|
|
|
|
) -> Result<Task, QueueError> {
|
|
|
|
let scheduled_at = match params.cron() {
|
|
|
|
Some(scheduled) => match scheduled {
|
|
|
|
CronPattern(cron_pattern) => {
|
|
|
|
let schedule = Schedule::from_str(&cron_pattern)?;
|
|
|
|
let mut iterator = schedule.upcoming(Utc);
|
|
|
|
|
|
|
|
iterator
|
|
|
|
.next()
|
|
|
|
.ok_or(QueueError::CronError(CronError::NoTimestampsError))?
|
|
|
|
}
|
|
|
|
ScheduleOnce(datetime) => datetime,
|
|
|
|
},
|
|
|
|
None => {
|
|
|
|
return Err(QueueError::CronError(CronError::TaskNotSchedulableError));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
Self::insert_query(connection, params, scheduled_at)
|
2021-06-06 08:44:46 +00:00
|
|
|
}
|
2021-06-12 12:59:09 +00:00
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
fn calculate_hash(json: String) -> String {
|
|
|
|
let mut hasher = Sha256::new();
|
|
|
|
hasher.update(json.as_bytes());
|
|
|
|
let result = hasher.finalize();
|
|
|
|
hex::encode(result)
|
2021-07-25 12:20:16 +00:00
|
|
|
}
|
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
pub fn insert_query(
|
2022-09-01 15:54:04 +00:00
|
|
|
connection: &mut PgConnection,
|
2022-08-29 16:59:22 +00:00
|
|
|
params: &dyn Runnable,
|
|
|
|
scheduled_at: DateTime<Utc>,
|
|
|
|
) -> Result<Task, QueueError> {
|
|
|
|
if !params.uniq() {
|
|
|
|
let new_task = NewTask::builder()
|
|
|
|
.scheduled_at(scheduled_at)
|
|
|
|
.uniq_hash(None)
|
|
|
|
.task_type(params.task_type())
|
|
|
|
.metadata(serde_json::to_value(params).unwrap())
|
|
|
|
.build();
|
|
|
|
|
|
|
|
Ok(diesel::insert_into(fang_tasks::table)
|
|
|
|
.values(new_task)
|
|
|
|
.get_result::<Task>(connection)?)
|
|
|
|
} else {
|
|
|
|
let metadata = serde_json::to_value(params).unwrap();
|
|
|
|
|
|
|
|
let uniq_hash = Self::calculate_hash(metadata.to_string());
|
|
|
|
|
|
|
|
match Self::find_task_by_uniq_hash_query(connection, &uniq_hash) {
|
|
|
|
Some(task) => Ok(task),
|
|
|
|
None => {
|
|
|
|
let new_task = NewTask::builder()
|
|
|
|
.scheduled_at(scheduled_at)
|
|
|
|
.uniq_hash(Some(uniq_hash))
|
|
|
|
.task_type(params.task_type())
|
|
|
|
.metadata(serde_json::to_value(params).unwrap())
|
|
|
|
.build();
|
|
|
|
|
|
|
|
Ok(diesel::insert_into(fang_tasks::table)
|
|
|
|
.values(new_task)
|
|
|
|
.get_result::<Task>(connection)?)
|
|
|
|
}
|
|
|
|
}
|
2021-06-12 12:59:09 +00:00
|
|
|
}
|
|
|
|
}
|
2021-06-20 08:10:02 +00:00
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
pub fn fetch_task_query(connection: &mut PgConnection, task_type: String) -> Option<Task> {
|
2022-08-29 16:59:22 +00:00
|
|
|
Self::fetch_task_of_type_query(connection, &task_type)
|
2021-07-25 12:20:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn fetch_and_touch_query(
|
2022-09-01 15:54:04 +00:00
|
|
|
connection: &mut PgConnection,
|
2022-08-29 16:59:22 +00:00
|
|
|
task_type: String,
|
|
|
|
) -> Result<Option<Task>, QueueError> {
|
2022-09-01 15:54:04 +00:00
|
|
|
connection.transaction::<Option<Task>, QueueError, _>(|conn| {
|
|
|
|
let found_task = Self::fetch_task_query(conn, task_type);
|
2021-06-20 08:58:03 +00:00
|
|
|
|
2021-06-23 11:30:19 +00:00
|
|
|
if found_task.is_none() {
|
2021-06-20 08:58:03 +00:00
|
|
|
return Ok(None);
|
|
|
|
}
|
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
match Self::update_task_state_query(
|
2022-09-01 15:54:04 +00:00
|
|
|
conn,
|
2022-08-29 16:59:22 +00:00
|
|
|
&found_task.unwrap(),
|
|
|
|
FangTaskState::InProgress,
|
|
|
|
) {
|
2021-06-20 08:58:03 +00:00
|
|
|
Ok(updated_task) => Ok(Some(updated_task)),
|
|
|
|
Err(err) => Err(err),
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
pub fn find_task_by_id_query(connection: &mut PgConnection, id: Uuid) -> Option<Task> {
|
2021-07-03 12:18:41 +00:00
|
|
|
fang_tasks::table
|
2021-06-20 08:10:02 +00:00
|
|
|
.filter(fang_tasks::id.eq(id))
|
2021-07-25 12:20:16 +00:00
|
|
|
.first::<Task>(connection)
|
2021-07-03 12:18:41 +00:00
|
|
|
.ok()
|
|
|
|
}
|
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
pub fn remove_all_tasks_query(connection: &mut PgConnection) -> Result<usize, QueueError> {
|
2022-08-29 16:59:22 +00:00
|
|
|
Ok(diesel::delete(fang_tasks::table).execute(connection)?)
|
2021-07-25 12:20:16 +00:00
|
|
|
}
|
|
|
|
|
2022-08-31 23:01:15 +00:00
|
|
|
pub fn remove_all_scheduled_tasks_query(
|
2022-09-01 15:54:04 +00:00
|
|
|
connection: &mut PgConnection,
|
2022-08-31 23:01:15 +00:00
|
|
|
) -> Result<usize, QueueError> {
|
|
|
|
let query = fang_tasks::table.filter(fang_tasks::scheduled_at.gt(Utc::now()));
|
|
|
|
|
|
|
|
Ok(diesel::delete(query).execute(connection)?)
|
|
|
|
}
|
|
|
|
|
2021-07-25 12:20:16 +00:00
|
|
|
pub fn remove_tasks_of_type_query(
|
2022-09-01 15:54:04 +00:00
|
|
|
connection: &mut PgConnection,
|
2021-07-25 12:20:16 +00:00
|
|
|
task_type: &str,
|
2022-08-29 16:59:22 +00:00
|
|
|
) -> Result<usize, QueueError> {
|
2021-07-25 12:20:16 +00:00
|
|
|
let query = fang_tasks::table.filter(fang_tasks::task_type.eq(task_type));
|
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
Ok(diesel::delete(query).execute(connection)?)
|
2021-07-25 12:20:16 +00:00
|
|
|
}
|
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
pub fn remove_task_query(connection: &mut PgConnection, id: Uuid) -> Result<usize, QueueError> {
|
2021-07-03 12:18:41 +00:00
|
|
|
let query = fang_tasks::table.filter(fang_tasks::id.eq(id));
|
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
Ok(diesel::delete(query).execute(connection)?)
|
2021-07-25 12:20:16 +00:00
|
|
|
}
|
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
pub fn update_task_state_query(
|
2022-09-01 15:54:04 +00:00
|
|
|
connection: &mut PgConnection,
|
2021-07-25 12:20:16 +00:00
|
|
|
task: &Task,
|
2022-08-29 16:59:22 +00:00
|
|
|
state: FangTaskState,
|
|
|
|
) -> Result<Task, QueueError> {
|
|
|
|
Ok(diesel::update(task)
|
2021-06-20 08:58:03 +00:00
|
|
|
.set((
|
2022-08-29 16:59:22 +00:00
|
|
|
fang_tasks::state.eq(state),
|
2021-06-20 08:58:03 +00:00
|
|
|
fang_tasks::updated_at.eq(Self::current_time()),
|
|
|
|
))
|
2022-08-29 16:59:22 +00:00
|
|
|
.get_result::<Task>(connection)?)
|
2021-07-25 12:20:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn fail_task_query(
|
2022-09-01 15:54:04 +00:00
|
|
|
connection: &mut PgConnection,
|
2021-07-25 12:20:16 +00:00
|
|
|
task: &Task,
|
|
|
|
error: String,
|
2022-08-29 16:59:22 +00:00
|
|
|
) -> Result<Task, QueueError> {
|
|
|
|
Ok(diesel::update(task)
|
2021-06-20 08:10:02 +00:00
|
|
|
.set((
|
|
|
|
fang_tasks::state.eq(FangTaskState::Failed),
|
|
|
|
fang_tasks::error_message.eq(error),
|
|
|
|
fang_tasks::updated_at.eq(Self::current_time()),
|
|
|
|
))
|
2022-08-29 16:59:22 +00:00
|
|
|
.get_result::<Task>(connection)?)
|
2021-07-25 12:20:16 +00:00
|
|
|
}
|
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
fn current_time() -> DateTime<Utc> {
|
|
|
|
Utc::now()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
2021-07-25 12:20:16 +00:00
|
|
|
pub fn connection_pool(pool_size: u32) -> r2d2::Pool<r2d2::ConnectionManager<PgConnection>> {
|
|
|
|
dotenv().ok();
|
|
|
|
|
|
|
|
let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
|
|
|
|
|
|
|
|
let manager = r2d2::ConnectionManager::<PgConnection>::new(database_url);
|
|
|
|
|
|
|
|
r2d2::Pool::builder()
|
|
|
|
.max_size(pool_size)
|
|
|
|
.build(manager)
|
|
|
|
.unwrap()
|
2021-06-20 08:10:02 +00:00
|
|
|
}
|
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
fn fetch_task_of_type_query(connection: &mut PgConnection, task_type: &str) -> Option<Task> {
|
2021-07-03 12:18:41 +00:00
|
|
|
fang_tasks::table
|
2021-07-03 04:23:05 +00:00
|
|
|
.order(fang_tasks::created_at.asc())
|
2022-08-29 16:59:22 +00:00
|
|
|
.order(fang_tasks::scheduled_at.asc())
|
2021-07-03 04:23:05 +00:00
|
|
|
.limit(1)
|
2022-08-29 16:59:22 +00:00
|
|
|
.filter(fang_tasks::scheduled_at.le(Utc::now()))
|
2021-07-03 04:23:05 +00:00
|
|
|
.filter(fang_tasks::state.eq(FangTaskState::New))
|
|
|
|
.filter(fang_tasks::task_type.eq(task_type))
|
|
|
|
.for_update()
|
|
|
|
.skip_locked()
|
2021-07-25 12:20:16 +00:00
|
|
|
.get_result::<Task>(connection)
|
2021-07-03 12:18:41 +00:00
|
|
|
.ok()
|
2021-07-03 04:23:05 +00:00
|
|
|
}
|
2021-07-18 19:09:30 +00:00
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
fn find_task_by_uniq_hash_query(
|
|
|
|
connection: &mut PgConnection,
|
|
|
|
uniq_hash: &str,
|
|
|
|
) -> Option<Task> {
|
2021-07-18 19:09:30 +00:00
|
|
|
fang_tasks::table
|
2022-08-29 16:59:22 +00:00
|
|
|
.filter(fang_tasks::uniq_hash.eq(uniq_hash))
|
|
|
|
.filter(fang_tasks::state.eq(FangTaskState::New))
|
2021-07-25 12:20:16 +00:00
|
|
|
.first::<Task>(connection)
|
2021-07-18 19:09:30 +00:00
|
|
|
.ok()
|
|
|
|
}
|
2021-06-12 12:59:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
2021-07-25 12:20:16 +00:00
|
|
|
mod queue_tests {
|
|
|
|
use super::Queue;
|
2022-08-29 16:59:22 +00:00
|
|
|
use super::Queueable;
|
2022-08-31 23:01:15 +00:00
|
|
|
use crate::chrono::SubsecRound;
|
2022-08-29 16:59:22 +00:00
|
|
|
use crate::runnable::Runnable;
|
|
|
|
use crate::runnable::COMMON_TYPE;
|
2021-06-12 12:59:09 +00:00
|
|
|
use crate::schema::FangTaskState;
|
2021-07-11 07:26:20 +00:00
|
|
|
use crate::typetag;
|
2022-08-31 17:45:13 +00:00
|
|
|
use crate::FangError;
|
2022-08-31 23:01:15 +00:00
|
|
|
use crate::Scheduled;
|
|
|
|
use chrono::DateTime;
|
|
|
|
use chrono::Duration;
|
2022-08-29 16:59:22 +00:00
|
|
|
use chrono::Utc;
|
2021-06-12 12:59:09 +00:00
|
|
|
use diesel::connection::Connection;
|
|
|
|
use diesel::result::Error;
|
2021-07-31 06:47:53 +00:00
|
|
|
use serde::{Deserialize, Serialize};
|
2021-06-12 12:59:09 +00:00
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
#[derive(Serialize, Deserialize)]
|
|
|
|
struct PepeTask {
|
|
|
|
pub number: u16,
|
2021-06-12 12:59:09 +00:00
|
|
|
}
|
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
#[typetag::serde]
|
|
|
|
impl Runnable for PepeTask {
|
2022-08-31 17:45:13 +00:00
|
|
|
fn run(&self, _queue: &dyn Queueable) -> Result<(), FangError> {
|
2022-08-29 16:59:22 +00:00
|
|
|
println!("the number is {}", self.number);
|
2021-06-12 12:59:09 +00:00
|
|
|
|
|
|
|
Ok(())
|
2022-08-29 16:59:22 +00:00
|
|
|
}
|
|
|
|
fn uniq(&self) -> bool {
|
|
|
|
true
|
|
|
|
}
|
2021-06-12 12:59:09 +00:00
|
|
|
}
|
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
#[derive(Serialize, Deserialize)]
|
|
|
|
struct AyratTask {
|
|
|
|
pub number: u16,
|
2021-06-20 08:10:02 +00:00
|
|
|
}
|
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
#[typetag::serde]
|
|
|
|
impl Runnable for AyratTask {
|
2022-08-31 17:45:13 +00:00
|
|
|
fn run(&self, _queue: &dyn Queueable) -> Result<(), FangError> {
|
2022-08-29 16:59:22 +00:00
|
|
|
println!("the number is {}", self.number);
|
2021-06-20 08:10:02 +00:00
|
|
|
|
|
|
|
Ok(())
|
2022-08-29 16:59:22 +00:00
|
|
|
}
|
|
|
|
fn uniq(&self) -> bool {
|
|
|
|
true
|
|
|
|
}
|
2021-06-20 08:58:03 +00:00
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
fn task_type(&self) -> String {
|
|
|
|
"weirdo".to_string()
|
|
|
|
}
|
2021-06-20 08:58:03 +00:00
|
|
|
}
|
|
|
|
|
2022-08-31 23:01:15 +00:00
|
|
|
#[derive(Serialize, Deserialize)]
|
|
|
|
struct ScheduledPepeTask {
|
|
|
|
pub number: u16,
|
|
|
|
pub datetime: String,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[typetag::serde]
|
|
|
|
impl Runnable for ScheduledPepeTask {
|
|
|
|
fn run(&self, _queue: &dyn Queueable) -> Result<(), FangError> {
|
|
|
|
println!("the number is {}", self.number);
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
fn uniq(&self) -> bool {
|
|
|
|
true
|
|
|
|
}
|
|
|
|
|
|
|
|
fn task_type(&self) -> String {
|
|
|
|
"scheduled".to_string()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn cron(&self) -> Option<Scheduled> {
|
|
|
|
let datetime = self.datetime.parse::<DateTime<Utc>>().ok()?;
|
|
|
|
Some(Scheduled::ScheduleOnce(datetime))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-20 08:58:03 +00:00
|
|
|
#[test]
|
2022-09-01 15:54:04 +00:00
|
|
|
fn insert_task_test() {
|
2022-08-29 16:59:22 +00:00
|
|
|
let task = PepeTask { number: 10 };
|
2021-06-20 08:58:03 +00:00
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
let pool = Queue::connection_pool(5);
|
2021-06-20 08:58:03 +00:00
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
let queue = Queue::builder().connection_pool(pool).build();
|
2021-06-20 08:58:03 +00:00
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
let mut queue_pooled_connection = queue.connection_pool.get().unwrap();
|
2021-06-23 10:48:03 +00:00
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
queue_pooled_connection.test_transaction::<(), Error, _>(|conn| {
|
|
|
|
let task = Queue::insert_query(conn, &task, Utc::now()).unwrap();
|
2021-06-23 10:48:03 +00:00
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
let metadata = task.metadata.as_object().unwrap();
|
|
|
|
let number = metadata["number"].as_u64();
|
|
|
|
let type_task = metadata["type"].as_str();
|
2021-06-23 10:48:03 +00:00
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
assert_eq!(task.error_message, None);
|
|
|
|
assert_eq!(FangTaskState::New, task.state);
|
|
|
|
assert_eq!(Some(10), number);
|
|
|
|
assert_eq!(Some("PepeTask"), type_task);
|
2021-06-23 10:48:03 +00:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-07-18 19:09:30 +00:00
|
|
|
#[test]
|
2022-08-29 16:59:22 +00:00
|
|
|
fn fetch_task_fetches_the_oldest_task() {
|
|
|
|
let task1 = PepeTask { number: 10 };
|
|
|
|
let task2 = PepeTask { number: 11 };
|
|
|
|
|
|
|
|
let pool = Queue::connection_pool(5);
|
2021-07-18 19:09:30 +00:00
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
let queue = Queue::builder().connection_pool(pool).build();
|
2021-07-18 19:09:30 +00:00
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
let mut queue_pooled_connection = queue.connection_pool.get().unwrap();
|
2021-07-18 19:09:30 +00:00
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
queue_pooled_connection.test_transaction::<(), Error, _>(|conn| {
|
|
|
|
let task1 = Queue::insert_query(conn, &task1, Utc::now()).unwrap();
|
|
|
|
let _task2 = Queue::insert_query(conn, &task2, Utc::now()).unwrap();
|
2021-07-18 19:09:30 +00:00
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
let found_task = Queue::fetch_task_query(conn, COMMON_TYPE.to_string()).unwrap();
|
2022-08-29 16:59:22 +00:00
|
|
|
assert_eq!(found_task.id, task1.id);
|
2021-07-18 19:09:30 +00:00
|
|
|
Ok(())
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2022-08-29 16:59:22 +00:00
|
|
|
fn update_task_state_test() {
|
|
|
|
let task = PepeTask { number: 10 };
|
2021-07-18 19:09:30 +00:00
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
let pool = Queue::connection_pool(5);
|
2021-07-18 19:09:30 +00:00
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
let queue = Queue::builder().connection_pool(pool).build();
|
2021-07-18 19:09:30 +00:00
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
let mut queue_pooled_connection = queue.connection_pool.get().unwrap();
|
2021-07-18 19:09:30 +00:00
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
queue_pooled_connection.test_transaction::<(), Error, _>(|conn| {
|
|
|
|
let task = Queue::insert_query(conn, &task, Utc::now()).unwrap();
|
2021-07-18 19:09:30 +00:00
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
let found_task =
|
|
|
|
Queue::update_task_state_query(conn, &task, FangTaskState::Finished).unwrap();
|
2021-07-18 19:09:30 +00:00
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
let metadata = found_task.metadata.as_object().unwrap();
|
|
|
|
let number = metadata["number"].as_u64();
|
|
|
|
let type_task = metadata["type"].as_str();
|
2021-07-18 19:09:30 +00:00
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
assert_eq!(found_task.id, task.id);
|
|
|
|
assert_eq!(found_task.state, FangTaskState::Finished);
|
|
|
|
assert_eq!(Some(10), number);
|
|
|
|
assert_eq!(Some("PepeTask"), type_task);
|
2021-07-18 19:09:30 +00:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2022-08-29 16:59:22 +00:00
|
|
|
fn fail_task_updates_state_field_and_sets_error_message() {
|
|
|
|
let task = PepeTask { number: 10 };
|
2021-07-18 19:09:30 +00:00
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
let pool = Queue::connection_pool(5);
|
2021-07-18 19:09:30 +00:00
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
let queue = Queue::builder().connection_pool(pool).build();
|
2021-07-18 19:09:30 +00:00
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
let mut queue_pooled_connection = queue.connection_pool.get().unwrap();
|
2021-07-18 19:09:30 +00:00
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
queue_pooled_connection.test_transaction::<(), Error, _>(|conn| {
|
|
|
|
let task = Queue::insert_query(conn, &task, Utc::now()).unwrap();
|
2021-07-18 19:09:30 +00:00
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
let error = "Failed".to_string();
|
2021-07-18 19:09:30 +00:00
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
let found_task = Queue::fail_task_query(conn, &task, error.clone()).unwrap();
|
2021-07-18 19:09:30 +00:00
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
let metadata = found_task.metadata.as_object().unwrap();
|
|
|
|
let number = metadata["number"].as_u64();
|
|
|
|
let type_task = metadata["type"].as_str();
|
2021-07-18 19:09:30 +00:00
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
assert_eq!(found_task.id, task.id);
|
|
|
|
assert_eq!(found_task.state, FangTaskState::Failed);
|
|
|
|
assert_eq!(Some(10), number);
|
|
|
|
assert_eq!(Some("PepeTask"), type_task);
|
|
|
|
assert_eq!(found_task.error_message.unwrap(), error);
|
2021-07-18 19:09:30 +00:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2022-08-29 16:59:22 +00:00
|
|
|
fn fetch_and_touch_updates_state() {
|
|
|
|
let task = PepeTask { number: 10 };
|
2021-07-18 19:09:30 +00:00
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
let pool = Queue::connection_pool(5);
|
2021-07-18 19:09:30 +00:00
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
let queue = Queue::builder().connection_pool(pool).build();
|
2021-07-18 19:09:30 +00:00
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
let mut queue_pooled_connection = queue.connection_pool.get().unwrap();
|
2021-07-18 19:09:30 +00:00
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
queue_pooled_connection.test_transaction::<(), Error, _>(|conn| {
|
|
|
|
let task = Queue::insert_query(conn, &task, Utc::now()).unwrap();
|
2021-07-18 19:09:30 +00:00
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
let found_task = Queue::fetch_and_touch_query(conn, COMMON_TYPE.to_string())
|
|
|
|
.unwrap()
|
|
|
|
.unwrap();
|
2021-07-18 19:09:30 +00:00
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
let metadata = found_task.metadata.as_object().unwrap();
|
|
|
|
let number = metadata["number"].as_u64();
|
|
|
|
let type_task = metadata["type"].as_str();
|
2021-07-18 19:09:30 +00:00
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
assert_eq!(found_task.id, task.id);
|
|
|
|
assert_eq!(found_task.state, FangTaskState::InProgress);
|
|
|
|
assert_eq!(Some(10), number);
|
|
|
|
assert_eq!(Some("PepeTask"), type_task);
|
2021-07-18 19:09:30 +00:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2022-08-29 16:59:22 +00:00
|
|
|
fn fetch_and_touch_returns_none() {
|
|
|
|
let pool = Queue::connection_pool(5);
|
2021-07-18 19:09:30 +00:00
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
let queue = Queue::builder().connection_pool(pool).build();
|
2021-07-18 19:09:30 +00:00
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
let mut queue_pooled_connection = queue.connection_pool.get().unwrap();
|
2021-07-18 19:09:30 +00:00
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
queue_pooled_connection.test_transaction::<(), Error, _>(|conn| {
|
|
|
|
let found_task = Queue::fetch_and_touch_query(conn, COMMON_TYPE.to_string()).unwrap();
|
2021-07-18 19:09:30 +00:00
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
assert_eq!(None, found_task);
|
2021-07-18 19:09:30 +00:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-07-03 12:18:41 +00:00
|
|
|
#[test]
|
2022-08-29 16:59:22 +00:00
|
|
|
fn insert_task_uniq_test() {
|
|
|
|
let task = PepeTask { number: 10 };
|
2021-07-03 12:18:41 +00:00
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
let pool = Queue::connection_pool(5);
|
2021-07-03 12:18:41 +00:00
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
let queue = Queue::builder().connection_pool(pool).build();
|
2021-07-25 12:20:16 +00:00
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
let mut queue_pooled_connection = queue.connection_pool.get().unwrap();
|
2021-07-25 12:20:16 +00:00
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
queue_pooled_connection.test_transaction::<(), Error, _>(|conn| {
|
|
|
|
let task1 = Queue::insert_query(conn, &task, Utc::now()).unwrap();
|
|
|
|
let task2 = Queue::insert_query(conn, &task, Utc::now()).unwrap();
|
2021-07-25 12:20:16 +00:00
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
assert_eq!(task2.id, task1.id);
|
2021-07-25 12:20:16 +00:00
|
|
|
Ok(())
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2022-08-31 23:01:15 +00:00
|
|
|
#[test]
|
|
|
|
fn schedule_task_test() {
|
|
|
|
let pool = Queue::connection_pool(5);
|
|
|
|
let queue = Queue::builder().connection_pool(pool).build();
|
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
let mut queue_pooled_connection = queue.connection_pool.get().unwrap();
|
2022-08-31 23:01:15 +00:00
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
queue_pooled_connection.test_transaction::<(), Error, _>(|conn| {
|
2022-08-31 23:01:15 +00:00
|
|
|
let datetime = (Utc::now() + Duration::seconds(7)).round_subsecs(0);
|
|
|
|
|
|
|
|
let task = &ScheduledPepeTask {
|
|
|
|
number: 10,
|
|
|
|
datetime: datetime.to_string(),
|
|
|
|
};
|
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
let task = Queue::schedule_task_query(conn, task).unwrap();
|
2022-08-31 23:01:15 +00:00
|
|
|
|
|
|
|
let metadata = task.metadata.as_object().unwrap();
|
|
|
|
let number = metadata["number"].as_u64();
|
|
|
|
let type_task = metadata["type"].as_str();
|
|
|
|
|
|
|
|
assert_eq!(Some(10), number);
|
|
|
|
assert_eq!(Some("ScheduledPepeTask"), type_task);
|
|
|
|
assert_eq!(task.scheduled_at, datetime);
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn remove_all_scheduled_tasks_test() {
|
|
|
|
let pool = Queue::connection_pool(5);
|
|
|
|
let queue = Queue::builder().connection_pool(pool).build();
|
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
let mut queue_pooled_connection = queue.connection_pool.get().unwrap();
|
2022-08-31 23:01:15 +00:00
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
queue_pooled_connection.test_transaction::<(), Error, _>(|conn| {
|
2022-08-31 23:01:15 +00:00
|
|
|
let datetime = (Utc::now() + Duration::seconds(7)).round_subsecs(0);
|
|
|
|
|
|
|
|
let task1 = &ScheduledPepeTask {
|
|
|
|
number: 10,
|
|
|
|
datetime: datetime.to_string(),
|
|
|
|
};
|
|
|
|
|
|
|
|
let task2 = &ScheduledPepeTask {
|
|
|
|
number: 11,
|
|
|
|
datetime: datetime.to_string(),
|
|
|
|
};
|
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
Queue::schedule_task_query(conn, task1).unwrap();
|
|
|
|
Queue::schedule_task_query(conn, task2).unwrap();
|
2022-08-31 23:01:15 +00:00
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
let number = Queue::remove_all_scheduled_tasks_query(conn).unwrap();
|
2022-08-31 23:01:15 +00:00
|
|
|
|
|
|
|
assert_eq!(2, number);
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-07-25 12:20:16 +00:00
|
|
|
#[test]
|
2022-08-29 16:59:22 +00:00
|
|
|
fn remove_all_tasks_test() {
|
|
|
|
let task1 = PepeTask { number: 10 };
|
|
|
|
let task2 = PepeTask { number: 11 };
|
2021-07-25 12:20:16 +00:00
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
let pool = Queue::connection_pool(5);
|
2021-07-25 12:20:16 +00:00
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
let queue = Queue::builder().connection_pool(pool).build();
|
2021-07-03 12:18:41 +00:00
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
let mut queue_pooled_connection = queue.connection_pool.get().unwrap();
|
2021-07-03 12:18:41 +00:00
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
queue_pooled_connection.test_transaction::<(), Error, _>(|conn| {
|
|
|
|
let task1 = Queue::insert_query(conn, &task1, Utc::now()).unwrap();
|
|
|
|
let task2 = Queue::insert_query(conn, &task2, Utc::now()).unwrap();
|
2021-07-03 12:18:41 +00:00
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
let result = Queue::remove_all_tasks_query(conn).unwrap();
|
2022-08-29 16:59:22 +00:00
|
|
|
|
|
|
|
assert_eq!(2, result);
|
2022-09-01 15:54:04 +00:00
|
|
|
assert_eq!(None, Queue::find_task_by_id_query(conn, task1.id));
|
|
|
|
assert_eq!(None, Queue::find_task_by_id_query(conn, task2.id));
|
2021-07-03 12:18:41 +00:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-06-12 12:59:09 +00:00
|
|
|
#[test]
|
2022-08-29 16:59:22 +00:00
|
|
|
fn remove_task() {
|
|
|
|
let task1 = PepeTask { number: 10 };
|
|
|
|
let task2 = PepeTask { number: 11 };
|
2021-06-13 09:26:40 +00:00
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
let pool = Queue::connection_pool(5);
|
2021-06-12 12:59:09 +00:00
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
let queue = Queue::builder().connection_pool(pool).build();
|
2021-06-12 12:59:09 +00:00
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
let mut queue_pooled_connection = queue.connection_pool.get().unwrap();
|
2021-06-12 12:59:09 +00:00
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
queue_pooled_connection.test_transaction::<(), Error, _>(|conn| {
|
|
|
|
let task1 = Queue::insert_query(conn, &task1, Utc::now()).unwrap();
|
|
|
|
let task2 = Queue::insert_query(conn, &task2, Utc::now()).unwrap();
|
2021-06-12 12:59:09 +00:00
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
assert!(Queue::find_task_by_id_query(conn, task1.id).is_some());
|
|
|
|
assert!(Queue::find_task_by_id_query(conn, task2.id).is_some());
|
2021-06-12 12:59:09 +00:00
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
Queue::remove_task_query(conn, task1.id).unwrap();
|
2021-06-12 12:59:09 +00:00
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
assert!(Queue::find_task_by_id_query(conn, task1.id).is_none());
|
|
|
|
assert!(Queue::find_task_by_id_query(conn, task2.id).is_some());
|
2021-06-12 12:59:09 +00:00
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
Ok(())
|
2021-06-12 12:59:09 +00:00
|
|
|
});
|
2022-08-29 16:59:22 +00:00
|
|
|
}
|
2021-06-12 12:59:09 +00:00
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
#[test]
|
|
|
|
fn remove_task_of_type() {
|
|
|
|
let task1 = PepeTask { number: 10 };
|
|
|
|
let task2 = AyratTask { number: 10 };
|
2021-06-12 12:59:09 +00:00
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
let pool = Queue::connection_pool(5);
|
2021-06-12 12:59:09 +00:00
|
|
|
|
2022-08-29 16:59:22 +00:00
|
|
|
let queue = Queue::builder().connection_pool(pool).build();
|
2021-06-13 09:26:40 +00:00
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
let mut queue_pooled_connection = queue.connection_pool.get().unwrap();
|
2021-06-12 12:59:09 +00:00
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
queue_pooled_connection.test_transaction::<(), Error, _>(|conn| {
|
|
|
|
let task1 = Queue::insert_query(conn, &task1, Utc::now()).unwrap();
|
|
|
|
let task2 = Queue::insert_query(conn, &task2, Utc::now()).unwrap();
|
2021-06-12 12:59:09 +00:00
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
assert!(Queue::find_task_by_id_query(conn, task1.id).is_some());
|
|
|
|
assert!(Queue::find_task_by_id_query(conn, task2.id).is_some());
|
2021-06-13 09:26:40 +00:00
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
Queue::remove_tasks_of_type_query(conn, "weirdo").unwrap();
|
2021-06-12 12:59:09 +00:00
|
|
|
|
2022-09-01 15:54:04 +00:00
|
|
|
assert!(Queue::find_task_by_id_query(conn, task1.id).is_some());
|
|
|
|
assert!(Queue::find_task_by_id_query(conn, task2.id).is_none());
|
2021-06-23 10:48:03 +00:00
|
|
|
|
|
|
|
Ok(())
|
2022-08-29 16:59:22 +00:00
|
|
|
});
|
2021-06-20 08:10:02 +00:00
|
|
|
}
|
2021-06-06 08:44:46 +00:00
|
|
|
}
|