pub trait Backend:
Send
+ Sync
+ 'static {
// Required methods
fn names(&self) -> Vec<String>;
fn summary(&self, name: &str) -> Result<DatasetSummary, AppError>;
fn schema(&self, name: &str) -> Result<Arc<DatasetSchema>, AppError>;
fn sample<'life0, 'life1, 'async_trait>(
&'life0 self,
name: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<String, AppError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
fn query<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
name: &'life1 str,
req: &'life2 QueryRequest,
) -> Pin<Box<dyn Future<Output = Result<String, AppError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait;
fn count<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
name: &'life1 str,
req: &'life2 CountRequest,
) -> Pin<Box<dyn Future<Output = Result<i64, AppError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait;
fn reload<'life0, 'life1, 'async_trait>(
&'life0 self,
name: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<ReloadStats, AppError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
// Provided methods
fn indexed_columns(&self, _name: &str) -> Result<Vec<String>, AppError> { ... }
fn query_arrow<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
_name: &'life1 str,
_req: &'life2 QueryRequest,
) -> Pin<Box<dyn Future<Output = Result<Vec<u8>, AppError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait { ... }
fn query_arrow_stream<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
name: &'life1 str,
req: &'life2 QueryRequest,
) -> Pin<Box<dyn Future<Output = Result<ArrowIpcStream, AppError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait { ... }
fn query_arrow_stream_all<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
name: &'life1 str,
req: &'life2 QueryRequest,
) -> Pin<Box<dyn Future<Output = Result<ArrowIpcStream, AppError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait { ... }
fn parquet<'life0, 'life1, 'async_trait>(
&'life0 self,
_name: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Bytes, AppError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait { ... }
}Expand description
Read / reload interface every backend exposes to the HTTP layer.
All methods are async — synchronous backends (DuckDB) wrap their
blocking calls in actix_web::web::block inside the impl.
Required Methods§
Sourcefn summary(&self, name: &str) -> Result<DatasetSummary, AppError>
fn summary(&self, name: &str) -> Result<DatasetSummary, AppError>
Cheap summary for the dataset listing endpoint. Err(NotFound)
on unknown name.
Sourcefn schema(&self, name: &str) -> Result<Arc<DatasetSchema>, AppError>
fn schema(&self, name: &str) -> Result<Arc<DatasetSchema>, AppError>
Full schema for name. Err(NotFound) on unknown name.
Sourcefn sample<'life0, 'life1, 'async_trait>(
&'life0 self,
name: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<String, AppError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn sample<'life0, 'life1, 'async_trait>(
&'life0 self,
name: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<String, AppError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
JSON for the first row of the dataset, or the literal string
"null" if the dataset is empty.
Sourcefn query<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
name: &'life1 str,
req: &'life2 QueryRequest,
) -> Pin<Box<dyn Future<Output = Result<String, AppError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn query<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
name: &'life1 str,
req: &'life2 QueryRequest,
) -> Pin<Box<dyn Future<Output = Result<String, AppError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Execute req against name, returning the JSON-encoded data
array (without the {"data": …, "page": …} envelope — that’s
added by the handler).
Sourcefn count<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
name: &'life1 str,
req: &'life2 CountRequest,
) -> Pin<Box<dyn Future<Output = Result<i64, AppError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn count<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
name: &'life1 str,
req: &'life2 CountRequest,
) -> Pin<Box<dyn Future<Output = Result<i64, AppError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Count rows in name matching req.predicates.
Sourcefn reload<'life0, 'life1, 'async_trait>(
&'life0 self,
name: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<ReloadStats, AppError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn reload<'life0, 'life1, 'async_trait>(
&'life0 self,
name: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<ReloadStats, AppError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Rebuild name from its configured source and atomically swap it in.
Provided Methods§
Sourcefn indexed_columns(&self, _name: &str) -> Result<Vec<String>, AppError>
fn indexed_columns(&self, _name: &str) -> Result<Vec<String>, AppError>
Names of columns the backend has built an equality index over,
for inclusion in the /schema response. Default impl returns
an empty vec — backends without per-column indexes (e.g.
DuckDB, which relies on the embedded database engine) need
not override.
Sourcefn query_arrow<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
_name: &'life1 str,
_req: &'life2 QueryRequest,
) -> Pin<Box<dyn Future<Output = Result<Vec<u8>, AppError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn query_arrow<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
_name: &'life1 str,
_req: &'life2 QueryRequest,
) -> Pin<Box<dyn Future<Output = Result<Vec<u8>, AppError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Execute req against name, returning the result as an Arrow IPC
stream byte buffer (one schema message + zero or more
RecordBatch messages + EOS). The handler ships this verbatim
with Content-Type: application/vnd.apache.arrow.stream.
Default impl errors with InvalidValue — backends that don’t
produce Arrow natively (e.g. DuckDB today) reject the format and
the handler falls through to JSON. Override on backends where
batches are already Arrow.
Sourcefn query_arrow_stream<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
name: &'life1 str,
req: &'life2 QueryRequest,
) -> Pin<Box<dyn Future<Output = Result<ArrowIpcStream, AppError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn query_arrow_stream<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
name: &'life1 str,
req: &'life2 QueryRequest,
) -> Pin<Box<dyn Future<Output = Result<ArrowIpcStream, AppError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Execute req and stream the Arrow IPC bytes. The default adapter
preserves compatibility for backends that only implement
Backend::query_arrow, but high-throughput backends should
override this to avoid building one full response buffer.
Sourcefn query_arrow_stream_all<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
name: &'life1 str,
req: &'life2 QueryRequest,
) -> Pin<Box<dyn Future<Output = Result<ArrowIpcStream, AppError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn query_arrow_stream_all<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
name: &'life1 str,
req: &'life2 QueryRequest,
) -> Pin<Box<dyn Future<Output = Result<ArrowIpcStream, AppError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Execute req and stream all matching Arrow IPC batches in one HTTP
response. Unlike Backend::query_arrow_stream, this is not page
scoped; limit may still cap the total rows returned.
Sourcefn parquet<'life0, 'life1, 'async_trait>(
&'life0 self,
_name: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Bytes, AppError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn parquet<'life0, 'life1, 'async_trait>(
&'life0 self,
_name: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Bytes, AppError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Encode the entire dataset as a single self-contained Parquet file, returned as in-memory bytes.
Powers GET /datasets/{name}/parquet, which serves these bytes
with HTTP range support so external tools (DuckDB httpfs, pandas,
polars, …) can read the dataset straight over HTTP — e.g.
SELECT count(*) FROM 'http://host/api/v1/datasets/accidents/parquet'.
The handler caches the result per dataset (and invalidates on
reload) so the repeated range requests a Parquet reader makes all
see identical, stable bytes. Default impl errors with
InvalidValue; every shipped backend overrides it.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".