use darpi::job::{CpuJob, FutureJob, IOBlockingJob}; use darpi::{ app, handler, job_factory, logger::DefaultFormat, middleware, Body, Json, Method, Path, Query, Request, RequestParts, Response, }; use darpi_middleware::{log_request, log_response}; use env_logger; use serde::{Deserialize, Serialize}; use shaku::module; use std::convert::Infallible; fn make_container() -> Container { let module = Container::builder().build(); module } module! { Container { components = [], providers = [], } } #[derive(Deserialize, Serialize, Debug, Query, Path)] pub struct Name { name: String, } #[job_factory(Request)] async fn first_async_job() -> FutureJob { async { println!("first job in the background.") }.into() } #[job_factory(Response)] async fn first_sync_job(#[response] r: &Response) -> IOBlockingJob { let status_code = r.status(); let job = move || { std::thread::sleep(std::time::Duration::from_secs(2)); println!( "first_sync_job in the background for a request with status {}", status_code ); }; job.into() } #[job_factory(Response)] async fn first_sync_job1() -> CpuJob { let job = || { for _ in 0..100 { let mut r = 0; for _ in 0..10000000 { r += 1; } println!("first_sync_job1 finished in the background. {}", r); } }; job.into() } #[job_factory(Response)] async fn first_sync_io_job() -> IOBlockingJob { let job = || { for i in 0..5 { std::thread::sleep(std::time::Duration::from_secs(1)); println!("sync io finished in the background {}", i); } }; job.into() } // todo make sure Request is passed by value // show a nice error #[handler({ jobs: { response: [first_sync_job, first_sync_job1] } })] async fn hello_world(#[request_parts] r: &RequestParts) -> &'static str { if r.headers.get("destroy-cpu-header").is_some() { let job = || { let mut r = 0; for _ in 0..10000000 { r += 1; } println!("first_sync_job1 finished in the background. {}", r) }; darpi::spawn(CpuJob::from(job)).await.expect("ohh noes"); } "hello world" } #[handler] async fn hello_world1() -> Result { let get_secs = move || { let secs = 2; std::thread::sleep(std::time::Duration::from_secs(secs)); secs }; let secs = darpi::oneshot(IOBlockingJob::from(get_secs)) .await .map_err(|e| format!("{}", e))? .await .map_err(|e| format!("{}", e))?; Ok(format!("waited {} seconds to say hello world", secs)) } #[middleware(Request)] pub(crate) async fn roundtrip( #[request] _rp: &Request, #[handler] msg: impl AsRef + Send + Sync + 'static, ) -> Result { let res = format!("{} from roundtrip middleware", msg.as_ref()); Ok(res) } #[handler({ container: Container, middleware: { request: [roundtrip("blah")] } })] async fn do_something123( // the request query is deserialized into Name // if deseriliazation fails, it will result in an error response // to make it optional wrap it in an Option #[query] query: Name, // the request path is deserialized into Name #[path] path: Name, // the request body is deserialized into the struct Name // it is important to mention that the wrapper around Name // should implement darpi::request::FromRequestBody // Common formats like Json, Xml and Yaml are supported out // of the box but users can implement their own #[body] payload: Json, // we can access the T from Ok(T) in the middleware result #[middleware::request(0)] m_str: String, // returning a String works because darpi has implemented // the Responder trait for common types ) -> String { format!( "query: {:#?} path: {} body: {} middleware: {}", query, path.name, payload.name, m_str ) } //todo add configuration for the 3 different runtimes so the // runtime serving requests doesn't get stomped //RUST_LOG=darpi=info cargo test --test job -- --nocapture //#[tokio::test] #[tokio::test] async fn main() -> Result<(), darpi::Error> { env_logger::builder().is_test(true).try_init().unwrap(); app!({ address: "127.0.0.1:3000", container: { factory: make_container(), type: Container }, jobs: { request: [], response: [first_sync_io_job] }, middleware: { request: [log_request(DefaultFormat)], response: [log_response(DefaultFormat, request(0))] }, handlers: [{ route: "/hello_world", method: Method::GET, handler: hello_world }] }) .run() .await }