Skip to main content

solti_api/
lib.rs

1//! # solti-api - task management API.
2//!
3//! Dual-transport API layer exposing task operations over gRPC and HTTP.
4//! Both transports share the same wire types generated from `proto/solti/task/v1/*.proto` and delegate to an [`ApiHandler`] implementation.
5//!
6//! | feature | transport         | module                                |
7//! |---------|-------------------|---------------------------------------|
8//! | `grpc`  | tonic gRPC server | `TaskApiService`, `TaskServiceServer` |
9//! | `http`  | axum HTTP/JSON    | `HttpApi`                             |
10//!
11//! ## Quick start
12//!
13//! Build one [`ApiHandler`] and share it across both transports (the handler is `Arc`-wrapped once, then cloned into each server):
14//!
15//! ```text
16//! let handler = Arc::new(SupervisorApiAdapter::new(supervisor));
17//! let grpc    = TaskServiceServer::new(TaskApiService::new(handler.clone()));
18//! let http    = HttpApi::new(handler).router();
19//! ```
20//!
21//! ## Also
22//!
23//! - [`ApiHandler`] transport-agnostic trait with 6 operations.
24//! - [`ApiError`] unified error type mapped to gRPC Status / HTTP JSON.
25//! - [`SupervisorApiAdapter`] default adapter bridging to `SupervisorApi`.
26
27#![forbid(unsafe_code)]
28
29/// Compiles the runnable Rust code blocks in `README.md` as doctests.
30#[cfg(doctest)]
31#[doc = include_str!("../README.md")]
32struct ReadmeDoctests;
33
34#[doc(hidden)]
35#[macro_export]
36macro_rules! solti_api_major {
37    () => {
38        1
39    };
40}
41
42/// Compose a compile-time URL path rooted at `/api/v<API_MAJOR>`.
43#[cfg(feature = "http")]
44#[doc(hidden)]
45#[macro_export]
46macro_rules! api_url {
47    ($path:literal) => {
48        concat!("/api/v", $crate::solti_api_major!(), $path)
49    };
50}
51
52/// Current API protocol version.
53pub const API_VERSION: u32 = solti_api_major!();
54
55/// Maximum accepted request body / message size for both HTTP and gRPC transports. **4 MiB.**
56pub const MAX_REQUEST_BYTES: usize = 4 * 1024 * 1024;
57
58mod error;
59pub use error::ApiError;
60
61mod handler;
62pub use handler::{ApiHandler, OutputEventStream};
63
64mod adapter;
65pub use adapter::SupervisorApiAdapter;
66
67mod metrics;
68#[cfg(feature = "http")]
69pub use metrics::http_metrics_middleware;
70pub use metrics::{
71    ApiMetricsBackend, ApiMetricsHandle, NoOpApiMetrics, Transport, noop_api_metrics,
72};
73
74#[cfg(any(feature = "grpc", feature = "http"))]
75#[cfg_attr(not(feature = "grpc"), allow(dead_code))]
76pub(crate) mod proto_api {
77    include!(concat!(
78        env!("OUT_DIR"),
79        "/solti.task.v",
80        solti_api_major!(),
81        ".rs"
82    ));
83
84    #[cfg(feature = "http")]
85    include!(concat!(
86        env!("OUT_DIR"),
87        "/solti.task.v",
88        solti_api_major!(),
89        ".serde.rs"
90    ));
91}
92
93#[cfg(any(feature = "grpc", feature = "http"))]
94mod convert;
95
96#[cfg(any(feature = "grpc", feature = "http"))]
97mod validate;
98
99#[cfg(feature = "grpc")]
100mod grpc;
101
102#[cfg(feature = "grpc")]
103pub use grpc::{
104    BearerAuth, TaskApiService, build_grpc_server, build_grpc_server_with_auth,
105    build_grpc_server_with_metrics, build_grpc_server_with_metrics_auth,
106};
107
108#[cfg(feature = "grpc")]
109pub use proto_api::task_service_server::TaskServiceServer;
110
111#[cfg(feature = "grpc")]
112pub use tonic;
113
114#[cfg(feature = "http")]
115mod http;
116
117#[cfg(feature = "http")]
118pub use http::HttpApi;
119
120#[cfg(feature = "http")]
121pub use axum;
122
123#[cfg(all(feature = "grpc", feature = "tls"))]
124mod tls;
125
126#[cfg(all(feature = "grpc", feature = "tls"))]
127pub use tls::to_tonic_server_tls;
128
129#[cfg(all(test, any(feature = "grpc", feature = "http")))]
130mod api_major_guard {
131    #[test]
132    fn api_major_matches_build_rs() {
133        assert_eq!(
134            super::API_VERSION.to_string(),
135            env!("SOLTI_API_MAJOR"),
136            "lib.rs solti_api_major!() must match build.rs API_MAJOR",
137        );
138    }
139}