mirror of
https://git.asonix.dog/asonix/background-jobs.git
synced 2024-12-11 21:16:28 +00:00
Remove anyhow
This commit is contained in:
parent
8217012237
commit
141db9afc8
30 changed files with 196 additions and 135 deletions
15
README.md
15
README.md
|
@ -15,7 +15,6 @@ might not be the best experience.
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-rt = "2.2.0"
|
actix-rt = "2.2.0"
|
||||||
background-jobs = "0.15.0"
|
background-jobs = "0.15.0"
|
||||||
anyhow = "1.0"
|
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -24,8 +23,7 @@ Jobs are a combination of the data required to perform an operation, and the log
|
||||||
operation. They implement the `Job`, `serde::Serialize`, and `serde::DeserializeOwned`.
|
operation. They implement the `Job`, `serde::Serialize`, and `serde::DeserializeOwned`.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use background_jobs::Job;
|
use background_jobs::{Job, BoxError};
|
||||||
use anyhow::Error;
|
|
||||||
use std::future::{ready, Ready};
|
use std::future::{ready, Ready};
|
||||||
|
|
||||||
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
||||||
|
@ -45,7 +43,8 @@ impl MyJob {
|
||||||
|
|
||||||
impl Job for MyJob {
|
impl Job for MyJob {
|
||||||
type State = ();
|
type State = ();
|
||||||
type Future = Ready<Result<(), Error>>;
|
type Error = BoxError;
|
||||||
|
type Future = Ready<Result<(), BoxError>>;
|
||||||
|
|
||||||
const NAME: &'static str = "MyJob";
|
const NAME: &'static str = "MyJob";
|
||||||
|
|
||||||
|
@ -80,7 +79,8 @@ impl MyState {
|
||||||
|
|
||||||
impl Job for MyJob {
|
impl Job for MyJob {
|
||||||
type State = MyState;
|
type State = MyState;
|
||||||
type Future = Ready<Result<(), Error>>;
|
type Error = BoxError;
|
||||||
|
type Future = Ready<Result<(), BoxError>>;
|
||||||
|
|
||||||
// The name of the job. It is super important that each job has a unique name,
|
// The name of the job. It is super important that each job has a unique name,
|
||||||
// because otherwise one job will overwrite another job when they're being
|
// because otherwise one job will overwrite another job when they're being
|
||||||
|
@ -126,11 +126,10 @@ With that out of the way, back to the examples:
|
||||||
|
|
||||||
##### Main
|
##### Main
|
||||||
```rust
|
```rust
|
||||||
use background_jobs::{create_server, WorkerConfig};
|
use background_jobs::{create_server, actix::WorkerConfig, BoxError};
|
||||||
use anyhow::Error;
|
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_rt::main]
|
||||||
async fn main() -> Result<(), Error> {
|
async fn main() -> Result<(), BoxError> {
|
||||||
// Set up our Storage
|
// Set up our Storage
|
||||||
// For this example, we use the default in-memory storage mechanism
|
// For this example, we use the default in-memory storage mechanism
|
||||||
use background_jobs::memory_storage::{ActixTimer, Storage};
|
use background_jobs::memory_storage::{ActixTimer, Storage};
|
||||||
|
|
|
@ -8,7 +8,6 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-rt = "2.0.0"
|
actix-rt = "2.0.0"
|
||||||
anyhow = "1.0"
|
|
||||||
background-jobs = { version = "0.17.0", path = "../..", features = [ "error-logging", "sled" ] }
|
background-jobs = { version = "0.17.0", path = "../..", features = [ "error-logging", "sled" ] }
|
||||||
tracing = "0.1"
|
tracing = "0.1"
|
||||||
tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt"] }
|
tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt"] }
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
use actix_rt::Arbiter;
|
use actix_rt::Arbiter;
|
||||||
use anyhow::Error;
|
|
||||||
use background_jobs::{
|
use background_jobs::{
|
||||||
actix::{Spawner, WorkerConfig},
|
actix::{Spawner, WorkerConfig},
|
||||||
memory_storage::{ActixTimer, Storage},
|
memory_storage::{ActixTimer, Storage},
|
||||||
MaxRetries, UnsendJob as Job,
|
BoxError, MaxRetries, UnsendJob as Job,
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
future::{ready, Ready},
|
future::{ready, Ready},
|
||||||
|
@ -26,7 +25,7 @@ pub struct MyJob {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_rt::main]
|
||||||
async fn main() -> Result<(), Error> {
|
async fn main() -> Result<(), BoxError> {
|
||||||
let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"));
|
let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"));
|
||||||
|
|
||||||
tracing_subscriber::fmt::fmt()
|
tracing_subscriber::fmt::fmt()
|
||||||
|
@ -84,8 +83,8 @@ impl MyJob {
|
||||||
|
|
||||||
impl Job for MyJob {
|
impl Job for MyJob {
|
||||||
type State = MyState;
|
type State = MyState;
|
||||||
type Error = Error;
|
type Error = BoxError;
|
||||||
type Future = Ready<Result<(), Error>>;
|
type Future = Ready<Result<(), BoxError>>;
|
||||||
type Spawner = Spawner;
|
type Spawner = Spawner;
|
||||||
|
|
||||||
// The name of the job. It is super important that each job has a unique name,
|
// The name of the job. It is super important that each job has a unique name,
|
||||||
|
|
|
@ -8,7 +8,6 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-rt = "2.0.0"
|
actix-rt = "2.0.0"
|
||||||
anyhow = "1.0"
|
|
||||||
background-jobs = { version = "0.17.0", path = "../..", features = [
|
background-jobs = { version = "0.17.0", path = "../..", features = [
|
||||||
"error-logging",
|
"error-logging",
|
||||||
"sled",
|
"sled",
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use actix_rt::Arbiter;
|
use actix_rt::Arbiter;
|
||||||
use anyhow::Error;
|
use background_jobs::{actix::WorkerConfig, sled::Storage, BoxError, Job, MaxRetries};
|
||||||
use background_jobs::{actix::WorkerConfig, sled::Storage, Job, MaxRetries};
|
|
||||||
use std::{
|
use std::{
|
||||||
future::{ready, Ready},
|
future::{ready, Ready},
|
||||||
time::{Duration, SystemTime},
|
time::{Duration, SystemTime},
|
||||||
|
@ -25,7 +24,7 @@ pub struct MyJob {
|
||||||
pub struct ErroringJob;
|
pub struct ErroringJob;
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_rt::main]
|
||||||
async fn main() -> Result<(), Error> {
|
async fn main() -> Result<(), BoxError> {
|
||||||
let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"));
|
let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"));
|
||||||
|
|
||||||
tracing_subscriber::fmt::fmt()
|
tracing_subscriber::fmt::fmt()
|
||||||
|
@ -87,8 +86,8 @@ impl MyJob {
|
||||||
|
|
||||||
impl Job for MyJob {
|
impl Job for MyJob {
|
||||||
type State = MyState;
|
type State = MyState;
|
||||||
type Error = Error;
|
type Error = BoxError;
|
||||||
type Future = Ready<Result<(), Error>>;
|
type Future = Ready<Result<(), BoxError>>;
|
||||||
|
|
||||||
// The name of the job. It is super important that each job has a unique name,
|
// The name of the job. It is super important that each job has a unique name,
|
||||||
// because otherwise one job will overwrite another job when they're being
|
// because otherwise one job will overwrite another job when they're being
|
||||||
|
@ -115,10 +114,19 @@ impl Job for MyJob {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Boom;
|
||||||
|
impl std::fmt::Display for Boom {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "boom")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl std::error::Error for Boom {}
|
||||||
|
|
||||||
impl Job for ErroringJob {
|
impl Job for ErroringJob {
|
||||||
type State = MyState;
|
type State = MyState;
|
||||||
type Error = Error;
|
type Error = Boom;
|
||||||
type Future = Ready<Result<(), Error>>;
|
type Future = Ready<Result<(), Boom>>;
|
||||||
|
|
||||||
const NAME: &'static str = "ErroringJob";
|
const NAME: &'static str = "ErroringJob";
|
||||||
|
|
||||||
|
@ -127,6 +135,6 @@ impl Job for ErroringJob {
|
||||||
const MAX_RETRIES: MaxRetries = MaxRetries::Count(0);
|
const MAX_RETRIES: MaxRetries = MaxRetries::Count(0);
|
||||||
|
|
||||||
fn run(self, _: MyState) -> Self::Future {
|
fn run(self, _: MyState) -> Self::Future {
|
||||||
ready(Err(anyhow::anyhow!("boom")))
|
ready(Err(Boom))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-rt = "2.0.0"
|
actix-rt = "2.0.0"
|
||||||
anyhow = "1.0"
|
|
||||||
background-jobs = { version = "0.17.0", path = "../..", features = [ "error-logging", "sled" ] }
|
background-jobs = { version = "0.17.0", path = "../..", features = [ "error-logging", "sled" ] }
|
||||||
tracing = "0.1"
|
tracing = "0.1"
|
||||||
tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt"] }
|
tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt"] }
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
use actix_rt::Arbiter;
|
use actix_rt::Arbiter;
|
||||||
use anyhow::Error;
|
|
||||||
use background_jobs::{
|
use background_jobs::{
|
||||||
actix::{Spawner, WorkerConfig},
|
actix::{Spawner, WorkerConfig},
|
||||||
sled::Storage,
|
sled::Storage,
|
||||||
MaxRetries, UnsendJob as Job,
|
BoxError, MaxRetries, UnsendJob as Job,
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
future::{ready, Future, Ready},
|
future::{ready, Future, Ready},
|
||||||
|
@ -30,7 +29,7 @@ pub struct MyJob {
|
||||||
pub struct LongJob;
|
pub struct LongJob;
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_rt::main]
|
||||||
async fn main() -> Result<(), Error> {
|
async fn main() -> Result<(), BoxError> {
|
||||||
let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"));
|
let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"));
|
||||||
|
|
||||||
tracing_subscriber::fmt::fmt()
|
tracing_subscriber::fmt::fmt()
|
||||||
|
@ -90,8 +89,8 @@ impl MyJob {
|
||||||
|
|
||||||
impl Job for MyJob {
|
impl Job for MyJob {
|
||||||
type State = MyState;
|
type State = MyState;
|
||||||
type Error = Error;
|
type Error = BoxError;
|
||||||
type Future = Ready<Result<(), Error>>;
|
type Future = Ready<Result<(), BoxError>>;
|
||||||
type Spawner = Spawner;
|
type Spawner = Spawner;
|
||||||
|
|
||||||
// The name of the job. It is super important that each job has a unique name,
|
// The name of the job. It is super important that each job has a unique name,
|
||||||
|
@ -121,8 +120,8 @@ impl Job for MyJob {
|
||||||
|
|
||||||
impl Job for LongJob {
|
impl Job for LongJob {
|
||||||
type State = MyState;
|
type State = MyState;
|
||||||
type Error = Error;
|
type Error = BoxError;
|
||||||
type Future = Pin<Box<dyn Future<Output = Result<(), Error>>>>;
|
type Future = Pin<Box<dyn Future<Output = Result<(), BoxError>>>>;
|
||||||
type Spawner = Spawner;
|
type Spawner = Spawner;
|
||||||
|
|
||||||
const NAME: &'static str = "LongJob";
|
const NAME: &'static str = "LongJob";
|
||||||
|
|
|
@ -8,7 +8,6 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-rt = "2.0.0"
|
actix-rt = "2.0.0"
|
||||||
anyhow = "1.0"
|
|
||||||
background-jobs = { version = "0.17.0", path = "../..", features = [ "error-logging", "sled"] }
|
background-jobs = { version = "0.17.0", path = "../..", features = [ "error-logging", "sled"] }
|
||||||
tracing = "0.1"
|
tracing = "0.1"
|
||||||
tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt"] }
|
tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt"] }
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
use actix_rt::Arbiter;
|
use actix_rt::Arbiter;
|
||||||
use anyhow::Error;
|
|
||||||
use background_jobs::{
|
use background_jobs::{
|
||||||
actix::{Spawner, WorkerConfig},
|
actix::{Spawner, WorkerConfig},
|
||||||
sled::Storage,
|
sled::Storage,
|
||||||
MaxRetries, UnsendJob as Job,
|
BoxError, MaxRetries, UnsendJob as Job,
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
future::{ready, Ready},
|
future::{ready, Ready},
|
||||||
|
@ -29,7 +28,7 @@ pub struct MyJob {
|
||||||
pub struct StopJob;
|
pub struct StopJob;
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_rt::main]
|
||||||
async fn main() -> Result<(), Error> {
|
async fn main() -> Result<(), BoxError> {
|
||||||
let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"));
|
let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"));
|
||||||
|
|
||||||
tracing_subscriber::fmt::fmt()
|
tracing_subscriber::fmt::fmt()
|
||||||
|
@ -102,8 +101,8 @@ impl MyJob {
|
||||||
|
|
||||||
impl Job for MyJob {
|
impl Job for MyJob {
|
||||||
type State = MyState;
|
type State = MyState;
|
||||||
type Error = Error;
|
type Error = BoxError;
|
||||||
type Future = Ready<Result<(), Error>>;
|
type Future = Ready<Result<(), BoxError>>;
|
||||||
type Spawner = Spawner;
|
type Spawner = Spawner;
|
||||||
|
|
||||||
// The name of the job. It is super important that each job has a unique name,
|
// The name of the job. It is super important that each job has a unique name,
|
||||||
|
@ -133,8 +132,8 @@ impl Job for MyJob {
|
||||||
|
|
||||||
impl Job for StopJob {
|
impl Job for StopJob {
|
||||||
type State = MyState;
|
type State = MyState;
|
||||||
type Error = Error;
|
type Error = BoxError;
|
||||||
type Future = Ready<Result<(), Error>>;
|
type Future = Ready<Result<(), BoxError>>;
|
||||||
type Spawner = Spawner;
|
type Spawner = Spawner;
|
||||||
|
|
||||||
const NAME: &'static str = "StopJob";
|
const NAME: &'static str = "StopJob";
|
||||||
|
|
|
@ -8,7 +8,6 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-rt = "2.0.0"
|
actix-rt = "2.0.0"
|
||||||
anyhow = "1.0"
|
|
||||||
background-jobs = { version = "0.17.0", path = "../..", features = [ "error-logging", "sled" ] }
|
background-jobs = { version = "0.17.0", path = "../..", features = [ "error-logging", "sled" ] }
|
||||||
tracing = "0.1"
|
tracing = "0.1"
|
||||||
tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt"] }
|
tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt"] }
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
use actix_rt::Arbiter;
|
use actix_rt::Arbiter;
|
||||||
use anyhow::Error;
|
|
||||||
use background_jobs::{
|
use background_jobs::{
|
||||||
actix::{Spawner, WorkerConfig},
|
actix::{Spawner, WorkerConfig},
|
||||||
metrics::MetricsStorage,
|
metrics::MetricsStorage,
|
||||||
sled::Storage,
|
sled::Storage,
|
||||||
MaxRetries, UnsendJob as Job,
|
BoxError, MaxRetries, UnsendJob as Job,
|
||||||
};
|
};
|
||||||
use std::{future::Future, pin::Pin, time::Duration};
|
use std::{future::Future, pin::Pin, time::Duration};
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
|
@ -24,7 +23,7 @@ pub struct MyJob {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_rt::main]
|
||||||
async fn main() -> Result<(), Error> {
|
async fn main() -> Result<(), BoxError> {
|
||||||
let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("warn"));
|
let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("warn"));
|
||||||
|
|
||||||
// Install the metrics subscriber
|
// Install the metrics subscriber
|
||||||
|
@ -89,8 +88,8 @@ impl MyJob {
|
||||||
|
|
||||||
impl Job for MyJob {
|
impl Job for MyJob {
|
||||||
type State = MyState;
|
type State = MyState;
|
||||||
type Error = Error;
|
type Error = BoxError;
|
||||||
type Future = Pin<Box<dyn Future<Output = Result<(), Error>> + 'static>>;
|
type Future = Pin<Box<dyn Future<Output = Result<(), BoxError>> + 'static>>;
|
||||||
type Spawner = Spawner;
|
type Spawner = Spawner;
|
||||||
|
|
||||||
// The name of the job. It is super important that each job has a unique name,
|
// The name of the job. It is super important that each job has a unique name,
|
||||||
|
|
|
@ -7,7 +7,6 @@ edition = "2021"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0"
|
|
||||||
background-jobs = { version = "0.17.0", path = "../..", default-features = false, features = [ "error-logging", "sled", "tokio" ] }
|
background-jobs = { version = "0.17.0", path = "../..", default-features = false, features = [ "error-logging", "sled", "tokio" ] }
|
||||||
time = "0.3"
|
time = "0.3"
|
||||||
tokio = { version = "1", features = ["full"] }
|
tokio = { version = "1", features = ["full"] }
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
use anyhow::Error;
|
use background_jobs::{sled::Storage, tokio::WorkerConfig, BoxError, Job, MaxRetries};
|
||||||
use background_jobs::{sled::Storage, tokio::WorkerConfig, Job, MaxRetries};
|
|
||||||
use std::{
|
use std::{
|
||||||
future::{ready, Ready},
|
future::{ready, Ready},
|
||||||
time::{Duration, SystemTime},
|
time::{Duration, SystemTime},
|
||||||
|
@ -24,7 +23,7 @@ pub struct MyJob {
|
||||||
pub struct PanickingJob;
|
pub struct PanickingJob;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), Error> {
|
async fn main() -> Result<(), BoxError> {
|
||||||
let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"));
|
let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"));
|
||||||
|
|
||||||
tracing_subscriber::fmt::fmt()
|
tracing_subscriber::fmt::fmt()
|
||||||
|
@ -83,8 +82,8 @@ impl MyJob {
|
||||||
|
|
||||||
impl Job for MyJob {
|
impl Job for MyJob {
|
||||||
type State = MyState;
|
type State = MyState;
|
||||||
type Error = Error;
|
type Error = BoxError;
|
||||||
type Future = Ready<Result<(), Error>>;
|
type Future = Ready<Result<(), BoxError>>;
|
||||||
|
|
||||||
// The name of the job. It is super important that each job has a unique name,
|
// The name of the job. It is super important that each job has a unique name,
|
||||||
// because otherwise one job will overwrite another job when they're being
|
// because otherwise one job will overwrite another job when they're being
|
||||||
|
@ -113,8 +112,8 @@ impl Job for MyJob {
|
||||||
|
|
||||||
impl Job for PanickingJob {
|
impl Job for PanickingJob {
|
||||||
type State = MyState;
|
type State = MyState;
|
||||||
type Error = Error;
|
type Error = BoxError;
|
||||||
type Future = Ready<Result<(), Error>>;
|
type Future = Ready<Result<(), BoxError>>;
|
||||||
|
|
||||||
const NAME: &'static str = "PanickingJob";
|
const NAME: &'static str = "PanickingJob";
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,6 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-rt = "2.9.0"
|
actix-rt = "2.9.0"
|
||||||
anyhow = "1.0.79"
|
|
||||||
background-jobs = { version = "0.17.0", features = ["postgres"], path = "../.." }
|
background-jobs = { version = "0.17.0", features = ["postgres"], path = "../.." }
|
||||||
serde = { version = "1.0.195", features = ["derive"] }
|
serde = { version = "1.0.195", features = ["derive"] }
|
||||||
tokio = { version = "1.35.1", features = ["full"] }
|
tokio = { version = "1.35.1", features = ["full"] }
|
||||||
|
|
|
@ -2,7 +2,7 @@ use actix_rt::Arbiter;
|
||||||
use background_jobs::{
|
use background_jobs::{
|
||||||
actix::{Spawner, WorkerConfig},
|
actix::{Spawner, WorkerConfig},
|
||||||
postgres::Storage,
|
postgres::Storage,
|
||||||
MaxRetries, UnsendJob as Job,
|
BoxError, MaxRetries, UnsendJob as Job,
|
||||||
};
|
};
|
||||||
// use background_jobs_sled_storage::Storage;
|
// use background_jobs_sled_storage::Storage;
|
||||||
use std::{
|
use std::{
|
||||||
|
@ -26,7 +26,7 @@ pub struct MyJob {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_rt::main]
|
||||||
async fn main() -> anyhow::Result<()> {
|
async fn main() -> Result<(), BoxError> {
|
||||||
let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"));
|
let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"));
|
||||||
|
|
||||||
tracing_subscriber::fmt::fmt()
|
tracing_subscriber::fmt::fmt()
|
||||||
|
@ -90,8 +90,8 @@ impl MyJob {
|
||||||
|
|
||||||
impl Job for MyJob {
|
impl Job for MyJob {
|
||||||
type State = MyState;
|
type State = MyState;
|
||||||
type Error = anyhow::Error;
|
type Error = BoxError;
|
||||||
type Future = Ready<anyhow::Result<()>>;
|
type Future = Ready<Result<(), BoxError>>;
|
||||||
type Spawner = Spawner;
|
type Spawner = Spawner;
|
||||||
|
|
||||||
// The name of the job. It is super important that each job has a unique name,
|
// The name of the job. It is super important that each job has a unique name,
|
||||||
|
|
|
@ -7,7 +7,6 @@ edition = "2021"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0"
|
|
||||||
background-jobs = { version = "0.17.0", path = "../..", default-features = false, features = [ "error-logging", "sled", "tokio"] }
|
background-jobs = { version = "0.17.0", path = "../..", default-features = false, features = [ "error-logging", "sled", "tokio"] }
|
||||||
tokio = { version = "1", features = ["full"] }
|
tokio = { version = "1", features = ["full"] }
|
||||||
tracing = "0.1"
|
tracing = "0.1"
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
use anyhow::Error;
|
|
||||||
use background_jobs::{
|
use background_jobs::{
|
||||||
memory_storage::{Storage, TokioTimer},
|
memory_storage::{Storage, TokioTimer},
|
||||||
tokio::WorkerConfig,
|
tokio::WorkerConfig,
|
||||||
Job, MaxRetries,
|
BoxError, Job, MaxRetries,
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
future::{ready, Ready},
|
future::{ready, Ready},
|
||||||
|
@ -25,7 +24,7 @@ pub struct MyJob {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), Error> {
|
async fn main() -> Result<(), BoxError> {
|
||||||
let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"));
|
let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"));
|
||||||
|
|
||||||
tracing_subscriber::fmt::fmt()
|
tracing_subscriber::fmt::fmt()
|
||||||
|
@ -79,8 +78,8 @@ impl MyJob {
|
||||||
|
|
||||||
impl Job for MyJob {
|
impl Job for MyJob {
|
||||||
type State = MyState;
|
type State = MyState;
|
||||||
type Error = Error;
|
type Error = BoxError;
|
||||||
type Future = Ready<Result<(), Error>>;
|
type Future = Ready<Result<(), BoxError>>;
|
||||||
|
|
||||||
// The name of the job. It is super important that each job has a unique name,
|
// The name of the job. It is super important that each job has a unique name,
|
||||||
// because otherwise one job will overwrite another job when they're being
|
// because otherwise one job will overwrite another job when they're being
|
||||||
|
|
|
@ -11,7 +11,6 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-rt = "2.5.1"
|
actix-rt = "2.5.1"
|
||||||
anyhow = "1.0"
|
|
||||||
async-trait = "0.1.24"
|
async-trait = "0.1.24"
|
||||||
background-jobs-core = { version = "0.17.0", path = "../jobs-core" }
|
background-jobs-core = { version = "0.17.0", path = "../jobs-core" }
|
||||||
metrics = "0.22.0"
|
metrics = "0.22.0"
|
||||||
|
|
|
@ -12,8 +12,7 @@
|
||||||
//!
|
//!
|
||||||
//! ### Example
|
//! ### Example
|
||||||
//! ```rust
|
//! ```rust
|
||||||
//! use anyhow::Error;
|
//! use background_jobs_core::{Backoff, Job, MaxRetries, BoxError};
|
||||||
//! use background_jobs_core::{Backoff, Job, MaxRetries};
|
|
||||||
//! use background_jobs_actix::{ActixTimer, WorkerConfig};
|
//! use background_jobs_actix::{ActixTimer, WorkerConfig};
|
||||||
//! use std::future::{ready, Ready};
|
//! use std::future::{ready, Ready};
|
||||||
//!
|
//!
|
||||||
|
@ -31,7 +30,7 @@
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! #[actix_rt::main]
|
//! #[actix_rt::main]
|
||||||
//! async fn main() -> Result<(), Error> {
|
//! async fn main() -> Result<(), BoxError> {
|
||||||
//! // Set up our Storage
|
//! // Set up our Storage
|
||||||
//! // For this example, we use the default in-memory storage mechanism
|
//! // For this example, we use the default in-memory storage mechanism
|
||||||
//! use background_jobs_core::memory_storage::Storage;
|
//! use background_jobs_core::memory_storage::Storage;
|
||||||
|
@ -72,7 +71,7 @@
|
||||||
//!
|
//!
|
||||||
//! impl Job for MyJob {
|
//! impl Job for MyJob {
|
||||||
//! type State = MyState;
|
//! type State = MyState;
|
||||||
//! type Future = Ready<Result<(), Error>>;
|
//! type Future = Ready<Result<(), BoxError>>;
|
||||||
//!
|
//!
|
||||||
//! // The name of the job. It is super important that each job has a unique name,
|
//! // The name of the job. It is super important that each job has a unique name,
|
||||||
//! // because otherwise one job will overwrite another job when they're being
|
//! // because otherwise one job will overwrite another job when they're being
|
||||||
|
@ -114,9 +113,8 @@
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
use actix_rt::{Arbiter, ArbiterHandle};
|
use actix_rt::{Arbiter, ArbiterHandle};
|
||||||
use anyhow::Error;
|
|
||||||
use background_jobs_core::{
|
use background_jobs_core::{
|
||||||
memory_storage::Timer, new_job, new_scheduled_job, Job, ProcessorMap, Storage,
|
memory_storage::Timer, new_job, new_scheduled_job, BoxError, Job, ProcessorMap, Storage,
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
collections::BTreeMap,
|
collections::BTreeMap,
|
||||||
|
@ -469,7 +467,7 @@ impl QueueHandle {
|
||||||
///
|
///
|
||||||
/// This job will be sent to the server for storage, and will execute whenever a worker for the
|
/// This job will be sent to the server for storage, and will execute whenever a worker for the
|
||||||
/// job's queue is free to do so.
|
/// job's queue is free to do so.
|
||||||
pub async fn queue<J>(&self, job: J) -> Result<(), Error>
|
pub async fn queue<J>(&self, job: J) -> Result<(), BoxError>
|
||||||
where
|
where
|
||||||
J: Job,
|
J: Job,
|
||||||
{
|
{
|
||||||
|
@ -482,7 +480,7 @@ impl QueueHandle {
|
||||||
///
|
///
|
||||||
/// This job will be sent to the server for storage, and will execute after the specified time
|
/// This job will be sent to the server for storage, and will execute after the specified time
|
||||||
/// and when a worker for the job's queue is free to do so.
|
/// and when a worker for the job's queue is free to do so.
|
||||||
pub async fn schedule<J>(&self, job: J, after: SystemTime) -> Result<(), Error>
|
pub async fn schedule<J>(&self, job: J, after: SystemTime) -> Result<(), BoxError>
|
||||||
where
|
where
|
||||||
J: Job,
|
J: Job,
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,16 +1,15 @@
|
||||||
use anyhow::Error;
|
use background_jobs_core::{BoxError, JobInfo, NewJobInfo, ReturnJobInfo, Storage};
|
||||||
use background_jobs_core::{JobInfo, NewJobInfo, ReturnJobInfo, Storage};
|
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
pub(crate) trait ActixStorage {
|
pub(crate) trait ActixStorage {
|
||||||
async fn push(&self, job: NewJobInfo) -> Result<Uuid, Error>;
|
async fn push(&self, job: NewJobInfo) -> Result<Uuid, BoxError>;
|
||||||
|
|
||||||
async fn pop(&self, queue: &str, runner_id: Uuid) -> Result<JobInfo, Error>;
|
async fn pop(&self, queue: &str, runner_id: Uuid) -> Result<JobInfo, BoxError>;
|
||||||
|
|
||||||
async fn heartbeat(&self, job_id: Uuid, runner_id: Uuid) -> Result<(), Error>;
|
async fn heartbeat(&self, job_id: Uuid, runner_id: Uuid) -> Result<(), BoxError>;
|
||||||
|
|
||||||
async fn complete(&self, ret: ReturnJobInfo) -> Result<(), Error>;
|
async fn complete(&self, ret: ReturnJobInfo) -> Result<(), BoxError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct StorageWrapper<S>(pub(crate) S)
|
pub(crate) struct StorageWrapper<S>(pub(crate) S)
|
||||||
|
@ -24,19 +23,19 @@ where
|
||||||
S: Storage + Send + Sync,
|
S: Storage + Send + Sync,
|
||||||
S::Error: Send + Sync + 'static,
|
S::Error: Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
async fn push(&self, job: NewJobInfo) -> Result<Uuid, Error> {
|
async fn push(&self, job: NewJobInfo) -> Result<Uuid, BoxError> {
|
||||||
Ok(self.0.push(job).await?)
|
Ok(self.0.push(job).await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn pop(&self, queue: &str, runner_id: Uuid) -> Result<JobInfo, Error> {
|
async fn pop(&self, queue: &str, runner_id: Uuid) -> Result<JobInfo, BoxError> {
|
||||||
Ok(self.0.pop(queue, runner_id).await?)
|
Ok(self.0.pop(queue, runner_id).await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn heartbeat(&self, job_id: Uuid, runner_id: Uuid) -> Result<(), Error> {
|
async fn heartbeat(&self, job_id: Uuid, runner_id: Uuid) -> Result<(), BoxError> {
|
||||||
Ok(self.0.heartbeat(job_id, runner_id).await?)
|
Ok(self.0.heartbeat(job_id, runner_id).await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn complete(&self, ret: ReturnJobInfo) -> Result<(), Error> {
|
async fn complete(&self, ret: ReturnJobInfo) -> Result<(), BoxError> {
|
||||||
self.0.complete(ret).await?;
|
self.0.complete(ret).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -18,7 +18,6 @@ completion-logging = []
|
||||||
error-logging = []
|
error-logging = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0"
|
|
||||||
async-trait = "0.1.24"
|
async-trait = "0.1.24"
|
||||||
event-listener = "4"
|
event-listener = "4"
|
||||||
metrics = "0.22.0"
|
metrics = "0.22.0"
|
||||||
|
|
71
jobs-core/src/box_error.rs
Normal file
71
jobs-core/src/box_error.rs
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
/// A simple error box that provides no additional formatting utilities
|
||||||
|
pub struct BoxError {
|
||||||
|
error: Box<dyn std::error::Error + Send + Sync>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Debug for BoxError {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
self.error.fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for BoxError {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
self.error.fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E> From<E> for BoxError
|
||||||
|
where
|
||||||
|
E: std::error::Error + Send + Sync + 'static,
|
||||||
|
{
|
||||||
|
fn from(error: E) -> Self {
|
||||||
|
BoxError {
|
||||||
|
error: Box::new(error),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<BoxError> for Box<dyn std::error::Error + Send + Sync> {
|
||||||
|
fn from(value: BoxError) -> Self {
|
||||||
|
value.error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<BoxError> for Box<dyn std::error::Error + Send> {
|
||||||
|
fn from(value: BoxError) -> Self {
|
||||||
|
value.error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<BoxError> for Box<dyn std::error::Error> {
|
||||||
|
fn from(value: BoxError) -> Self {
|
||||||
|
value.error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsRef<dyn std::error::Error + Send + Sync> for BoxError {
|
||||||
|
fn as_ref(&self) -> &(dyn std::error::Error + Send + Sync + 'static) {
|
||||||
|
self.error.as_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsRef<dyn std::error::Error + Send> for BoxError {
|
||||||
|
fn as_ref(&self) -> &(dyn std::error::Error + Send + 'static) {
|
||||||
|
self.error.as_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsRef<dyn std::error::Error> for BoxError {
|
||||||
|
fn as_ref(&self) -> &(dyn std::error::Error + 'static) {
|
||||||
|
self.error.as_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::Deref for BoxError {
|
||||||
|
type Target = dyn std::error::Error + Send + Sync;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
self.error.as_ref()
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,4 @@
|
||||||
use crate::{Backoff, JobError, MaxRetries, NewJobInfo};
|
use crate::{Backoff, BoxError, JobError, MaxRetries, NewJobInfo};
|
||||||
use anyhow::Error;
|
|
||||||
use serde::{de::DeserializeOwned, ser::Serialize};
|
use serde::{de::DeserializeOwned, ser::Serialize};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use std::{future::Future, pin::Pin, time::SystemTime};
|
use std::{future::Future, pin::Pin, time::SystemTime};
|
||||||
|
@ -15,8 +14,7 @@ use tracing::{Instrument, Span};
|
||||||
/// ### Example
|
/// ### Example
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use anyhow::Error;
|
/// use background_jobs_core::{Job, new_job, BoxError};
|
||||||
/// use background_jobs_core::{Job, new_job};
|
|
||||||
/// use tracing::info;
|
/// use tracing::info;
|
||||||
/// use std::future::{ready, Ready};
|
/// use std::future::{ready, Ready};
|
||||||
///
|
///
|
||||||
|
@ -27,7 +25,8 @@ use tracing::{Instrument, Span};
|
||||||
///
|
///
|
||||||
/// impl Job for MyJob {
|
/// impl Job for MyJob {
|
||||||
/// type State = ();
|
/// type State = ();
|
||||||
/// type Future = Ready<Result<(), Error>>;
|
/// type Error = BoxError;
|
||||||
|
/// type Future = Ready<Result<(), BoxError>>;
|
||||||
///
|
///
|
||||||
/// const NAME: &'static str = "MyJob";
|
/// const NAME: &'static str = "MyJob";
|
||||||
///
|
///
|
||||||
|
@ -38,7 +37,7 @@ use tracing::{Instrument, Span};
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// fn main() -> Result<(), Error> {
|
/// fn main() -> Result<(), BoxError> {
|
||||||
/// let job = new_job(MyJob { count: 1234 })?;
|
/// let job = new_job(MyJob { count: 1234 })?;
|
||||||
///
|
///
|
||||||
/// Ok(())
|
/// Ok(())
|
||||||
|
@ -49,7 +48,7 @@ pub trait Job: Serialize + DeserializeOwned + 'static {
|
||||||
type State: Clone + 'static;
|
type State: Clone + 'static;
|
||||||
|
|
||||||
/// The error type this job returns
|
/// The error type this job returns
|
||||||
type Error: Into<Box<dyn std::error::Error>>;
|
type Error: Into<BoxError>;
|
||||||
|
|
||||||
/// The future returned by this job
|
/// The future returned by this job
|
||||||
type Future: Future<Output = Result<(), Self::Error>> + Send;
|
type Future: Future<Output = Result<(), Self::Error>> + Send;
|
||||||
|
@ -130,7 +129,7 @@ pub trait Job: Serialize + DeserializeOwned + 'static {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A provided method to create a new JobInfo from provided arguments
|
/// A provided method to create a new JobInfo from provided arguments
|
||||||
pub fn new_job<J>(job: J) -> Result<NewJobInfo, Error>
|
pub fn new_job<J>(job: J) -> Result<NewJobInfo, BoxError>
|
||||||
where
|
where
|
||||||
J: Job,
|
J: Job,
|
||||||
{
|
{
|
||||||
|
@ -147,7 +146,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a NewJobInfo to schedule a job to be performed after a certain time
|
/// Create a NewJobInfo to schedule a job to be performed after a certain time
|
||||||
pub fn new_scheduled_job<J>(job: J, after: SystemTime) -> Result<NewJobInfo, Error>
|
pub fn new_scheduled_job<J>(job: J, after: SystemTime) -> Result<NewJobInfo, BoxError>
|
||||||
where
|
where
|
||||||
J: Job,
|
J: Job,
|
||||||
{
|
{
|
||||||
|
@ -178,13 +177,13 @@ where
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
let (fut, span) = res?;
|
let (fut, span) = res?;
|
||||||
|
|
||||||
if let Some(span) = span {
|
let res = if let Some(span) = span {
|
||||||
fut.instrument(span).await.map_err(Into::into)?;
|
fut.instrument(span).await
|
||||||
} else {
|
} else {
|
||||||
fut.await.map_err(Into::into)?;
|
fut.await
|
||||||
}
|
};
|
||||||
|
|
||||||
Ok(())
|
res.map_err(Into::into).map_err(JobError::Processing)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
//! This crate shouldn't be depended on directly, except in the case of implementing a custom jobs
|
//! This crate shouldn't be depended on directly, except in the case of implementing a custom jobs
|
||||||
//! processor. For a default solution based on Actix and Sled, look at the `background-jobs` crate.
|
//! processor. For a default solution based on Actix and Sled, look at the `background-jobs` crate.
|
||||||
|
|
||||||
|
mod box_error;
|
||||||
mod catch_unwind;
|
mod catch_unwind;
|
||||||
mod job;
|
mod job;
|
||||||
mod job_info;
|
mod job_info;
|
||||||
|
@ -14,6 +15,7 @@ mod storage;
|
||||||
mod unsend_job;
|
mod unsend_job;
|
||||||
|
|
||||||
pub use crate::{
|
pub use crate::{
|
||||||
|
box_error::BoxError,
|
||||||
job::{new_job, new_scheduled_job, process, Job},
|
job::{new_job, new_scheduled_job, process, Job},
|
||||||
job_info::{JobInfo, NewJobInfo, ReturnJobInfo},
|
job_info::{JobInfo, NewJobInfo, ReturnJobInfo},
|
||||||
processor_map::{CachedProcessorMap, ProcessorMap},
|
processor_map::{CachedProcessorMap, ProcessorMap},
|
||||||
|
@ -27,7 +29,7 @@ pub use unsend_job::{JoinError, UnsendJob, UnsendSpawner};
|
||||||
pub enum JobError {
|
pub enum JobError {
|
||||||
/// Some error occurred while processing the job
|
/// Some error occurred while processing the job
|
||||||
#[error("{0}")]
|
#[error("{0}")]
|
||||||
Processing(#[from] Box<dyn std::error::Error>),
|
Processing(#[from] BoxError),
|
||||||
|
|
||||||
/// Creating a `Job` type from the provided `serde_json::Value` failed
|
/// Creating a `Job` type from the provided `serde_json::Value` failed
|
||||||
#[error("Could not make JSON value from arguments")]
|
#[error("Could not make JSON value from arguments")]
|
||||||
|
|
|
@ -188,10 +188,11 @@ where
|
||||||
ReturnJobInfo::pass(id)
|
ReturnJobInfo::pass(id)
|
||||||
}
|
}
|
||||||
Ok(Err(e)) => {
|
Ok(Err(e)) => {
|
||||||
let display = format!("{}", e);
|
let display = format!("{e}");
|
||||||
let debug = format!("{:?}", e);
|
|
||||||
span.record("exception.message", &tracing::field::display(&display));
|
span.record("exception.message", &tracing::field::display(&display));
|
||||||
|
let debug = format!("{e:?}");
|
||||||
span.record("exception.details", &tracing::field::display(&debug));
|
span.record("exception.details", &tracing::field::display(&debug));
|
||||||
|
|
||||||
#[cfg(feature = "error-logging")]
|
#[cfg(feature = "error-logging")]
|
||||||
tracing::warn!("Job {queue}: {name}-{id} errored");
|
tracing::warn!("Job {queue}: {name}-{id} errored");
|
||||||
ReturnJobInfo::fail(id)
|
ReturnJobInfo::fail(id)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{Backoff, Job, MaxRetries};
|
use crate::{Backoff, BoxError, Job, MaxRetries};
|
||||||
use serde::{de::DeserializeOwned, ser::Serialize};
|
use serde::{de::DeserializeOwned, ser::Serialize};
|
||||||
use std::{
|
use std::{
|
||||||
fmt::Debug,
|
fmt::Debug,
|
||||||
|
@ -45,7 +45,7 @@ pub trait UnsendJob: Serialize + DeserializeOwned + 'static {
|
||||||
type State: Clone + 'static;
|
type State: Clone + 'static;
|
||||||
|
|
||||||
/// The error type this job returns
|
/// The error type this job returns
|
||||||
type Error: Into<Box<dyn std::error::Error>> + Send;
|
type Error: Into<BoxError>;
|
||||||
|
|
||||||
/// The future returned by this job
|
/// The future returned by this job
|
||||||
///
|
///
|
||||||
|
@ -150,7 +150,7 @@ where
|
||||||
T: UnsendJob,
|
T: UnsendJob,
|
||||||
{
|
{
|
||||||
type State = T::State;
|
type State = T::State;
|
||||||
type Error = T::Error;
|
type Error = BoxError;
|
||||||
type Future = UnwrapFuture<<T::Spawner as UnsendSpawner>::Handle<Result<(), Self::Error>>>;
|
type Future = UnwrapFuture<<T::Spawner as UnsendSpawner>::Handle<Result<(), Self::Error>>>;
|
||||||
|
|
||||||
const NAME: &'static str = <Self as UnsendJob>::NAME;
|
const NAME: &'static str = <Self as UnsendJob>::NAME;
|
||||||
|
@ -161,7 +161,8 @@ where
|
||||||
|
|
||||||
fn run(self, state: Self::State) -> Self::Future {
|
fn run(self, state: Self::State) -> Self::Future {
|
||||||
UnwrapFuture(T::Spawner::spawn(
|
UnwrapFuture(T::Spawner::spawn(
|
||||||
UnsendJob::run(self, state).instrument(Span::current()),
|
async move { UnsendJob::run(self, state).await.map_err(Into::into) }
|
||||||
|
.instrument(Span::current()),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,6 @@ edition = "2021"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.79"
|
|
||||||
async-trait = "0.1.77"
|
async-trait = "0.1.77"
|
||||||
background-jobs-core = { version = "0.17.0", path = "../jobs-core" }
|
background-jobs-core = { version = "0.17.0", path = "../jobs-core" }
|
||||||
metrics = "0.22.0"
|
metrics = "0.22.0"
|
||||||
|
|
|
@ -12,8 +12,7 @@
|
||||||
//!
|
//!
|
||||||
//! ### Example
|
//! ### Example
|
||||||
//! ```rust
|
//! ```rust
|
||||||
//! use anyhow::Error;
|
//! use background_jobs_core::{Backoff, Job, MaxRetries, BoxError};
|
||||||
//! use background_jobs_core::{Backoff, Job, MaxRetries};
|
|
||||||
//! use background_jobs_tokio::{TokioTimer, WorkerConfig};
|
//! use background_jobs_tokio::{TokioTimer, WorkerConfig};
|
||||||
//! use std::future::{ready, Ready};
|
//! use std::future::{ready, Ready};
|
||||||
//!
|
//!
|
||||||
|
@ -31,7 +30,7 @@
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! #[tokio::main]
|
//! #[tokio::main]
|
||||||
//! async fn main() -> Result<(), Error> {
|
//! async fn main() -> Result<(), BoxError> {
|
||||||
//! // Set up our Storage
|
//! // Set up our Storage
|
||||||
//! // For this example, we use the default in-memory storage mechanism
|
//! // For this example, we use the default in-memory storage mechanism
|
||||||
//! use background_jobs_core::memory_storage::Storage;
|
//! use background_jobs_core::memory_storage::Storage;
|
||||||
|
@ -74,7 +73,7 @@
|
||||||
//!
|
//!
|
||||||
//! impl Job for MyJob {
|
//! impl Job for MyJob {
|
||||||
//! type State = MyState;
|
//! type State = MyState;
|
||||||
//! type Future = Ready<Result<(), Error>>;
|
//! type Future = Ready<Result<(), BoxError>>;
|
||||||
//!
|
//!
|
||||||
//! // The name of the job. It is super important that each job has a unique name,
|
//! // The name of the job. It is super important that each job has a unique name,
|
||||||
//! // because otherwise one job will overwrite another job when they're being
|
//! // because otherwise one job will overwrite another job when they're being
|
||||||
|
@ -115,9 +114,9 @@
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
use anyhow::Error;
|
|
||||||
use background_jobs_core::{
|
use background_jobs_core::{
|
||||||
memory_storage::Timer, new_job, new_scheduled_job, Job, ProcessorMap, Storage as StorageTrait,
|
memory_storage::Timer, new_job, new_scheduled_job, BoxError, Job, ProcessorMap,
|
||||||
|
Storage as StorageTrait,
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
collections::{BTreeMap, HashMap},
|
collections::{BTreeMap, HashMap},
|
||||||
|
@ -314,7 +313,7 @@ impl QueueHandle {
|
||||||
///
|
///
|
||||||
/// This job will be sent to the server for storage, and will execute whenever a worker for the
|
/// This job will be sent to the server for storage, and will execute whenever a worker for the
|
||||||
/// job's queue is free to do so.
|
/// job's queue is free to do so.
|
||||||
pub async fn queue<J>(&self, job: J) -> Result<(), Error>
|
pub async fn queue<J>(&self, job: J) -> Result<(), BoxError>
|
||||||
where
|
where
|
||||||
J: Job,
|
J: Job,
|
||||||
{
|
{
|
||||||
|
@ -327,7 +326,7 @@ impl QueueHandle {
|
||||||
///
|
///
|
||||||
/// This job will be sent to the server for storage, and will execute after the specified time
|
/// This job will be sent to the server for storage, and will execute after the specified time
|
||||||
/// and when a worker for the job's queue is free to do so.
|
/// and when a worker for the job's queue is free to do so.
|
||||||
pub async fn schedule<J>(&self, job: J, after: SystemTime) -> Result<(), Error>
|
pub async fn schedule<J>(&self, job: J, after: SystemTime) -> Result<(), BoxError>
|
||||||
where
|
where
|
||||||
J: Job,
|
J: Job,
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
use std::{ops::Deref, sync::Arc};
|
use std::{ops::Deref, sync::Arc};
|
||||||
|
|
||||||
use background_jobs_core::{JobInfo, NewJobInfo, ReturnJobInfo, Storage as StorageTrait};
|
use background_jobs_core::{BoxError, JobInfo, NewJobInfo, ReturnJobInfo, Storage as StorageTrait};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
pub trait TokioStorage: Send + Sync {
|
pub trait TokioStorage: Send + Sync {
|
||||||
async fn push(&self, job: NewJobInfo) -> anyhow::Result<Uuid>;
|
async fn push(&self, job: NewJobInfo) -> Result<Uuid, BoxError>;
|
||||||
|
|
||||||
async fn pop(&self, queue: &str, runner_id: Uuid) -> anyhow::Result<JobInfo>;
|
async fn pop(&self, queue: &str, runner_id: Uuid) -> Result<JobInfo, BoxError>;
|
||||||
|
|
||||||
async fn heartbeat(&self, job_id: Uuid, worker_id: Uuid) -> anyhow::Result<()>;
|
async fn heartbeat(&self, job_id: Uuid, worker_id: Uuid) -> Result<(), BoxError>;
|
||||||
|
|
||||||
async fn complete(&self, return_job_info: ReturnJobInfo) -> anyhow::Result<()>;
|
async fn complete(&self, return_job_info: ReturnJobInfo) -> Result<(), BoxError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -26,19 +26,22 @@ impl<S> TokioStorage for StorageWrapper<S>
|
||||||
where
|
where
|
||||||
S: StorageTrait + Send + Sync + 'static,
|
S: StorageTrait + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
async fn push(&self, job: NewJobInfo) -> anyhow::Result<Uuid> {
|
async fn push(&self, job: NewJobInfo) -> Result<Uuid, BoxError> {
|
||||||
self.0.push(job).await.map_err(From::from)
|
self.0.push(job).await.map_err(From::from)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn pop(&self, queue: &str, runner_id: Uuid) -> anyhow::Result<JobInfo> {
|
async fn pop(&self, queue: &str, runner_id: Uuid) -> Result<JobInfo, BoxError> {
|
||||||
self.0.pop(queue, runner_id).await.map_err(From::from)
|
self.0.pop(queue, runner_id).await.map_err(From::from)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn heartbeat(&self, job_id: Uuid, runner_id: Uuid) -> anyhow::Result<()> {
|
async fn heartbeat(&self, job_id: Uuid, runner_id: Uuid) -> Result<(), BoxError> {
|
||||||
self.0.heartbeat(job_id, runner_id).await.map_err(From::from)
|
self.0
|
||||||
|
.heartbeat(job_id, runner_id)
|
||||||
|
.await
|
||||||
|
.map_err(From::from)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn complete(&self, return_job_info: ReturnJobInfo) -> anyhow::Result<()> {
|
async fn complete(&self, return_job_info: ReturnJobInfo) -> Result<(), BoxError> {
|
||||||
self.0
|
self.0
|
||||||
.complete(return_job_info)
|
.complete(return_job_info)
|
||||||
.await
|
.await
|
||||||
|
|
20
src/lib.rs
20
src/lib.rs
|
@ -29,7 +29,6 @@
|
||||||
//! ```toml
|
//! ```toml
|
||||||
//! [dependencies]
|
//! [dependencies]
|
||||||
//! actix-rt = "2.6.0"
|
//! actix-rt = "2.6.0"
|
||||||
//! anyhow = "1.0"
|
|
||||||
//! background-jobs = "0.15.0"
|
//! background-jobs = "0.15.0"
|
||||||
//! serde = { version = "1.0", features = ["derive"] }
|
//! serde = { version = "1.0", features = ["derive"] }
|
||||||
//! ```
|
//! ```
|
||||||
|
@ -39,8 +38,7 @@
|
||||||
//! operation. They implment the `Job`, `serde::Serialize`, and `serde::DeserializeOwned`.
|
//! operation. They implment the `Job`, `serde::Serialize`, and `serde::DeserializeOwned`.
|
||||||
//!
|
//!
|
||||||
//! ```rust,ignore
|
//! ```rust,ignore
|
||||||
//! use anyhow::Error;
|
//! use background_jobs::[Job, BoxError};
|
||||||
//! use background_jobs::Job;
|
|
||||||
//! use std::future::{ready, Ready};
|
//! use std::future::{ready, Ready};
|
||||||
//!
|
//!
|
||||||
//! #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
//! #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
||||||
|
@ -60,7 +58,8 @@
|
||||||
//!
|
//!
|
||||||
//! impl Job for MyJob {
|
//! impl Job for MyJob {
|
||||||
//! type State = ();
|
//! type State = ();
|
||||||
//! type Future = Ready<Result<(), Error>>;
|
//! type Error = BoxError;
|
||||||
|
//! type Future = Ready<Result<(), BoxError>>;
|
||||||
//!
|
//!
|
||||||
//! const NAME: &'static str = "MyJob";
|
//! const NAME: &'static str = "MyJob";
|
||||||
//!
|
//!
|
||||||
|
@ -80,8 +79,7 @@
|
||||||
//! Let's re-define the job to care about some application state.
|
//! Let's re-define the job to care about some application state.
|
||||||
//!
|
//!
|
||||||
//! ```rust,ignore
|
//! ```rust,ignore
|
||||||
//! use anyhow::Error;
|
//! use background_jobs::[Job, BoxError};
|
||||||
//! use background_jobs::Job;
|
|
||||||
//! use std::future::{ready, Ready};
|
//! use std::future::{ready, Ready};
|
||||||
//!
|
//!
|
||||||
//! #[derive(Clone, Debug)]
|
//! #[derive(Clone, Debug)]
|
||||||
|
@ -99,7 +97,8 @@
|
||||||
//!
|
//!
|
||||||
//! impl Job for MyJob {
|
//! impl Job for MyJob {
|
||||||
//! type State = MyState;
|
//! type State = MyState;
|
||||||
//! type Future = Ready<Result<(), Error>>;
|
//! type Error = BoxError;
|
||||||
|
//! type Future = Ready<Result<(), BoxError>>;
|
||||||
//!
|
//!
|
||||||
//! const NAME: &'static str = "MyJob";
|
//! const NAME: &'static str = "MyJob";
|
||||||
//!
|
//!
|
||||||
|
@ -123,11 +122,10 @@
|
||||||
//!
|
//!
|
||||||
//! ##### Main
|
//! ##### Main
|
||||||
//! ```rust,ignore
|
//! ```rust,ignore
|
||||||
//! use anyhow::Error;
|
//! use background_jobs::{ServerConfig, memory_storage::Storage, actix::WorkerConfig, BoxError};
|
||||||
//! use background_jobs::{ServerConfig, memory_storage::Storage, WorkerConfig};
|
|
||||||
//!
|
//!
|
||||||
//! #[actix_rt::main]
|
//! #[actix_rt::main]
|
||||||
//! async fn main() -> Result<(), Error> {
|
//! async fn main() -> Result<(), BoxError> {
|
||||||
//! // Set up our Storage
|
//! // Set up our Storage
|
||||||
//! let storage = Storage::new();
|
//! let storage = Storage::new();
|
||||||
//!
|
//!
|
||||||
|
@ -173,7 +171,7 @@
|
||||||
//! | `completion-logging` | Enables a tracing event that occurs whenever a job completes |
|
//! | `completion-logging` | Enables a tracing event that occurs whenever a job completes |
|
||||||
//! | `error-logging` | Enables a tracing event that occurs whenever a job fails |
|
//! | `error-logging` | Enables a tracing event that occurs whenever a job fails |
|
||||||
|
|
||||||
pub use background_jobs_core::{Backoff, Job, MaxRetries, UnsendJob, UnsendSpawner};
|
pub use background_jobs_core::{Backoff, BoxError, Job, MaxRetries, UnsendJob, UnsendSpawner};
|
||||||
|
|
||||||
#[cfg(feature = "metrics")]
|
#[cfg(feature = "metrics")]
|
||||||
pub mod metrics {
|
pub mod metrics {
|
||||||
|
|
Loading…
Reference in a new issue