mirror of
https://git.asonix.dog/asonix/relay.git
synced 2024-11-25 02:51:12 +00:00
Update background-jobs, rework errors
This commit is contained in:
parent
ed399f1531
commit
b074759eb4
19 changed files with 189 additions and 140 deletions
69
Cargo.lock
generated
69
Cargo.lock
generated
|
@ -389,12 +389,12 @@ dependencies = [
|
||||||
"actix-web",
|
"actix-web",
|
||||||
"actix-webfinger",
|
"actix-webfinger",
|
||||||
"ammonia",
|
"ammonia",
|
||||||
"anyhow",
|
|
||||||
"async-cpupool",
|
"async-cpupool",
|
||||||
"background-jobs",
|
"background-jobs",
|
||||||
"base64",
|
"base64",
|
||||||
"bcrypt",
|
"bcrypt",
|
||||||
"clap",
|
"clap",
|
||||||
|
"color-eyre",
|
||||||
"config",
|
"config",
|
||||||
"console-subscriber",
|
"console-subscriber",
|
||||||
"dashmap",
|
"dashmap",
|
||||||
|
@ -564,9 +564,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "background-jobs"
|
name = "background-jobs"
|
||||||
version = "0.17.0"
|
version = "0.18.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "65f83277b60c9c889210ef54207cca1a8f7e6de916ad616ce4140d477c8a6094"
|
checksum = "50954581739942ccbf39f7723a250dd3044c32de2e2c7e5f8cf53cb35200136b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"background-jobs-core",
|
"background-jobs-core",
|
||||||
"background-jobs-metrics",
|
"background-jobs-metrics",
|
||||||
|
@ -575,11 +575,10 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "background-jobs-core"
|
name = "background-jobs-core"
|
||||||
version = "0.17.0"
|
version = "0.18.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "50ac54b76a9cb9bdf6bdb7a485181e9f9ab95e930aa34b6a74ebda76d04d6b11"
|
checksum = "dc0f2054eb1262a98306ef87d115c368aa1d38ecdf1cc5af08021e13eb0e55a8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"event-listener",
|
"event-listener",
|
||||||
"metrics",
|
"metrics",
|
||||||
|
@ -593,9 +592,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "background-jobs-metrics"
|
name = "background-jobs-metrics"
|
||||||
version = "0.17.0"
|
version = "0.18.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "119b921bdadd3bd666f8418054933e33b9d279203b8029c5881e3174c2821f79"
|
checksum = "617da80f3fe8fe9b042d07cab58cf92ba3098b2112c4c499a27f333ebab401d2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"background-jobs-core",
|
"background-jobs-core",
|
||||||
|
@ -607,11 +606,10 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "background-jobs-tokio"
|
name = "background-jobs-tokio"
|
||||||
version = "0.17.0"
|
version = "0.18.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d18cbc0bda6c07ffca4146ac88d93f93f93f374012a0c425c3a8b7fd34ccce4e"
|
checksum = "35759bf19b8b461e8d079f60565bf2ff8a76de36cdbe44d14de34cf4ae15c065"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"background-jobs-core",
|
"background-jobs-core",
|
||||||
"metrics",
|
"metrics",
|
||||||
|
@ -864,6 +862,33 @@ version = "0.6.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
|
checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "color-eyre"
|
||||||
|
version = "0.6.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5a667583cca8c4f8436db8de46ea8233c42a7d9ae424a82d338f2e4675229204"
|
||||||
|
dependencies = [
|
||||||
|
"backtrace",
|
||||||
|
"color-spantrace",
|
||||||
|
"eyre",
|
||||||
|
"indenter",
|
||||||
|
"once_cell",
|
||||||
|
"owo-colors",
|
||||||
|
"tracing-error",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "color-spantrace"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cd6be1b2a7e382e2b98b43b2adcca6bb0e465af0bdd38123873ae61eb17a72c2"
|
||||||
|
dependencies = [
|
||||||
|
"once_cell",
|
||||||
|
"owo-colors",
|
||||||
|
"tracing-core",
|
||||||
|
"tracing-error",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "colorchoice"
|
name = "colorchoice"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
|
@ -1259,6 +1284,16 @@ dependencies = [
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "eyre"
|
||||||
|
version = "0.6.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec"
|
||||||
|
dependencies = [
|
||||||
|
"indenter",
|
||||||
|
"once_cell",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fastrand"
|
name = "fastrand"
|
||||||
version = "2.0.1"
|
version = "2.0.1"
|
||||||
|
@ -1706,6 +1741,12 @@ version = "0.1.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "206ca75c9c03ba3d4ace2460e57b189f39f43de612c2f85836e65c929701bb2d"
|
checksum = "206ca75c9c03ba3d4ace2460e57b189f39f43de612c2f85836e65c929701bb2d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "indenter"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "1.9.3"
|
version = "1.9.3"
|
||||||
|
@ -2357,6 +2398,12 @@ version = "0.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
|
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "owo-colors"
|
||||||
|
version = "3.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parcel_selectors"
|
name = "parcel_selectors"
|
||||||
version = "0.26.4"
|
version = "0.26.4"
|
||||||
|
|
|
@ -21,7 +21,6 @@ default = []
|
||||||
# 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"
|
|
||||||
actix-web = { version = "4.4.0", default-features = false, features = ["compress-brotli", "compress-gzip", "rustls-0_22"] }
|
actix-web = { version = "4.4.0", default-features = false, features = ["compress-brotli", "compress-gzip", "rustls-0_22"] }
|
||||||
actix-webfinger = { version = "0.5.0", default-features = false }
|
actix-webfinger = { version = "0.5.0", default-features = false }
|
||||||
activitystreams = "0.7.0-alpha.25"
|
activitystreams = "0.7.0-alpha.25"
|
||||||
|
@ -31,6 +30,7 @@ async-cpupool = "0.2.0"
|
||||||
bcrypt = "0.15"
|
bcrypt = "0.15"
|
||||||
base64 = "0.21"
|
base64 = "0.21"
|
||||||
clap = { version = "4.0.0", features = ["derive"] }
|
clap = { version = "4.0.0", features = ["derive"] }
|
||||||
|
color-eyre = "0.6.2"
|
||||||
config = { version = "0.14.0", default-features = false, features = ["toml", "json", "yaml"] }
|
config = { version = "0.14.0", default-features = false, features = ["toml", "json", "yaml"] }
|
||||||
console-subscriber = { version = "0.2", optional = true }
|
console-subscriber = { version = "0.2", optional = true }
|
||||||
dashmap = "5.1.0"
|
dashmap = "5.1.0"
|
||||||
|
@ -84,7 +84,7 @@ tokio = { version = "1", features = ["full", "tracing"] }
|
||||||
uuid = { version = "1", features = ["v4", "serde"] }
|
uuid = { version = "1", features = ["v4", "serde"] }
|
||||||
|
|
||||||
[dependencies.background-jobs]
|
[dependencies.background-jobs]
|
||||||
version = "0.17.0"
|
version = "0.18.0"
|
||||||
default-features = false
|
default-features = false
|
||||||
features = ["error-logging", "metrics", "tokio"]
|
features = ["error-logging", "metrics", "tokio"]
|
||||||
|
|
||||||
|
@ -102,7 +102,7 @@ features = ["middleware", "ring"]
|
||||||
version = "0.7.9"
|
version = "0.7.9"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
anyhow = "1.0"
|
color-eyre = "0.6.2"
|
||||||
dotenv = "0.15.0"
|
dotenv = "0.15.0"
|
||||||
ructe = { version = "0.17.0", features = ["sass", "mime03"] }
|
ructe = { version = "0.17.0", features = ["sass", "mime03"] }
|
||||||
toml = "0.8.0"
|
toml = "0.8.0"
|
||||||
|
|
|
@ -21,7 +21,7 @@ fn git_info() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn version_info() -> Result<(), anyhow::Error> {
|
fn version_info() -> color_eyre::Result<()> {
|
||||||
let cargo_toml = Path::new(&std::env::var("CARGO_MANIFEST_DIR")?).join("Cargo.toml");
|
let cargo_toml = Path::new(&std::env::var("CARGO_MANIFEST_DIR")?).join("Cargo.toml");
|
||||||
|
|
||||||
let mut file = File::open(cargo_toml)?;
|
let mut file = File::open(cargo_toml)?;
|
||||||
|
@ -42,7 +42,7 @@ fn version_info() -> Result<(), anyhow::Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> Result<(), anyhow::Error> {
|
fn main() -> color_eyre::Result<()> {
|
||||||
dotenv::dotenv().ok();
|
dotenv::dotenv().ok();
|
||||||
|
|
||||||
git_info();
|
git_info();
|
||||||
|
|
99
src/error.rs
99
src/error.rs
|
@ -4,54 +4,82 @@ use actix_web::{
|
||||||
http::StatusCode,
|
http::StatusCode,
|
||||||
HttpResponse,
|
HttpResponse,
|
||||||
};
|
};
|
||||||
|
use background_jobs::BoxError;
|
||||||
|
use color_eyre::eyre::Error as Report;
|
||||||
use http_signature_normalization_reqwest::SignError;
|
use http_signature_normalization_reqwest::SignError;
|
||||||
use std::{convert::Infallible, fmt::Debug, io};
|
use std::{convert::Infallible, io, sync::Arc};
|
||||||
use tokio::task::JoinError;
|
use tokio::task::JoinError;
|
||||||
use tracing_error::SpanTrace;
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct ArcKind {
|
||||||
|
kind: Arc<ErrorKind>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Debug for ArcKind {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
self.kind.fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for ArcKind {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
self.kind.fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::error::Error for ArcKind {
|
||||||
|
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||||
|
self.kind.source()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) struct Error {
|
pub(crate) struct Error {
|
||||||
context: String,
|
kind: ArcKind,
|
||||||
kind: ErrorKind,
|
display: Box<str>,
|
||||||
|
debug: Box<str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Error {
|
impl Error {
|
||||||
|
fn kind(&self) -> &ErrorKind {
|
||||||
|
&self.kind.kind
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn is_breaker(&self) -> bool {
|
pub(crate) fn is_breaker(&self) -> bool {
|
||||||
matches!(self.kind, ErrorKind::Breaker)
|
matches!(self.kind(), ErrorKind::Breaker)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn is_not_found(&self) -> bool {
|
pub(crate) fn is_not_found(&self) -> bool {
|
||||||
matches!(self.kind, ErrorKind::Status(_, StatusCode::NOT_FOUND))
|
matches!(self.kind(), ErrorKind::Status(_, StatusCode::NOT_FOUND))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn is_bad_request(&self) -> bool {
|
pub(crate) fn is_bad_request(&self) -> bool {
|
||||||
matches!(self.kind, ErrorKind::Status(_, StatusCode::BAD_REQUEST))
|
matches!(self.kind(), ErrorKind::Status(_, StatusCode::BAD_REQUEST))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn is_gone(&self) -> bool {
|
pub(crate) fn is_gone(&self) -> bool {
|
||||||
matches!(self.kind, ErrorKind::Status(_, StatusCode::GONE))
|
matches!(self.kind(), ErrorKind::Status(_, StatusCode::GONE))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn is_malformed_json(&self) -> bool {
|
pub(crate) fn is_malformed_json(&self) -> bool {
|
||||||
matches!(self.kind, ErrorKind::Json(_))
|
matches!(self.kind(), ErrorKind::Json(_))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Debug for Error {
|
impl std::fmt::Debug for Error {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
writeln!(f, "{:?}", self.kind)
|
f.write_str(&self.debug)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for Error {
|
impl std::fmt::Display for Error {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
writeln!(f, "{}", self.kind)?;
|
f.write_str(&self.display)
|
||||||
std::fmt::Display::fmt(&self.context, f)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::error::Error for Error {
|
impl std::error::Error for Error {
|
||||||
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||||
self.kind.source()
|
self.kind().source()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,25 +88,36 @@ where
|
||||||
ErrorKind: From<T>,
|
ErrorKind: From<T>,
|
||||||
{
|
{
|
||||||
fn from(error: T) -> Self {
|
fn from(error: T) -> Self {
|
||||||
|
let kind = ArcKind {
|
||||||
|
kind: Arc::new(ErrorKind::from(error)),
|
||||||
|
};
|
||||||
|
let report = Report::new(kind.clone());
|
||||||
|
let display = format!("{report}");
|
||||||
|
let debug = format!("{report:?}");
|
||||||
|
|
||||||
Error {
|
Error {
|
||||||
context: SpanTrace::capture().to_string(),
|
kind,
|
||||||
kind: error.into(),
|
display: Box::from(display),
|
||||||
|
debug: Box::from(debug),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
pub(crate) enum ErrorKind {
|
pub(crate) enum ErrorKind {
|
||||||
#[error("Error queueing job, {0}")]
|
#[error("Error in extractor")]
|
||||||
Queue(anyhow::Error),
|
Extractor(#[from] crate::extractors::ErrorKind),
|
||||||
|
|
||||||
#[error("Error in configuration, {0}")]
|
#[error("Error queueing job")]
|
||||||
|
Queue(#[from] BoxError),
|
||||||
|
|
||||||
|
#[error("Error in configuration")]
|
||||||
Config(#[from] config::ConfigError),
|
Config(#[from] config::ConfigError),
|
||||||
|
|
||||||
#[error("Couldn't parse key, {0}")]
|
#[error("Couldn't parse key")]
|
||||||
Pkcs8(#[from] rsa::pkcs8::Error),
|
Pkcs8(#[from] rsa::pkcs8::Error),
|
||||||
|
|
||||||
#[error("Couldn't encode public key, {0}")]
|
#[error("Couldn't encode public key")]
|
||||||
Spki(#[from] rsa::pkcs8::spki::Error),
|
Spki(#[from] rsa::pkcs8::spki::Error),
|
||||||
|
|
||||||
#[error("Couldn't sign request")]
|
#[error("Couldn't sign request")]
|
||||||
|
@ -90,25 +129,25 @@ pub(crate) enum ErrorKind {
|
||||||
#[error("Couldn't make request")]
|
#[error("Couldn't make request")]
|
||||||
ReqwestMiddleware(#[from] reqwest_middleware::Error),
|
ReqwestMiddleware(#[from] reqwest_middleware::Error),
|
||||||
|
|
||||||
#[error("Couldn't parse IRI, {0}")]
|
#[error("Couldn't parse IRI")]
|
||||||
ParseIri(#[from] activitystreams::iri_string::validate::Error),
|
ParseIri(#[from] activitystreams::iri_string::validate::Error),
|
||||||
|
|
||||||
#[error("Couldn't normalize IRI, {0}")]
|
#[error("Couldn't normalize IRI")]
|
||||||
NormalizeIri(#[from] std::collections::TryReserveError),
|
NormalizeIri(#[from] std::collections::TryReserveError),
|
||||||
|
|
||||||
#[error("Couldn't perform IO, {0}")]
|
#[error("Couldn't perform IO")]
|
||||||
Io(#[from] io::Error),
|
Io(#[from] io::Error),
|
||||||
|
|
||||||
#[error("Couldn't sign string, {0}")]
|
#[error("Couldn't sign string, {0}")]
|
||||||
Rsa(rsa::errors::Error),
|
Rsa(rsa::errors::Error),
|
||||||
|
|
||||||
#[error("Couldn't use db, {0}")]
|
#[error("Couldn't use db")]
|
||||||
Sled(#[from] sled::Error),
|
Sled(#[from] sled::Error),
|
||||||
|
|
||||||
#[error("Couldn't do the json thing, {0}")]
|
#[error("Couldn't do the json thing")]
|
||||||
Json(#[from] serde_json::Error),
|
Json(#[from] serde_json::Error),
|
||||||
|
|
||||||
#[error("Couldn't sign request, {0}")]
|
#[error("Couldn't sign request")]
|
||||||
Sign(#[from] SignError),
|
Sign(#[from] SignError),
|
||||||
|
|
||||||
#[error("Couldn't sign digest")]
|
#[error("Couldn't sign digest")]
|
||||||
|
@ -147,10 +186,10 @@ pub(crate) enum ErrorKind {
|
||||||
#[error("Wrong ActivityPub kind, {0}")]
|
#[error("Wrong ActivityPub kind, {0}")]
|
||||||
Kind(String),
|
Kind(String),
|
||||||
|
|
||||||
#[error("Too many CPUs, {0}")]
|
#[error("Too many CPUs")]
|
||||||
CpuCount(#[from] std::num::TryFromIntError),
|
CpuCount(#[from] std::num::TryFromIntError),
|
||||||
|
|
||||||
#[error("{0}")]
|
#[error("Host mismatch")]
|
||||||
HostMismatch(#[from] CheckError),
|
HostMismatch(#[from] CheckError),
|
||||||
|
|
||||||
#[error("Couldn't flush buffer")]
|
#[error("Couldn't flush buffer")]
|
||||||
|
@ -204,7 +243,7 @@ pub(crate) enum ErrorKind {
|
||||||
|
|
||||||
impl ResponseError for Error {
|
impl ResponseError for Error {
|
||||||
fn status_code(&self) -> StatusCode {
|
fn status_code(&self) -> StatusCode {
|
||||||
match self.kind {
|
match self.kind() {
|
||||||
ErrorKind::NotAllowed(_) | ErrorKind::WrongActor(_) | ErrorKind::BadActor(_, _) => {
|
ErrorKind::NotAllowed(_) | ErrorKind::WrongActor(_) | ErrorKind::BadActor(_, _) => {
|
||||||
StatusCode::FORBIDDEN
|
StatusCode::FORBIDDEN
|
||||||
}
|
}
|
||||||
|
@ -224,7 +263,7 @@ impl ResponseError for Error {
|
||||||
.insert_header(("Content-Type", "application/activity+json"))
|
.insert_header(("Content-Type", "application/activity+json"))
|
||||||
.body(
|
.body(
|
||||||
serde_json::to_string(&serde_json::json!({
|
serde_json::to_string(&serde_json::json!({
|
||||||
"error": self.kind.to_string(),
|
"error": self.kind().to_string(),
|
||||||
}))
|
}))
|
||||||
.unwrap_or_else(|_| "{}".to_string()),
|
.unwrap_or_else(|_| "{}".to_string()),
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,19 +1,15 @@
|
||||||
use actix_web::{
|
use actix_web::{
|
||||||
dev::Payload,
|
dev::Payload,
|
||||||
error::ParseError,
|
error::ParseError,
|
||||||
http::{
|
http::header::{from_one_raw_str, Header, HeaderName, HeaderValue, TryIntoHeaderValue},
|
||||||
header::{from_one_raw_str, Header, HeaderName, HeaderValue, TryIntoHeaderValue},
|
|
||||||
StatusCode,
|
|
||||||
},
|
|
||||||
web::Data,
|
web::Data,
|
||||||
FromRequest, HttpMessage, HttpRequest, HttpResponse, ResponseError,
|
FromRequest, HttpMessage, HttpRequest,
|
||||||
};
|
};
|
||||||
use bcrypt::{BcryptError, DEFAULT_COST};
|
use bcrypt::{BcryptError, DEFAULT_COST};
|
||||||
use http_signature_normalization_actix::{prelude::InvalidHeaderValue, Canceled, Spawn};
|
use http_signature_normalization_actix::{prelude::InvalidHeaderValue, Canceled, Spawn};
|
||||||
use std::{convert::Infallible, str::FromStr, time::Instant};
|
use std::{convert::Infallible, str::FromStr, time::Instant};
|
||||||
use tracing_error::SpanTrace;
|
|
||||||
|
|
||||||
use crate::{db::Db, future::LocalBoxFuture, spawner::Spawner};
|
use crate::{db::Db, error::Error, future::LocalBoxFuture, spawner::Spawner};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub(crate) struct AdminConfig {
|
pub(crate) struct AdminConfig {
|
||||||
|
@ -83,74 +79,42 @@ impl Admin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
|
||||||
#[error("Failed authentication")]
|
|
||||||
pub(crate) struct Error {
|
|
||||||
context: String,
|
|
||||||
#[source]
|
|
||||||
kind: ErrorKind,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Error {
|
impl Error {
|
||||||
fn invalid() -> Self {
|
fn invalid() -> Self {
|
||||||
Error {
|
Error::from(ErrorKind::Invalid)
|
||||||
context: SpanTrace::capture().to_string(),
|
|
||||||
kind: ErrorKind::Invalid,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn missing_config() -> Self {
|
fn missing_config() -> Self {
|
||||||
Error {
|
Error::from(ErrorKind::MissingConfig)
|
||||||
context: SpanTrace::capture().to_string(),
|
|
||||||
kind: ErrorKind::MissingConfig,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn missing_db() -> Self {
|
fn missing_db() -> Self {
|
||||||
Error {
|
Error::from(ErrorKind::MissingDb)
|
||||||
context: SpanTrace::capture().to_string(),
|
|
||||||
kind: ErrorKind::MissingDb,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn missing_spawner() -> Self {
|
fn missing_spawner() -> Self {
|
||||||
Error {
|
Error::from(ErrorKind::MissingSpawner)
|
||||||
context: SpanTrace::capture().to_string(),
|
|
||||||
kind: ErrorKind::MissingSpawner,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bcrypt_verify(e: BcryptError) -> Self {
|
fn bcrypt_verify(e: BcryptError) -> Self {
|
||||||
Error {
|
Error::from(ErrorKind::BCryptVerify(e))
|
||||||
context: SpanTrace::capture().to_string(),
|
|
||||||
kind: ErrorKind::BCryptVerify(e),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bcrypt_hash(e: BcryptError) -> Self {
|
fn bcrypt_hash(e: BcryptError) -> Self {
|
||||||
Error {
|
Error::from(ErrorKind::BCryptHash(e))
|
||||||
context: SpanTrace::capture().to_string(),
|
|
||||||
kind: ErrorKind::BCryptHash(e),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_header(e: ParseError) -> Self {
|
fn parse_header(e: ParseError) -> Self {
|
||||||
Error {
|
Error::from(ErrorKind::ParseHeader(e))
|
||||||
context: SpanTrace::capture().to_string(),
|
|
||||||
kind: ErrorKind::ParseHeader(e),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn canceled(_: Canceled) -> Self {
|
fn canceled(_: Canceled) -> Self {
|
||||||
Error {
|
Error::from(ErrorKind::Canceled)
|
||||||
context: SpanTrace::capture().to_string(),
|
|
||||||
kind: ErrorKind::Canceled,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
enum ErrorKind {
|
pub(crate) enum ErrorKind {
|
||||||
#[error("Invalid API Token")]
|
#[error("Invalid API Token")]
|
||||||
Invalid,
|
Invalid,
|
||||||
|
|
||||||
|
@ -176,20 +140,6 @@ enum ErrorKind {
|
||||||
ParseHeader(#[source] ParseError),
|
ParseHeader(#[source] ParseError),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ResponseError for Error {
|
|
||||||
fn status_code(&self) -> StatusCode {
|
|
||||||
match self.kind {
|
|
||||||
ErrorKind::Invalid | ErrorKind::ParseHeader(_) => StatusCode::BAD_REQUEST,
|
|
||||||
_ => StatusCode::INTERNAL_SERVER_ERROR,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn error_response(&self) -> HttpResponse {
|
|
||||||
HttpResponse::build(self.status_code())
|
|
||||||
.json(serde_json::json!({ "msg": self.kind.to_string() }))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromRequest for Admin {
|
impl FromRequest for Admin {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
type Future = LocalBoxFuture<'static, Result<Self, Self::Error>>;
|
type Future = LocalBoxFuture<'static, Result<Self, Self::Error>>;
|
||||||
|
|
|
@ -64,12 +64,13 @@ fn generate_announce(
|
||||||
|
|
||||||
impl Job for Announce {
|
impl Job for Announce {
|
||||||
type State = JobState;
|
type State = JobState;
|
||||||
type Future = BoxFuture<'static, anyhow::Result<()>>;
|
type Error = Error;
|
||||||
|
type Future = BoxFuture<'static, Result<(), Self::Error>>;
|
||||||
|
|
||||||
const NAME: &'static str = "relay::jobs::apub::Announce";
|
const NAME: &'static str = "relay::jobs::apub::Announce";
|
||||||
const QUEUE: &'static str = "apub";
|
const QUEUE: &'static str = "apub";
|
||||||
|
|
||||||
fn run(self, state: Self::State) -> Self::Future {
|
fn run(self, state: Self::State) -> Self::Future {
|
||||||
Box::pin(async move { self.perform(state).await.map_err(Into::into) })
|
Box::pin(self.perform(state))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -113,12 +113,13 @@ fn generate_accept_follow(
|
||||||
|
|
||||||
impl Job for Follow {
|
impl Job for Follow {
|
||||||
type State = JobState;
|
type State = JobState;
|
||||||
type Future = BoxFuture<'static, anyhow::Result<()>>;
|
type Error = Error;
|
||||||
|
type Future = BoxFuture<'static, Result<(), Self::Error>>;
|
||||||
|
|
||||||
const NAME: &'static str = "relay::jobs::apub::Follow";
|
const NAME: &'static str = "relay::jobs::apub::Follow";
|
||||||
const QUEUE: &'static str = "apub";
|
const QUEUE: &'static str = "apub";
|
||||||
|
|
||||||
fn run(self, state: Self::State) -> Self::Future {
|
fn run(self, state: Self::State) -> Self::Future {
|
||||||
Box::pin(async move { self.perform(state).await.map_err(Into::into) })
|
Box::pin(self.perform(state))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,12 +49,13 @@ impl Forward {
|
||||||
|
|
||||||
impl Job for Forward {
|
impl Job for Forward {
|
||||||
type State = JobState;
|
type State = JobState;
|
||||||
type Future = BoxFuture<'static, anyhow::Result<()>>;
|
type Error = Error;
|
||||||
|
type Future = BoxFuture<'static, Result<(), Self::Error>>;
|
||||||
|
|
||||||
const NAME: &'static str = "relay::jobs::apub::Forward";
|
const NAME: &'static str = "relay::jobs::apub::Forward";
|
||||||
const QUEUE: &'static str = "apub";
|
const QUEUE: &'static str = "apub";
|
||||||
|
|
||||||
fn run(self, state: Self::State) -> Self::Future {
|
fn run(self, state: Self::State) -> Self::Future {
|
||||||
Box::pin(async move { self.perform(state).await.map_err(Into::into) })
|
Box::pin(self.perform(state))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,12 +35,13 @@ impl Reject {
|
||||||
|
|
||||||
impl Job for Reject {
|
impl Job for Reject {
|
||||||
type State = JobState;
|
type State = JobState;
|
||||||
type Future = BoxFuture<'static, anyhow::Result<()>>;
|
type Error = Error;
|
||||||
|
type Future = BoxFuture<'static, Result<(), Self::Error>>;
|
||||||
|
|
||||||
const NAME: &'static str = "relay::jobs::apub::Reject";
|
const NAME: &'static str = "relay::jobs::apub::Reject";
|
||||||
const QUEUE: &'static str = "apub";
|
const QUEUE: &'static str = "apub";
|
||||||
|
|
||||||
fn run(self, state: Self::State) -> Self::Future {
|
fn run(self, state: Self::State) -> Self::Future {
|
||||||
Box::pin(async move { self.perform(state).await.map_err(Into::into) })
|
Box::pin(self.perform(state))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,12 +50,13 @@ impl Undo {
|
||||||
|
|
||||||
impl Job for Undo {
|
impl Job for Undo {
|
||||||
type State = JobState;
|
type State = JobState;
|
||||||
type Future = BoxFuture<'static, anyhow::Result<()>>;
|
type Error = Error;
|
||||||
|
type Future = BoxFuture<'static, Result<(), Self::Error>>;
|
||||||
|
|
||||||
const NAME: &'static str = "relay::jobs::apub::Undo";
|
const NAME: &'static str = "relay::jobs::apub::Undo";
|
||||||
const QUEUE: &'static str = "apub";
|
const QUEUE: &'static str = "apub";
|
||||||
|
|
||||||
fn run(self, state: Self::State) -> Self::Future {
|
fn run(self, state: Self::State) -> Self::Future {
|
||||||
Box::pin(async move { self.perform(state).await.map_err(Into::into) })
|
Box::pin(self.perform(state))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,13 +87,14 @@ fn to_contact(contact: AcceptedActors) -> Option<(String, String, IriString, Iri
|
||||||
|
|
||||||
impl Job for QueryContact {
|
impl Job for QueryContact {
|
||||||
type State = JobState;
|
type State = JobState;
|
||||||
type Future = BoxFuture<'static, anyhow::Result<()>>;
|
type Error = Error;
|
||||||
|
type Future = BoxFuture<'static, Result<(), Self::Error>>;
|
||||||
|
|
||||||
const NAME: &'static str = "relay::jobs::QueryContact";
|
const NAME: &'static str = "relay::jobs::QueryContact";
|
||||||
const QUEUE: &'static str = "maintenance";
|
const QUEUE: &'static str = "maintenance";
|
||||||
|
|
||||||
fn run(self, state: Self::State) -> Self::Future {
|
fn run(self, state: Self::State) -> Self::Future {
|
||||||
Box::pin(async move { self.perform(state).await.map_err(Into::into) })
|
Box::pin(self.perform(state))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ impl Deliver {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(name = "Deliver", skip(state))]
|
#[tracing::instrument(name = "Deliver", skip(state))]
|
||||||
async fn permform(self, state: JobState) -> Result<(), Error> {
|
async fn perform(self, state: JobState) -> Result<(), Error> {
|
||||||
if let Err(e) = state
|
if let Err(e) = state
|
||||||
.state
|
.state
|
||||||
.requests
|
.requests
|
||||||
|
@ -58,13 +58,14 @@ impl Deliver {
|
||||||
|
|
||||||
impl Job for Deliver {
|
impl Job for Deliver {
|
||||||
type State = JobState;
|
type State = JobState;
|
||||||
type Future = BoxFuture<'static, anyhow::Result<()>>;
|
type Error = Error;
|
||||||
|
type Future = BoxFuture<'static, Result<(), Self::Error>>;
|
||||||
|
|
||||||
const NAME: &'static str = "relay::jobs::Deliver";
|
const NAME: &'static str = "relay::jobs::Deliver";
|
||||||
const QUEUE: &'static str = "deliver";
|
const QUEUE: &'static str = "deliver";
|
||||||
const BACKOFF: Backoff = Backoff::Exponential(8);
|
const BACKOFF: Backoff = Backoff::Exponential(8);
|
||||||
|
|
||||||
fn run(self, state: Self::State) -> Self::Future {
|
fn run(self, state: Self::State) -> Self::Future {
|
||||||
Box::pin(async move { self.permform(state).await.map_err(Into::into) })
|
Box::pin(self.perform(state))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,12 +47,13 @@ impl DeliverMany {
|
||||||
|
|
||||||
impl Job for DeliverMany {
|
impl Job for DeliverMany {
|
||||||
type State = JobState;
|
type State = JobState;
|
||||||
type Future = BoxFuture<'static, anyhow::Result<()>>;
|
type Error = Error;
|
||||||
|
type Future = BoxFuture<'static, Result<(), Self::Error>>;
|
||||||
|
|
||||||
const NAME: &'static str = "relay::jobs::DeliverMany";
|
const NAME: &'static str = "relay::jobs::DeliverMany";
|
||||||
const QUEUE: &'static str = "deliver";
|
const QUEUE: &'static str = "deliver";
|
||||||
|
|
||||||
fn run(self, state: Self::State) -> Self::Future {
|
fn run(self, state: Self::State) -> Self::Future {
|
||||||
Box::pin(async move { self.perform(state).await.map_err(Into::into) })
|
Box::pin(self.perform(state))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -167,13 +167,14 @@ impl QueryInstance {
|
||||||
|
|
||||||
impl Job for QueryInstance {
|
impl Job for QueryInstance {
|
||||||
type State = JobState;
|
type State = JobState;
|
||||||
type Future = BoxFuture<'static, anyhow::Result<()>>;
|
type Error = Error;
|
||||||
|
type Future = BoxFuture<'static, Result<(), Self::Error>>;
|
||||||
|
|
||||||
const NAME: &'static str = "relay::jobs::QueryInstance";
|
const NAME: &'static str = "relay::jobs::QueryInstance";
|
||||||
const QUEUE: &'static str = "maintenance";
|
const QUEUE: &'static str = "maintenance";
|
||||||
|
|
||||||
fn run(self, state: Self::State) -> Self::Future {
|
fn run(self, state: Self::State) -> Self::Future {
|
||||||
Box::pin(async move { self.perform(state).await.map_err(Into::into) })
|
Box::pin(self.perform(state))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -106,13 +106,14 @@ impl QueryNodeinfo {
|
||||||
|
|
||||||
impl Job for QueryNodeinfo {
|
impl Job for QueryNodeinfo {
|
||||||
type State = JobState;
|
type State = JobState;
|
||||||
type Future = BoxFuture<'static, anyhow::Result<()>>;
|
type Error = Error;
|
||||||
|
type Future = BoxFuture<'static, Result<(), Self::Error>>;
|
||||||
|
|
||||||
const NAME: &'static str = "relay::jobs::QueryNodeinfo";
|
const NAME: &'static str = "relay::jobs::QueryNodeinfo";
|
||||||
const QUEUE: &'static str = "maintenance";
|
const QUEUE: &'static str = "maintenance";
|
||||||
|
|
||||||
fn run(self, state: Self::State) -> Self::Future {
|
fn run(self, state: Self::State) -> Self::Future {
|
||||||
Box::pin(async move { self.perform(state).await.map_err(Into::into) })
|
Box::pin(self.perform(state))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,12 +25,13 @@ impl Listeners {
|
||||||
|
|
||||||
impl Job for Listeners {
|
impl Job for Listeners {
|
||||||
type State = JobState;
|
type State = JobState;
|
||||||
type Future = BoxFuture<'static, anyhow::Result<()>>;
|
type Error = Error;
|
||||||
|
type Future = BoxFuture<'static, Result<(), Self::Error>>;
|
||||||
|
|
||||||
const NAME: &'static str = "relay::jobs::Listeners";
|
const NAME: &'static str = "relay::jobs::Listeners";
|
||||||
const QUEUE: &'static str = "maintenance";
|
const QUEUE: &'static str = "maintenance";
|
||||||
|
|
||||||
fn run(self, state: Self::State) -> Self::Future {
|
fn run(self, state: Self::State) -> Self::Future {
|
||||||
Box::pin(async move { self.perform(state).await.map_err(Into::into) })
|
Box::pin(self.perform(state))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,13 +15,14 @@ impl RecordLastOnline {
|
||||||
|
|
||||||
impl Job for RecordLastOnline {
|
impl Job for RecordLastOnline {
|
||||||
type State = JobState;
|
type State = JobState;
|
||||||
type Future = BoxFuture<'static, anyhow::Result<()>>;
|
type Error = Error;
|
||||||
|
type Future = BoxFuture<'static, Result<(), Self::Error>>;
|
||||||
|
|
||||||
const NAME: &'static str = "relay::jobs::RecordLastOnline";
|
const NAME: &'static str = "relay::jobs::RecordLastOnline";
|
||||||
const QUEUE: &'static str = "maintenance";
|
const QUEUE: &'static str = "maintenance";
|
||||||
const BACKOFF: Backoff = Backoff::Linear(1);
|
const BACKOFF: Backoff = Backoff::Linear(1);
|
||||||
|
|
||||||
fn run(self, state: Self::State) -> Self::Future {
|
fn run(self, state: Self::State) -> Self::Future {
|
||||||
Box::pin(async move { self.perform(state).await.map_err(Into::into) })
|
Box::pin(self.perform(state))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
13
src/main.rs
13
src/main.rs
|
@ -56,8 +56,9 @@ use self::{
|
||||||
fn init_subscriber(
|
fn init_subscriber(
|
||||||
software_name: &'static str,
|
software_name: &'static str,
|
||||||
opentelemetry_url: Option<&IriString>,
|
opentelemetry_url: Option<&IriString>,
|
||||||
) -> Result<(), anyhow::Error> {
|
) -> color_eyre::Result<()> {
|
||||||
LogTracer::init()?;
|
LogTracer::init()?;
|
||||||
|
color_eyre::install()?;
|
||||||
|
|
||||||
let targets: Targets = std::env::var("RUST_LOG")
|
let targets: Targets = std::env::var("RUST_LOG")
|
||||||
.unwrap_or_else(|_| "info".into())
|
.unwrap_or_else(|_| "info".into())
|
||||||
|
@ -140,7 +141,7 @@ fn build_client(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), anyhow::Error> {
|
async fn main() -> color_eyre::Result<()> {
|
||||||
dotenv::dotenv().ok();
|
dotenv::dotenv().ok();
|
||||||
|
|
||||||
let config = Config::build()?;
|
let config = Config::build()?;
|
||||||
|
@ -166,7 +167,7 @@ async fn main() -> Result<(), anyhow::Error> {
|
||||||
.add_recorder(recorder)
|
.add_recorder(recorder)
|
||||||
.add_recorder(collector.clone())
|
.add_recorder(collector.clone())
|
||||||
.build();
|
.build();
|
||||||
metrics::set_global_recorder(recorder).map_err(|e| anyhow::anyhow!("{e}"))?;
|
metrics::set_global_recorder(recorder).map_err(|e| color_eyre::eyre::eyre!("{e}"))?;
|
||||||
} else {
|
} else {
|
||||||
collector.install()?;
|
collector.install()?;
|
||||||
}
|
}
|
||||||
|
@ -185,11 +186,11 @@ async fn main() -> Result<(), anyhow::Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn client_main(config: Config, args: Args) -> JoinHandle<Result<(), anyhow::Error>> {
|
fn client_main(config: Config, args: Args) -> JoinHandle<color_eyre::Result<()>> {
|
||||||
tokio::spawn(do_client_main(config, args))
|
tokio::spawn(do_client_main(config, args))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn do_client_main(config: Config, args: Args) -> Result<(), anyhow::Error> {
|
async fn do_client_main(config: Config, args: Args) -> color_eyre::Result<()> {
|
||||||
let client = build_client(
|
let client = build_client(
|
||||||
&config.user_agent(),
|
&config.user_agent(),
|
||||||
config.client_timeout(),
|
config.client_timeout(),
|
||||||
|
@ -280,7 +281,7 @@ async fn server_main(
|
||||||
media: MediaCache,
|
media: MediaCache,
|
||||||
collector: MemoryCollector,
|
collector: MemoryCollector,
|
||||||
config: Config,
|
config: Config,
|
||||||
) -> Result<(), anyhow::Error> {
|
) -> color_eyre::Result<()> {
|
||||||
let client = build_client(
|
let client = build_client(
|
||||||
&config.user_agent(),
|
&config.user_agent(),
|
||||||
config.client_timeout(),
|
config.client_timeout(),
|
||||||
|
|
|
@ -8,7 +8,7 @@ pub(crate) struct Spawner {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Spawner {
|
impl Spawner {
|
||||||
pub(crate) fn build(name: &'static str, threads: u16) -> anyhow::Result<Self> {
|
pub(crate) fn build(name: &'static str, threads: u16) -> color_eyre::Result<Self> {
|
||||||
let pool = CpuPool::configure()
|
let pool = CpuPool::configure()
|
||||||
.name(name)
|
.name(name)
|
||||||
.max_threads(threads)
|
.max_threads(threads)
|
||||||
|
|
Loading…
Reference in a new issue