spire_core/worker/mod.rs
1//! Workers, which handle fetched requests, and their [`Outcome`]s.
2
3mod outcome;
4
5use std::fmt;
6use std::future::Future;
7
8pub use outcome::{IntoOutcome, Outcome, Scope};
9
10use crate::context::Context;
11
12/// Handles one request of a crawl.
13///
14/// The worker receives a [`Context`] holding the request and a client for
15/// it. It decides when, and whether, to fetch the response, may queue
16/// further requests, and tells the crawler what to do next.
17pub trait Worker<C>: Send + Sync + 'static {
18 /// Handles the request in `cx`.
19 fn handle(&self, cx: Context<C>) -> impl Future<Output = Outcome> + Send;
20}
21
22/// Creates a [`Worker`] from an async function.
23///
24/// # Examples
25///
26/// ```
27/// use spire_core::backend::Noop;
28/// use spire_core::worker::from_fn;
29/// use spire_core::{Context, Result};
30///
31/// async fn handle(cx: Context<Noop>) -> Result<()> {
32/// let response = cx.fetch().await?;
33/// println!("status: {}", response.status());
34/// Ok(())
35/// }
36///
37/// let worker = from_fn(handle);
38/// ```
39pub const fn from_fn<F>(f: F) -> FromFn<F> {
40 FromFn(f)
41}
42
43/// A [`Worker`] backed by an async function, created by [`from_fn`].
44#[derive(Clone, Copy)]
45pub struct FromFn<F>(F);
46
47impl<C, F, Fut> Worker<C> for FromFn<F>
48where
49 C: Send + 'static,
50 F: Fn(Context<C>) -> Fut + Send + Sync + 'static,
51 Fut: Future<Output: IntoOutcome> + Send,
52{
53 fn handle(&self, cx: Context<C>) -> impl Future<Output = Outcome> + Send {
54 let future = (self.0)(cx);
55 async move { future.await.into_outcome() }
56 }
57}
58
59impl<F> fmt::Debug for FromFn<F> {
60 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
61 f.debug_struct("FromFn").finish_non_exhaustive()
62 }
63}