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/v1/*.proto` and delegate to an [`ApiHandler`] implementation.
5//!
6//! | feature | transport         | module                              |
7//! |---------|-------------------|-------------------------------------|
8//! | `grpc`  | tonic gRPC server | `SoltiApiService`, `SoltiApiServer` |
9//! | `http`  | axum HTTP/JSON    | `HttpApi`                           |
10//!
11//! ## Quick start
12//!
13//! ```text
14//! let adapter = SupervisorApiAdapter::new(supervisor);
15//! let svc     = SoltiApiServer::new(SoltiApiService::new(Arc::new(adapter)));
16//! let router  = HttpApi::new(Arc::new(adapter)).router();
17//! ```
18//!
19//! ## Also
20//!
21//! - [`ApiHandler`] transport-agnostic trait with 6 operations.
22//! - [`ApiError`] unified error type mapped to gRPC Status / HTTP JSON.
23//! - [`SupervisorApiAdapter`] default adapter bridging to `SupervisorApi`.
24
25#[doc(hidden)]
26#[macro_export]
27macro_rules! solti_api_major {
28    () => {
29        1
30    };
31}
32
33/// Compose a compile-time URL path rooted at `/api/v<API_MAJOR>`.
34#[cfg(feature = "http")]
35#[doc(hidden)]
36#[macro_export]
37macro_rules! api_url {
38    ($path:literal) => {
39        concat!("/api/v", $crate::solti_api_major!(), $path)
40    };
41}
42
43/// Current API protocol version.
44pub const API_VERSION: u32 = solti_api_major!();
45
46/// Maximum accepted request body / message size for both HTTP and gRPC transports. **4 MiB.**
47pub const MAX_REQUEST_BYTES: usize = 4 * 1024 * 1024;
48
49mod error;
50pub use error::ApiError;
51
52mod handler;
53pub use handler::{ApiHandler, OutputEventStream};
54
55mod adapter;
56pub use adapter::SupervisorApiAdapter;
57
58mod metrics;
59#[cfg(feature = "http")]
60pub use metrics::http_metrics_middleware;
61pub use metrics::{
62    ApiMetricsBackend, ApiMetricsHandle, NoOpApiMetrics, Transport, noop_api_metrics,
63};
64
65#[cfg(any(feature = "grpc", feature = "http"))]
66#[cfg_attr(not(feature = "grpc"), allow(dead_code))]
67pub(crate) mod proto_api {
68    include!(concat!(
69        env!("OUT_DIR"),
70        "/solti.v",
71        solti_api_major!(),
72        ".rs"
73    ));
74
75    #[cfg(feature = "http")]
76    include!(concat!(
77        env!("OUT_DIR"),
78        "/solti.v",
79        solti_api_major!(),
80        ".serde.rs"
81    ));
82}
83
84#[cfg(any(feature = "grpc", feature = "http"))]
85mod convert;
86
87#[cfg(any(feature = "grpc", feature = "http"))]
88mod validate;
89
90#[cfg(feature = "grpc")]
91mod grpc;
92
93#[cfg(feature = "grpc")]
94pub use grpc::{SoltiApiService, build_grpc_server, build_grpc_server_with_metrics};
95
96#[cfg(feature = "grpc")]
97pub use proto_api::solti_api_server::SoltiApiServer;
98
99#[cfg(feature = "grpc")]
100pub use tonic;
101
102#[cfg(feature = "http")]
103mod http;
104
105#[cfg(feature = "http")]
106pub use http::HttpApi;
107
108#[cfg(feature = "http")]
109pub use axum;
110
111#[cfg(all(feature = "grpc", feature = "tls"))]
112mod tls;
113
114#[cfg(all(feature = "grpc", feature = "tls"))]
115pub use tls::to_tonic_server_tls;
116
117#[cfg(all(test, any(feature = "grpc", feature = "http")))]
118mod api_major_guard {
119    #[test]
120    fn api_major_matches_build_rs() {
121        assert_eq!(
122            super::API_VERSION.to_string(),
123            env!("SOLTI_API_MAJOR"),
124            "lib.rs solti_api_major!() must match build.rs API_MAJOR",
125        );
126    }
127}