### Setup Databases for Testing Source: https://github.com/ayrat555/fang/blob/master/README.md Sets up the necessary databases for testing the Fang project. This command may require Docker to be installed and running. ```sh make -j db ``` -------------------------------- ### Install Diesel CLI Source: https://github.com/ayrat555/fang/blob/master/README.md Installs the Diesel CLI with support for multiple database backends. Ensure you have Rust and Cargo installed. ```sh cargo install diesel_cli --no-default-features --features "postgres sqlite mysql" ``` -------------------------------- ### Run PostgreSQL Migrations with Fang Source: https://github.com/ayrat555/fang/blob/master/README.md This example shows how to use the `migrations-postgres` feature to run database migrations programmatically. Ensure you have a connection established. ```rust use fang::run_migrations_postgres; run_migrations_postgres(&mut connection).unwrap(); ``` -------------------------------- ### Start Fang AsyncWorkerPool Source: https://github.com/ayrat555/fang/blob/master/docs/content/blog/2022-08-06-async-processing.md Initialize and start an `AsyncWorkerPool` with a specified number of workers and the configured `AsyncQueue`. The pool will begin processing tasks from the queue upon starting. ```rust use fang::asynk::async_worker_pool::AsyncWorkerPool; use fang::NoTls; let mut pool: AsyncWorkerPool> = AsyncWorkerPool::builder() .number_of_workers(10_u32) .queue(queue.clone()) .build(); pool.start().await; ``` -------------------------------- ### Start Asynchronous Worker Pool Source: https://github.com/ayrat555/fang/blob/master/README.md Initialize and start an `AsyncWorkerPool` for asynchronous tasks. Specify the number of workers, the queue, and optionally filter tasks by type. Workers run in separate tokio tasks and are restarted if they panic. ```rust use fang::asynk::async_worker_pool::AsyncWorkerPool; // Need to create a queue // Also insert some tasks let mut pool: AsyncWorkerPool = AsyncWorkerPool::builder() .number_of_workers(max_pool_size) .queue(queue.clone()) // if you want to run tasks of the specific kind .task_type("my_task_type") .build(); pool.start().await; ``` -------------------------------- ### Custom Sleep Parameters Example Source: https://github.com/ayrat555/fang/blob/master/README.md Example of setting custom `SleepParams` for worker sleep behavior. This allows tuning how long workers wait when the task queue is empty. ```rust let sleep_params = SleepParams { sleep_period: Duration::from_secs(2), max_sleep_period: Duration::from_secs(6), min_sleep_period: Duration::from_secs(2), sleep_step: Duration::from_secs(1), }; // Set sleep params with worker pools `TypeBuilder` in both modules. ``` -------------------------------- ### Start Blocking Worker Pool Source: https://github.com/ayrat555/fang/blob/master/README.md Initialize and start a `WorkerPool` for blocking tasks. Specify the number of workers and optionally filter tasks by type. Each worker runs in a separate thread and is restarted if it panics. ```rust use fang::WorkerPool; use fang::Queue; // create a Queue let mut worker_pool = WorkerPool::::builder() .queue(queue) .number_of_workers(3_u32) // if you want to run tasks of the specific kind .task_type("my_task_type") .build(); worker_pool.start(); ``` -------------------------------- ### AsyncRunnable CRON Task Scheduling Source: https://github.com/ayrat555/fang/blob/master/docs/content/blog/2022-09-08-fang-09-release.md Example of implementing the `AsyncRunnable` trait to schedule a task using a CRON pattern. The `cron` method should return `Scheduled::CronPattern` with a valid cron expression. ```rust impl AsyncRunnable for MyCronTask { async fn run(&self, _queue: &mut dyn AsyncQueueable) -> Result<(), Error> { log::info!("CRON!!!!!!!!!!!!!!!",); Ok(()) } // you must use fang::Scheduled enum. fn cron(&self) -> Option { // cron expression to execute a task every 20 seconds. let expression = "0/20 * * * * * *"; Some(Scheduled::CronPattern(expression.to_string())) } fn uniq(&self) -> bool { true } } ``` -------------------------------- ### AsyncRunnable Schedule Once Task Source: https://github.com/ayrat555/fang/blob/master/docs/content/blog/2022-09-08-fang-09-release.md Example of implementing the `AsyncRunnable` trait to schedule a task for a specific future time. The `cron` method should return `Scheduled::ScheduleOnce` with a `DateTime`. ```rust impl AsyncRunnable for MyCronTask { async fn run(&self, _queue: &mut dyn AsyncQueueable) -> Result<(), Error> { log::info!("CRON!!!!!!!!!!!!!!!",); Ok(()) } // you must use fang::Scheduled enum. fn cron(&self) -> Option { // You must use DateTime to specify // when in the future you would like schedule the task. // This will schedule the task for within 7 seconds. Some(Scheduled::ScheduleOnce(Utc::now() + Duration::seconds(7i64))) } fn uniq(&self) -> bool { true } } ``` -------------------------------- ### Fang SleepParams Struct Source: https://github.com/ayrat555/fang/blob/master/README.md Configures the sleep behavior of workers when no tasks are available. `sleep_period` is the initial sleep duration, `max_sleep_period` is the upper limit, `min_sleep_period` is the starting sleep duration, and `sleep_step` is the increment for each subsequent sleep period. ```rust pub struct SleepParams { pub sleep_period: Duration, // default value is 5 seconds pub max_sleep_period: Duration, // default value is 15 seconds pub min_sleep_period: Duration, // default value is 5 seconds pub sleep_step: Duration, // default value is 5 seconds } ``` -------------------------------- ### Initialize AsyncQueue (Postgres) Source: https://github.com/ayrat555/fang/blob/master/README.md Set up an `AsyncQueue` for the Postgres backend. Specify the database URI and the maximum number of connections. The queue must be connected before any operations can be performed. ```rust use fang::asynk::async_queue::AsyncQueue; use fang::AsyncRunnable; // Create an AsyncQueue let max_pool_size: u32 = 2; let mut queue = AsyncQueue::builder() // Postgres database url .uri("postgres://postgres:postgres@localhost/fang") // Max number of connections that are allowed .max_pool_size(max_pool_size) .build(); // Always connect first in order to perform any operation queue.connect().await.unwrap(); ``` -------------------------------- ### Initialize Fang AsyncQueue Source: https://github.com/ayrat555/fang/blob/master/docs/content/blog/2022-08-06-async-processing.md Initialize the `AsyncQueue` with a database connection URI and configure pool size and duplicate task handling. Ensure the database connection details are correct. ```rust use fang::asynk::async_queue::AsyncQueue; let max_pool_size: u32 = 2; let mut queue = AsyncQueue::builder() .uri("postgres://postgres:postgres@localhost/fang") .max_pool_size(max_pool_size) .duplicated_tasks(true) .build(); ``` -------------------------------- ### Add Fang with Asynk and Derive Macro Source: https://github.com/ayrat555/fang/blob/master/README.md This configuration enables the asynk feature with a specified database backend and the derive-error macro. Replace `{database}` with your chosen backend (e.g., `postgres`, `sqlite`, `mysql`). ```toml [dependencies] fang = { version = "0.11.0-rc1" , features = ["asynk-{database}", "derive-error" ], default-features = false } ``` -------------------------------- ### Add Fang with Asynk PostgreSQL Feature Source: https://github.com/ayrat555/fang/blob/master/README.md Use this configuration in Cargo.toml to set up PostgreSQL as the asynchronous task queue. ```toml [dependencies] fang = { version = "0.11.0-rc1" , features = ["asynk-postgres"], default-features = false } ``` -------------------------------- ### Add Fang with Asynk MySQL Feature Source: https://github.com/ayrat555/fang/blob/master/README.md Add this to your Cargo.toml to integrate MySQL as the asynchronous task queue. ```toml [dependencies] fang = { version = "0.11.0-rc1" , features = ["asynk-mysql"], default-features = false } ``` -------------------------------- ### Add Fang with Asynk SQLite Feature Source: https://github.com/ayrat555/fang/blob/master/README.md Configure your Cargo.toml with this to use SQLite as the asynchronous task queue. ```toml [dependencies] fang = { version = "0.11.0-rc1" , features = ["asynk-sqlite"], default-features = false } ``` -------------------------------- ### Add Fang with Migrations Feature Source: https://github.com/ayrat555/fang/blob/master/README.md This Cargo.toml configuration enables the asynchronous PostgreSQL backend along with the PostgreSQL migration feature, allowing you to run migrations as code. ```toml [dependencies] fang = { version = "0.11.0-rc1" , features = ["asynk-postgres", "migrations-postgres" ], default-features = false } ``` -------------------------------- ### Run Tests Source: https://github.com/ayrat555/fang/blob/master/README.md Executes the test suite for the Fang project. The `-j` flag enables parallel execution, which is recommended for faster test runs. ```sh make -j tests ``` -------------------------------- ### Add Fang with All Features Source: https://github.com/ayrat555/fang/blob/master/README.md Include this in your Cargo.toml to enable all features of the Fang library. Supports rustc 1.77+. ```toml fang = { version = "0.11.0-rc1" } ``` -------------------------------- ### Enqueue a Task into Fang Queue Source: https://github.com/ayrat555/fang/blob/master/docs/content/blog/2022-08-06-async-processing.md Create an instance of your task struct and enqueue it into the `AsyncQueue` using `insert_task`. Ensure the task is cast to `&dyn AsyncRunnable`. ```rust let task = MyTask::new(0); queue .insert_task(&task as &dyn AsyncRunnable) .await .unwrap(); ``` -------------------------------- ### Fang Sleep Parameters Configuration Source: https://github.com/ayrat555/fang/blob/master/fang/README.md Configure the sleep behavior of workers when no tasks are available. `sleep_period` is the initial sleep duration, `max_sleep_period` is the upper limit, `min_sleep_period` is the initial value, and `sleep_step` is the increment. ```rust pub struct SleepParams { pub sleep_period: Duration, // default value is 5 seconds pub max_sleep_period: Duration, // default value is 15 seconds pub min_sleep_period: Duration, // default value is 5 seconds pub sleep_step: Duration, // default value is 5 seconds } let sleep_params = SleepParams { sleep_period: Duration::from_secs(2), max_sleep_period: Duration::from_secs(6), min_sleep_period: Duration::from_secs(2), sleep_step: Duration::from_secs(1), }; ``` -------------------------------- ### Enqueue Task (Asynchronous) Source: https://github.com/ayrat555/fang/blob/master/README.md Enqueue a task using `AsyncQueueable::insert_task` in the asynchronous mode. The task must be a type that implements `AsyncRunnable`. ```rust // AsyncTask from the first example let task = AsyncTask { 8 }; let task_returned = queue .insert_task(&task as &dyn AsyncRunnable) .await .unwrap(); ``` -------------------------------- ### Add Fang with Blocking Feature Source: https://github.com/ayrat555/fang/blob/master/README.md Include this dependency in your Cargo.toml to enable the blocking worker functionality. ```toml [dependencies] fang = { version = "0.11.0-rc1" , features = ["blocking"], default-features = false } ``` -------------------------------- ### Define a Serializable Task with Serde Source: https://github.com/ayrat555/fang/blob/master/docs/content/blog/2022-08-06-async-processing.md Define a serializable task struct by deriving `serde` traits. Fang re-exports `serde`, so it doesn't need to be added to `Cargo.toml`. ```rust use fang::serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize)] #[serde(crate = "fang::serde")] pub struct MyTask { pub number: u16, } impl MyTask { pub fn new(number: u16) -> Self { Self { number } } } ``` -------------------------------- ### Define Asynchronous Task Source: https://github.com/ayrat555/fang/blob/master/README.md Implement `AsyncRunnable` for asynchronous tasks. Ensure task names are unique to avoid `typetag` crate failures. Configuration options for task type, uniqueness, cron scheduling, max retries, and backoff are available. ```rust use fang::AsyncRunnable; use fang::asynk::async_queue::AsyncQueueable; use fang::serde::{Deserialize, Serialize}; use fang::async_trait; #[derive(Serialize, Deserialize)] #[serde(crate = "fang::serde")] struct AsyncTask { pub number: u16, } #[typetag::serde] #[async_trait] impl AsyncRunnable for AsyncTask { async fn run(&self, _queueable: &mut dyn AsyncQueueable) -> Result<(), Error> { Ok(()) } // this func is optional // Default task_type is common fn task_type(&self) -> String { "my-task-type".to_string() } // If `uniq` is set to true and the task is already in the storage, it won't be inserted again // The existing record will be returned for for any insertions operaiton fn uniq(&self) -> bool { true } // This will be useful if you would like to schedule tasks. // default value is None (the task is not scheduled, it's just executed as soon as it's inserted) fn cron(&self) -> Option { let expression = "0/20 * * * Aug-Sep * 2022/1"; Some(Scheduled::CronPattern(expression.to_string())) } // the maximum number of retries. Set it to 0 to make it not retriable // the default value is 20 fn max_retries(&self) -> i32 { 20 } // backoff mode for retries fn backoff(&self, attempt: u32) -> u32 { u32::pow(2, attempt) } } ``` -------------------------------- ### Schedule Task Once Source: https://github.com/ayrat555/fang/blob/master/README.md Tasks can be scheduled for one-time execution using `Scheduled::ScheduleOnce`. Datetimes and cron patterns are interpreted in UTC; adjust with timezone offsets if necessary. ```rust let expression = "0 0 9 * * * *"; ``` -------------------------------- ### Stop Databases Source: https://github.com/ayrat555/fang/blob/master/README.md Shuts down the databases that were set up for testing. The `-j` flag enables parallel execution. ```sh make -j stop ``` -------------------------------- ### Define Blocking Task with Custom Error Handling Source: https://github.com/ayrat555/fang/blob/master/README.md Implement `Runnable` for blocking tasks. Use `#[derive(ToFangError)]` to easily convert custom errors to `FangError` for use with the `?` operator in the `run` function. Task uniqueness, type, cron scheduling, max retries, and backoff can be configured. ```rust use fang::FangError; use fang::Runnable; use fang::typetag; use fang::PgConnection; use fang::serde::{Deserialize, Serialize}; use fang::ToFangError; use std::fmt::Debug; #[derive(Debug, ToFangError)] enum CustomError { ErrorOne(String), ErrorTwo(u32), } fn my_func(num : u16) -> Result<(), CustomError> { if num == 0 { Err(CustomError::ErrorOne("is zero".to_string())) } if num > 500 { Err(CustomError::ErrorTwo(num)) } Ok(()) } #[derive(Serialize, Deserialize)] #[serde(crate = "fang::serde")] struct MyTask { pub number: u16, } #[typetag::serde] impl Runnable for MyTask { fn run(&self, _queue: &dyn Queueable) -> Result<(), FangError> { println!("the number is {}", self.number); my_func(self.number)?; // You can use ? operator because // From is implemented thanks to ToFangError derive macro. Ok(()) } // If `uniq` is set to true and the task is already in the storage, it won't be inserted again // The existing record will be returned for for any insertions operaiton fn uniq(&self) -> bool { true } // This will be useful if you want to filter tasks. // the default value is `common` fn task_type(&self) -> String { "my_task".to_string() } // This will be useful if you would like to schedule tasks. // default value is None (the task is not scheduled, it's just executed as soon as it's inserted) fn cron(&self) -> Option { let expression = "0/20 * * * Aug-Sep * 2022/1"; Some(Scheduled::CronPattern(expression.to_string())) } // the maximum number of retries. Set it to 0 to make it not retriable // the default value is 20 fn max_retries(&self) -> i32 { 20 } // backoff mode for retries fn backoff(&self, attempt: u32) -> u32 { u32::pow(2, attempt) } } ``` -------------------------------- ### Fang Tasks Table Schema Source: https://github.com/ayrat555/fang/blob/master/docs/content/blog/2022-09-08-fang-09-release.md Defines the updated schema for the `fang_tasks` table, consolidating periodic, scheduled, and one-time tasks. Includes new fields `scheduled_at` for scheduling and `uniq_hash` for deduplication. ```sql CREATE TABLE fang_tasks ( id uuid PRIMARY KEY DEFAULT uuid_generate_v4(), metadata jsonb NOT NULL, error_message TEXT, state fang_task_state DEFAULT 'new' NOT NULL, task_type VARCHAR DEFAULT 'common' NOT NULL, uniq_hash CHAR(64), scheduled_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(), created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW() ); ``` -------------------------------- ### Enqueue Task (Blocking) Source: https://github.com/ayrat555/fang/blob/master/README.md Use `Queue::enqueue_task` to add a task to the queue in the blocking mode. Requires a pre-configured r2d2 connection pool. ```rust use fang::Queue; // create a r2d2 pool // create a fang queue let queue = Queue::builder().connection_pool(pool).build(); let task_inserted = queue.insert_task(&MyTask::new(1)).unwrap(); ``` -------------------------------- ### Implement AsyncRunnable Trait for Tasks Source: https://github.com/ayrat555/fang/blob/master/docs/content/blog/2022-08-06-async-processing.md Implement the `AsyncRunnable` trait for your task struct using `async-trait` and `typetag`. This allows Fang to serialize and run the task asynchronously. The `run` method can enqueue new tasks and perform asynchronous operations. ```rust use fang::async_trait; use fang::typetag; use fang::AsyncRunnable; use std::time::Duration; #[async_trait] #[typetag::serde] impl AsyncRunnable for MyTask { async fn run(&self, queue: &mut dyn AsyncQueueable) -> Result<(), Error> { let new_task = MyTask::new(self.number + 1); queue .insert_task(&new_task as &dyn AsyncRunnable) .await .unwrap(); log::info!("the current number is {}", self.number); tokio::time::sleep(Duration::from_secs(3)).await; Ok(()) } } ``` -------------------------------- ### Blocking Queueable Trait API Source: https://github.com/ayrat555/fang/blob/master/docs/content/blog/2022-09-08-fang-09-release.md Defines the new `Queueable` trait for the blocking module, unifying the API with the async module and allowing for different backend implementations. Includes methods for task management and retrieval. ```rust pub trait Queueable { fn fetch_and_touch_task(&self, task_type: String) -> Result, QueueError>; fn insert_task(&self, params: &dyn Runnable) -> Result; fn remove_all_tasks(&self) -> Result; fn remove_all_scheduled_tasks(&self) -> Result; fn remove_tasks_of_type(&self, task_type: &str) -> Result; fn remove_task(&self, id: Uuid) -> Result; fn find_task_by_id(&self, id: Uuid) -> Option; fn update_task_state(&self, task: &Task, state: FangTaskState) -> Result; fn fail_task(&self, task: &Task, error: String) -> Result; fn schedule_task(&self, task: &dyn Runnable) -> Result; } ``` -------------------------------- ### Fang Retention Modes Enum Source: https://github.com/ayrat555/fang/blob/master/README.md Defines the retention modes for tasks in the database. `KeepAll` retains all tasks, `RemoveAll` removes all tasks, and `RemoveFinished` (the default) removes only successfully completed tasks. ```rust pub enum RetentionMode { KeepAll, // doesn't remove tasks RemoveAll, // removes all tasks RemoveFinished, // default value } ``` -------------------------------- ### Run Dirty/Long Tests Source: https://github.com/ayrat555/fang/blob/master/README.md Executes tests that are marked as dirty or long-running. The `-j` flag enables parallel execution. ```sh make -j ignored ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.