router, rest-server, api-macro: rename Streaming api to Serializing
This does not "stream", but rather skips the intermediate step to serialize the entire output into a local json string. We now reserve the "Stream*" prefix for actual *streaming*, that is, producing an API response which gets streamed continuously as it is asynchronously produced. Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
parent
e8b8060b17
commit
c31eaf0018
@ -169,8 +169,15 @@ pub fn handle_method(mut attribs: JSONObject, mut func: syn::ItemFn) -> Result<T
|
||||
.transpose()?
|
||||
.unwrap_or(false);
|
||||
|
||||
let streaming: bool = attribs
|
||||
.remove("streaming")
|
||||
if let Some(streaming) = attribs.remove("streaming") {
|
||||
error!(
|
||||
streaming.span(),
|
||||
"streaming attribute was renamed to 'serializing', as it did not actually stream"
|
||||
);
|
||||
}
|
||||
|
||||
let serializing: bool = attribs
|
||||
.remove("serializing")
|
||||
.map(TryFrom::try_from)
|
||||
.transpose()?
|
||||
.unwrap_or(false);
|
||||
@ -201,7 +208,7 @@ pub fn handle_method(mut attribs: JSONObject, mut func: syn::ItemFn) -> Result<T
|
||||
&mut func,
|
||||
&mut wrapper_ts,
|
||||
&mut default_consts,
|
||||
streaming,
|
||||
serializing,
|
||||
)?;
|
||||
|
||||
// input schema is done, let's give the method body a chance to extract default parameters:
|
||||
@ -224,9 +231,9 @@ pub fn handle_method(mut attribs: JSONObject, mut func: syn::ItemFn) -> Result<T
|
||||
returns_schema_setter = quote! { .returns(#inner) };
|
||||
}
|
||||
|
||||
let api_handler = match (streaming, is_async) {
|
||||
(true, true) => quote! { ::proxmox_router::ApiHandler::StreamingAsync(&#api_func_name) },
|
||||
(true, false) => quote! { ::proxmox_router::ApiHandler::StreamingSync(&#api_func_name) },
|
||||
let api_handler = match (serializing, is_async) {
|
||||
(true, true) => quote! { ::proxmox_router::ApiHandler::SerializingAsync(&#api_func_name) },
|
||||
(true, false) => quote! { ::proxmox_router::ApiHandler::SerializingSync(&#api_func_name) },
|
||||
(false, true) => quote! { ::proxmox_router::ApiHandler::Async(&#api_func_name) },
|
||||
(false, false) => quote! { ::proxmox_router::ApiHandler::Sync(&#api_func_name) },
|
||||
};
|
||||
@ -287,7 +294,7 @@ fn handle_function_signature(
|
||||
func: &mut syn::ItemFn,
|
||||
wrapper_ts: &mut TokenStream,
|
||||
default_consts: &mut TokenStream,
|
||||
streaming: bool,
|
||||
serializing: bool,
|
||||
) -> Result<Ident, Error> {
|
||||
let sig = &func.sig;
|
||||
let is_async = sig.asyncness.is_some();
|
||||
@ -423,7 +430,7 @@ fn handle_function_signature(
|
||||
wrapper_ts,
|
||||
default_consts,
|
||||
is_async,
|
||||
streaming,
|
||||
serializing,
|
||||
)
|
||||
}
|
||||
|
||||
@ -481,7 +488,7 @@ fn create_wrapper_function(
|
||||
wrapper_ts: &mut TokenStream,
|
||||
default_consts: &mut TokenStream,
|
||||
is_async: bool,
|
||||
streaming: bool,
|
||||
serializing: bool,
|
||||
) -> Result<Ident, Error> {
|
||||
let api_func_name = Ident::new(
|
||||
&format!("api_function_{}", &func.sig.ident),
|
||||
@ -523,7 +530,7 @@ fn create_wrapper_function(
|
||||
_ => Some(quote!(?)),
|
||||
};
|
||||
|
||||
let body = if streaming {
|
||||
let body = if serializing {
|
||||
quote! {
|
||||
if let ::serde_json::Value::Object(ref mut input_map) = &mut input_params {
|
||||
#body
|
||||
@ -545,14 +552,14 @@ fn create_wrapper_function(
|
||||
}
|
||||
};
|
||||
|
||||
match (streaming, is_async) {
|
||||
match (serializing, is_async) {
|
||||
(true, true) => {
|
||||
wrapper_ts.extend(quote! {
|
||||
fn #api_func_name<'a>(
|
||||
mut input_params: ::serde_json::Value,
|
||||
api_method_param: &'static ::proxmox_router::ApiMethod,
|
||||
rpc_env_param: &'a mut dyn ::proxmox_router::RpcEnvironment,
|
||||
) -> ::proxmox_router::StreamingApiFuture<'a> {
|
||||
) -> ::proxmox_router::SerializingApiFuture<'a> {
|
||||
::std::boxed::Box::pin(async move { #body })
|
||||
}
|
||||
});
|
||||
|
@ -236,18 +236,18 @@ pub fn basic_function() -> Result<(), Error> {
|
||||
}
|
||||
|
||||
#[api(
|
||||
streaming: true,
|
||||
serializing: true,
|
||||
)]
|
||||
/// streaming async call
|
||||
pub async fn streaming_async_call() -> Result<(), Error> {
|
||||
/// serializing async call
|
||||
pub async fn serializing_async_call() -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[api(
|
||||
streaming: true,
|
||||
serializing: true,
|
||||
)]
|
||||
/// streaming sync call
|
||||
pub fn streaming_sync_call() -> Result<(), Error> {
|
||||
/// serializing sync call
|
||||
pub fn serializing_sync_call() -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -505,13 +505,13 @@ pub(crate) async fn handle_api_request<Env: RpcEnvironment, S: 'static + BuildHa
|
||||
let params = parse_query_parameters(info.parameters, "", &parts, &uri_param)?;
|
||||
(handler)(parts, req_body, params, info, Box::new(rpcenv)).await
|
||||
}
|
||||
ApiHandler::StreamingSync(handler) => {
|
||||
ApiHandler::SerializingSync(handler) => {
|
||||
let params =
|
||||
get_request_parameters(info.parameters, parts, req_body, uri_param).await?;
|
||||
(handler)(params, info, &mut rpcenv)
|
||||
.and_then(|data| formatter.format_data_streaming(data, &rpcenv))
|
||||
}
|
||||
ApiHandler::StreamingAsync(handler) => {
|
||||
ApiHandler::SerializingAsync(handler) => {
|
||||
let params =
|
||||
get_request_parameters(info.parameters, parts, req_body, uri_param).await?;
|
||||
(handler)(params, info, &mut rpcenv)
|
||||
@ -617,11 +617,11 @@ async fn handle_unformatted_api_request<Env: RpcEnvironment, S: 'static + BuildH
|
||||
.await
|
||||
.and_then(|v| to_json_response(v, &rpcenv))
|
||||
}
|
||||
ApiHandler::StreamingSync(_) => http_bail!(
|
||||
ApiHandler::SerializingSync(_) => http_bail!(
|
||||
INTERNAL_SERVER_ERROR,
|
||||
"old-style streaming calls not supported"
|
||||
),
|
||||
ApiHandler::StreamingAsync(_) => http_bail!(
|
||||
ApiHandler::SerializingAsync(_) => http_bail!(
|
||||
INTERNAL_SERVER_ERROR,
|
||||
"old-style streaming calls not supported"
|
||||
),
|
||||
|
@ -88,10 +88,10 @@ async fn handle_simple_command_future(
|
||||
|
||||
let result = match cli_cmd.info.handler {
|
||||
ApiHandler::Sync(handler) => (handler)(params, cli_cmd.info, &mut rpcenv),
|
||||
ApiHandler::StreamingSync(handler) => (handler)(params, cli_cmd.info, &mut rpcenv)
|
||||
ApiHandler::SerializingSync(handler) => (handler)(params, cli_cmd.info, &mut rpcenv)
|
||||
.and_then(|r| r.to_value().map_err(Error::from)),
|
||||
ApiHandler::Async(handler) => (handler)(params, cli_cmd.info, &mut rpcenv).await,
|
||||
ApiHandler::StreamingAsync(handler) => (handler)(params, cli_cmd.info, &mut rpcenv)
|
||||
ApiHandler::SerializingAsync(handler) => (handler)(params, cli_cmd.info, &mut rpcenv)
|
||||
.await
|
||||
.and_then(|r| r.to_value().map_err(Error::from)),
|
||||
#[cfg(feature = "server")]
|
||||
@ -127,7 +127,7 @@ pub(crate) fn handle_simple_command<'cli>(
|
||||
|
||||
let result = match cli_cmd.info.handler {
|
||||
ApiHandler::Sync(handler) => (handler)(params, cli_cmd.info, rpcenv),
|
||||
ApiHandler::StreamingSync(handler) => {
|
||||
ApiHandler::SerializingSync(handler) => {
|
||||
(handler)(params, cli_cmd.info, rpcenv).and_then(|r| r.to_value().map_err(Error::from))
|
||||
}
|
||||
ApiHandler::Async(handler) => {
|
||||
@ -137,8 +137,8 @@ pub(crate) fn handle_simple_command<'cli>(
|
||||
let future = (handler)(params, cli_cmd.info, rpcenv);
|
||||
(run)(future)
|
||||
}
|
||||
ApiHandler::StreamingAsync(_handler) => {
|
||||
bail!("CliHandler does not support ApiHandler::StreamingAsync - internal error");
|
||||
ApiHandler::SerializingAsync(_handler) => {
|
||||
bail!("CliHandler does not support ApiHandler::SerializingAsync - internal error");
|
||||
}
|
||||
#[cfg(feature = "server")]
|
||||
ApiHandler::AsyncHttp(_) => {
|
||||
|
@ -64,11 +64,11 @@ pub type ApiHandlerFn = &'static (dyn Fn(Value, &ApiMethod, &mut dyn RpcEnvironm
|
||||
/// }
|
||||
///
|
||||
/// const API_METHOD_HELLO: ApiMethod = ApiMethod::new(
|
||||
/// &ApiHandler::StreamingSync(&hello),
|
||||
/// &ApiHandler::SerializingSync(&hello),
|
||||
/// &ObjectSchema::new("Hello World Example", &[])
|
||||
/// );
|
||||
/// ```
|
||||
pub type StreamingApiHandlerFn = &'static (dyn Fn(
|
||||
pub type SerializingApiHandlerFn = &'static (dyn Fn(
|
||||
Value,
|
||||
&ApiMethod,
|
||||
&mut dyn RpcEnvironment,
|
||||
@ -109,13 +109,13 @@ pub type ApiAsyncHandlerFn = &'static (dyn for<'a> Fn(Value, &'static ApiMethod,
|
||||
|
||||
pub type ApiFuture<'a> = Pin<Box<dyn Future<Output = Result<Value, anyhow::Error>> + Send + 'a>>;
|
||||
|
||||
/// Streaming asynchronous API handlers
|
||||
/// Serializing asynchronous API handlers
|
||||
///
|
||||
/// Returns a future Value.
|
||||
/// ```
|
||||
/// # use serde_json::{json, Value};
|
||||
/// #
|
||||
/// use proxmox_router::{ApiFuture, ApiHandler, ApiMethod, RpcEnvironment, StreamingApiFuture, SerializableReturn};
|
||||
/// use proxmox_router::{ApiFuture, ApiHandler, ApiMethod, RpcEnvironment, SerializingApiFuture, SerializableReturn};
|
||||
/// use proxmox_schema::ObjectSchema;
|
||||
///
|
||||
///
|
||||
@ -123,7 +123,7 @@ pub type ApiFuture<'a> = Pin<Box<dyn Future<Output = Result<Value, anyhow::Error
|
||||
/// param: Value,
|
||||
/// info: &ApiMethod,
|
||||
/// rpcenv: &'a mut dyn RpcEnvironment,
|
||||
/// ) -> StreamingApiFuture<'a> {
|
||||
/// ) -> SerializingApiFuture<'a> {
|
||||
/// Box::pin(async move {
|
||||
/// let res: Box<dyn SerializableReturn + Send> = Box::new(format!("Hello World!"));
|
||||
/// Ok(res)
|
||||
@ -131,19 +131,19 @@ pub type ApiFuture<'a> = Pin<Box<dyn Future<Output = Result<Value, anyhow::Error
|
||||
/// }
|
||||
///
|
||||
/// const API_METHOD_HELLO_FUTURE: ApiMethod = ApiMethod::new(
|
||||
/// &ApiHandler::StreamingAsync(&hello_future),
|
||||
/// &ApiHandler::SerializingAsync(&hello_future),
|
||||
/// &ObjectSchema::new("Hello World Example (async)", &[])
|
||||
/// );
|
||||
/// ```
|
||||
pub type StreamingApiAsyncHandlerFn = &'static (dyn for<'a> Fn(
|
||||
pub type SerializingApiAsyncHandlerFn = &'static (dyn for<'a> Fn(
|
||||
Value,
|
||||
&'static ApiMethod,
|
||||
&'a mut dyn RpcEnvironment,
|
||||
) -> StreamingApiFuture<'a>
|
||||
) -> SerializingApiFuture<'a>
|
||||
+ Send
|
||||
+ Sync);
|
||||
|
||||
pub type StreamingApiFuture<'a> = Pin<
|
||||
pub type SerializingApiFuture<'a> = Pin<
|
||||
Box<dyn Future<Output = Result<Box<dyn SerializableReturn + Send>, anyhow::Error>> + Send + 'a>,
|
||||
>;
|
||||
|
||||
@ -200,9 +200,9 @@ pub type ApiResponseFuture =
|
||||
#[non_exhaustive]
|
||||
pub enum ApiHandler {
|
||||
Sync(ApiHandlerFn),
|
||||
StreamingSync(StreamingApiHandlerFn),
|
||||
SerializingSync(SerializingApiHandlerFn),
|
||||
Async(ApiAsyncHandlerFn),
|
||||
StreamingAsync(StreamingApiAsyncHandlerFn),
|
||||
SerializingAsync(SerializingApiAsyncHandlerFn),
|
||||
#[cfg(feature = "server")]
|
||||
AsyncHttp(ApiAsyncHttpHandlerFn),
|
||||
}
|
||||
@ -218,13 +218,13 @@ impl PartialEq for ApiHandler {
|
||||
(ApiHandler::Sync(l), ApiHandler::Sync(r)) => {
|
||||
core::mem::transmute::<_, usize>(l) == core::mem::transmute::<_, usize>(r)
|
||||
}
|
||||
(ApiHandler::StreamingSync(l), ApiHandler::StreamingSync(r)) => {
|
||||
(ApiHandler::SerializingSync(l), ApiHandler::SerializingSync(r)) => {
|
||||
core::mem::transmute::<_, usize>(l) == core::mem::transmute::<_, usize>(r)
|
||||
}
|
||||
(ApiHandler::Async(l), ApiHandler::Async(r)) => {
|
||||
core::mem::transmute::<_, usize>(l) == core::mem::transmute::<_, usize>(r)
|
||||
}
|
||||
(ApiHandler::StreamingAsync(l), ApiHandler::StreamingAsync(r)) => {
|
||||
(ApiHandler::SerializingAsync(l), ApiHandler::SerializingAsync(r)) => {
|
||||
core::mem::transmute::<_, usize>(l) == core::mem::transmute::<_, usize>(r)
|
||||
}
|
||||
#[cfg(feature = "server")]
|
||||
|
Loading…
Reference in New Issue
Block a user