From e70a6b80e4e13f26d2249ea719fdef0f52f26ceb Mon Sep 17 00:00:00 2001 From: asonix Date: Wed, 7 Nov 2018 23:47:11 -0600 Subject: [PATCH] Make jobs processor accessible over a network --- Cargo.toml | 3 +- examples/server-jobs-example/.env | 1 + examples/server-jobs-example/Cargo.toml | 21 ++++++++ .../server-jobs-example/example-db/data.mdb | Bin 0 -> 454656 bytes .../server-jobs-example/example-db/lock.mdb | Bin 0 -> 1280 bytes .../server-jobs-example/src/bin/server.rs | 13 +++++ .../server-jobs-example/src/bin/spawner.rs | 25 +++++++++ .../server-jobs-example/src/bin/worker.rs | 13 +++++ examples/server-jobs-example/src/lib.rs | 46 ++++++++++++++++ examples/tokio-jobs-example/src/main.rs | 20 +++---- jobs-core/src/storage.rs | 4 ++ jobs-server-tokio/src/client.rs | 16 ++++-- jobs-server-tokio/src/lib.rs | 2 + jobs-server-tokio/src/spawner.rs | 49 ++++++++++++++++++ src/lib.rs | 3 ++ 15 files changed, 202 insertions(+), 14 deletions(-) create mode 100644 examples/server-jobs-example/.env create mode 100644 examples/server-jobs-example/Cargo.toml create mode 100644 examples/server-jobs-example/example-db/data.mdb create mode 100644 examples/server-jobs-example/example-db/lock.mdb create mode 100644 examples/server-jobs-example/src/bin/server.rs create mode 100644 examples/server-jobs-example/src/bin/spawner.rs create mode 100644 examples/server-jobs-example/src/bin/worker.rs create mode 100644 examples/server-jobs-example/src/lib.rs create mode 100644 jobs-server-tokio/src/spawner.rs diff --git a/Cargo.toml b/Cargo.toml index 21d5430..3a152ff 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,8 +10,9 @@ members = [ "jobs-core", "jobs-server-tokio", "jobs-tokio", - "examples/tokio-jobs-example", "examples/actix-jobs-example", + "examples/server-jobs-example", + "examples/tokio-jobs-example", ] [features] diff --git a/examples/server-jobs-example/.env b/examples/server-jobs-example/.env new file mode 100644 index 0000000..0e7a139 --- /dev/null +++ b/examples/server-jobs-example/.env @@ -0,0 +1 @@ +RUST_LOG=server_jobs_example,jobs_server_tokio=trace diff --git a/examples/server-jobs-example/Cargo.toml b/examples/server-jobs-example/Cargo.toml new file mode 100644 index 0000000..8829764 --- /dev/null +++ b/examples/server-jobs-example/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "server-jobs-example" +version = "0.1.0" +authors = ["asonix "] +edition = "2018" + +[dependencies] +dotenv = "0.13" +env_logger = "0.5" +failure = "0.1" +futures = "0.1" +log = "0.4" +serde = "1.0" +serde_derive = "1.0" +tokio = "0.1" + +[dependencies.jobs] +version = "0.1" +path = "../.." +default-features = false +features = ["jobs-server-tokio"] diff --git a/examples/server-jobs-example/example-db/data.mdb b/examples/server-jobs-example/example-db/data.mdb new file mode 100644 index 0000000000000000000000000000000000000000..a931091e5ac4ccc51ae053e8f7b4b8942ea57166 GIT binary patch literal 454656 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 F004cIZ;Jo` literal 0 HcmV?d00001 diff --git a/examples/server-jobs-example/src/bin/server.rs b/examples/server-jobs-example/src/bin/server.rs new file mode 100644 index 0000000..89db98b --- /dev/null +++ b/examples/server-jobs-example/src/bin/server.rs @@ -0,0 +1,13 @@ +use failure::Error; +use jobs::ServerConfig; + +fn main() -> Result<(), Error> { + dotenv::dotenv().ok(); + env_logger::init(); + + let config = ServerConfig::init("127.0.0.1", 5555, 1234, 1, "example-db")?; + + tokio::run(config.run()); + + Ok(()) +} diff --git a/examples/server-jobs-example/src/bin/spawner.rs b/examples/server-jobs-example/src/bin/spawner.rs new file mode 100644 index 0000000..2830efe --- /dev/null +++ b/examples/server-jobs-example/src/bin/spawner.rs @@ -0,0 +1,25 @@ +use futures::{future::lazy, Future}; +use jobs::{Processor, SpawnerConfig}; +use server_jobs_example::{MyJobArguments, MyProcessor}; + +fn main() { + let (_, _, jobs) = (1..50).fold((0, 1, Vec::new()), |(x, y, mut acc), _| { + acc.push(MyJobArguments::new(x, y)); + + (y, x + y, acc) + }); + + let spawner = SpawnerConfig::new("localhost", 5555); + + tokio::run(lazy(move || { + for job in jobs { + tokio::spawn( + spawner + .queue(MyProcessor::new_job(job, None, None).unwrap()) + .map_err(|_| ()), + ); + } + + Ok(()) + })); +} diff --git a/examples/server-jobs-example/src/bin/worker.rs b/examples/server-jobs-example/src/bin/worker.rs new file mode 100644 index 0000000..04cc94b --- /dev/null +++ b/examples/server-jobs-example/src/bin/worker.rs @@ -0,0 +1,13 @@ +use failure::Error; +use jobs::ClientConfig; +use server_jobs_example::MyProcessor; + +fn main() -> Result<(), Error> { + let mut client = ClientConfig::init(16, "localhost", 5555)?; + + client.register_processor(MyProcessor); + + tokio::run(client.run()); + + Ok(()) +} diff --git a/examples/server-jobs-example/src/lib.rs b/examples/server-jobs-example/src/lib.rs new file mode 100644 index 0000000..ebd9433 --- /dev/null +++ b/examples/server-jobs-example/src/lib.rs @@ -0,0 +1,46 @@ +#[macro_use] +extern crate serde_derive; + +use failure::Error; +use futures::{future::IntoFuture, Future}; +use jobs::{Backoff, MaxRetries, Processor}; + +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct MyJobArguments { + some_usize: usize, + other_usize: usize, +} + +impl MyJobArguments { + pub fn new(some_usize: usize, other_usize: usize) -> Self { + MyJobArguments { + some_usize, + other_usize, + } + } +} + +#[derive(Clone, Debug)] +pub struct MyProcessor; + +impl Processor for MyProcessor { + type Arguments = MyJobArguments; + + fn name() -> &'static str { + "MyProcessor" + } + + fn max_retries() -> MaxRetries { + MaxRetries::Count(1) + } + + fn backoff_strategy() -> Backoff { + Backoff::Exponential(2) + } + + fn process(&self, args: Self::Arguments) -> Box + Send> { + println!("args: {:?}", args); + + Box::new(Ok(()).into_future()) + } +} diff --git a/examples/tokio-jobs-example/src/main.rs b/examples/tokio-jobs-example/src/main.rs index e9826c1..f784fba 100644 --- a/examples/tokio-jobs-example/src/main.rs +++ b/examples/tokio-jobs-example/src/main.rs @@ -47,21 +47,21 @@ fn main() { dotenv::dotenv().ok(); env_logger::init(); - tokio::run(lazy(|| { + let (_, _, jobs) = (1..18).fold((0, 1, Vec::new()), |(x, y, mut acc), _| { + acc.push(MyJobArguments { + some_usize: x, + other_usize: y, + }); + + (y, x + y, acc) + }); + + tokio::run(lazy(move || { let mut runner = JobRunner::new(1234, 4, "example-db"); runner.register_processor(MyProcessor); let handle = runner.spawn(); - let (_, _, jobs) = (1..18).fold((0, 1, Vec::new()), |(x, y, mut acc), _| { - acc.push(MyJobArguments { - some_usize: x, - other_usize: y, - }); - - (y, x + y, acc) - }); - for job in jobs { tokio::spawn( handle diff --git a/jobs-core/src/storage.rs b/jobs-core/src/storage.rs index e7861b1..10a112d 100644 --- a/jobs-core/src/storage.rs +++ b/jobs-core/src/storage.rs @@ -44,6 +44,8 @@ impl Storage { let mut manager = Manager::new(); let mut cfg = Config::default(path); + cfg.set_max_readers(18); + // Create our buckets for bucket in Storage::buckets().iter() { cfg.bucket(bucket, None); @@ -150,6 +152,8 @@ impl Storage { trace!("Committing"); + read_txn.commit()?; + txn.commit()?; trace!("Committed"); diff --git a/jobs-server-tokio/src/client.rs b/jobs-server-tokio/src/client.rs index 43a2b97..d4d71b2 100644 --- a/jobs-server-tokio/src/client.rs +++ b/jobs-server-tokio/src/client.rs @@ -1,4 +1,4 @@ -use std::sync::Arc; +use std::{sync::Arc, time::Duration}; use failure::Error; use futures::{ @@ -6,6 +6,7 @@ use futures::{ Future, Stream, }; use jobs_core::{Processor, Processors}; +use tokio::timer::Delay; use tokio_zmq::{prelude::*, Multipart, Req}; use zmq::{Context, Message}; @@ -133,11 +134,17 @@ fn process_response( response: ServerResponse, processors: &Processors, ) -> impl Future { + let either_a = Either::A( + Delay::new(tokio::clock::now() + Duration::from_millis(500)) + .from_err() + .and_then(|_| Ok(ServerRequest::FetchJobs(1))), + ); + match response { ServerResponse::FetchJobs(jobs) => { let job = match jobs.into_iter().next() { Some(job) => job, - None => return Either::A(Ok(ServerRequest::FetchJobs(1)).into_future()), + None => return either_a, }; let fut = processors @@ -147,7 +154,10 @@ fn process_response( Either::B(fut) } - _ => return Either::A(Ok(ServerRequest::FetchJobs(1)).into_future()), + e => { + error!("Error from server, {:?}", e); + return either_a; + } } } diff --git a/jobs-server-tokio/src/lib.rs b/jobs-server-tokio/src/lib.rs index 826aace..869edbf 100644 --- a/jobs-server-tokio/src/lib.rs +++ b/jobs-server-tokio/src/lib.rs @@ -9,10 +9,12 @@ use failure::Error; mod client; mod server; +mod spawner; pub use crate::{ client::ClientConfig, server::{ServerConfig, ServerRequest, ServerResponse}, + spawner::SpawnerConfig, }; fn coerce(res: Result, F>) -> Result diff --git a/jobs-server-tokio/src/spawner.rs b/jobs-server-tokio/src/spawner.rs new file mode 100644 index 0000000..fd9d0ad --- /dev/null +++ b/jobs-server-tokio/src/spawner.rs @@ -0,0 +1,49 @@ +use std::sync::Arc; + +use failure::Error; +use futures::{future::IntoFuture, Future}; +use jobs_core::JobInfo; +use tokio_zmq::{prelude::*, Req}; +use zmq::{Context, Message}; + +use crate::ServerRequest; + +pub struct SpawnerConfig { + server: String, + ctx: Arc, +} + +impl SpawnerConfig { + pub fn new(server_host: &str, server_port: usize) -> Self { + let ctx = Arc::new(Context::new()); + + SpawnerConfig { + server: format!("tcp://{}:{}", server_host, server_port), + ctx, + } + } + + pub fn queue(&self, job: JobInfo) -> impl Future { + let msg = serde_json::to_string(&ServerRequest::ReturnJob(job)) + .map_err(Error::from) + .and_then(|s| { + Message::from_slice(s.as_ref()) + .map(|m| m.into()) + .map_err(Error::from) + }) + .into_future(); + + Req::builder(self.ctx.clone()) + .connect(&self.server) + .build() + .into_future() + .from_err() + .join(msg) + .and_then(move |(req, msg)| { + req.send(msg) + .from_err() + .and_then(|req| req.recv().from_err()) + .map(|_| ()) + }) + } +} diff --git a/src/lib.rs b/src/lib.rs index 87aba3c..279fd40 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,3 +7,6 @@ pub use jobs_tokio::{JobRunner, ProcessorHandle}; #[cfg(feature = "jobs-actix")] pub use jobs_actix::{JobsActor, JobsBuilder, QueueJob}; + +#[cfg(feature = "jobs-server-tokio")] +pub use jobs_server_tokio::{ClientConfig, ServerConfig, SpawnerConfig};