hotshot_query_service/fetching/
provider.rs

1// Copyright (c) 2022 Espresso Systems (espressosys.com)
2// This file is part of the HotShot Query Service library.
3//
4// This program is free software: you can redistribute it and/or modify it under the terms of the GNU
5// General Public License as published by the Free Software Foundation, either version 3 of the
6// License, or (at your option) any later version.
7// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
8// even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9// General Public License for more details.
10// You should have received a copy of the GNU General Public License along with this program. If not,
11// see <https://www.gnu.org/licenses/>.
12
13//! Asynchronous fetching from external data availability providers.
14//!
15//! Occasionally, data will be missing from the local persistent storage of this query service. This
16//! may be because the query service never received the data from the attached HotShot instance,
17//! which happens for each block payload committed while the attached HotShot instance is not a
18//! member of the DA committee. It may also be because the query service was started some time after
19//! the start of consensus, and needs to catch up on existing data. Or it may simply be a result of
20//! failures in the local storage medium.
21//!
22//! In any case, the query service is able to fetch missing data asynchronously and out of
23//! chronological order, and pending [`Fetch`](crate::availability::Fetch) requests for the missing
24//! data will resolve as soon as the data is available. Data can be fetched from any external data
25//! availability service, including the HotShot CDN, the data availability committee which is
26//! responsible for providing a particular payload, or another instance of this same query service.
27//!
28//! This module defines an abstract interface [`Provider`], which allows data to be fetched from any
29//! data availability provider, as well as various implementations for different data sources,
30//! including:
31//! * [`QueryServiceProvider`]
32//!
33//! We also provide combinators for modularly adding functionality to existing fetchers:
34//! * [`AnyProvider`]
35//! * [`TestProvider`]
36//!
37
38use std::sync::Arc;
39
40use async_trait::async_trait;
41
42use super::Request;
43
44mod any;
45mod query_service;
46mod testing;
47
48pub use any::AnyProvider;
49pub use query_service::QueryServiceProvider;
50#[cfg(any(test, feature = "testing"))]
51pub use testing::TestProvider;
52
53/// A provider which is able to satisfy requests for data of type `T`.
54///
55/// This trait use boxed future return types (`#[async_trait]`) instead of `impl Future` return
56/// types, so that it can be object safe.
57#[async_trait]
58pub trait Provider<Types, T: Request<Types>>: Send + Sync {
59    /// Fetch a resource.
60    async fn fetch(&self, req: T) -> Option<T::Response>;
61}
62
63/// Trivial [`Provider`] where fetching always fails.
64///
65/// Useful for examples and tests which should never have need of a fetcher.
66#[derive(Clone, Copy, Debug, Default)]
67pub struct NoFetching;
68
69#[async_trait]
70impl<Types, T: Send + Request<Types> + 'static> Provider<Types, T> for NoFetching {
71    async fn fetch(&self, _req: T) -> Option<T::Response> {
72        None
73    }
74}
75
76#[async_trait]
77impl<Types, T, P> Provider<Types, T> for Arc<P>
78where
79    T: Request<Types> + 'static,
80    P: Provider<Types, T> + Sync,
81{
82    async fn fetch(&self, req: T) -> Option<T::Response> {
83        (**self).fetch(req).await
84    }
85}