From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.proxmox.com (Postfix) with ESMTPS id 48114BE74 for ; Fri, 8 Apr 2022 11:56:45 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 3EF13D351 for ; Fri, 8 Apr 2022 11:56:15 +0200 (CEST) Received: from proxmox-new.maurer-it.com (proxmox-new.maurer-it.com [94.136.29.106]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by firstgate.proxmox.com (Proxmox) with ESMTPS id 5AB32D222 for ; Fri, 8 Apr 2022 11:56:08 +0200 (CEST) Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1]) by proxmox-new.maurer-it.com (Proxmox) with ESMTP id 30D8E45A0A for ; Fri, 8 Apr 2022 11:56:08 +0200 (CEST) From: Dominik Csapak To: pbs-devel@lists.proxmox.com Date: Fri, 8 Apr 2022 11:56:03 +0200 Message-Id: <20220408095606.2767234-5-d.csapak@proxmox.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220408095606.2767234-1-d.csapak@proxmox.com> References: <20220408095606.2767234-1-d.csapak@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL -0.010 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment POISEN_SPAM_PILL 0.1 Meta: its spam POISEN_SPAM_PILL_2 0.1 random spam to be learned in bayes POISEN_SPAM_PILL_4 0.1 random spam to be learned in bayes SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record T_SCC_BODY_TEXT_LINE -0.01 - Subject: [pbs-devel] [PATCH proxmox 4/4] proxmox-api-macro: add 'streaming' option X-BeenThere: pbs-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox Backup Server development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 08 Apr 2022 09:56:45 -0000 to generate the `Streaming` variants of the ApiHandler Signed-off-by: Dominik Csapak --- proxmox-api-macro/src/api/method.rs | 127 +++++++++++++++++++--------- proxmox-api-macro/tests/api1.rs | 16 ++++ 2 files changed, 104 insertions(+), 39 deletions(-) diff --git a/proxmox-api-macro/src/api/method.rs b/proxmox-api-macro/src/api/method.rs index f82cc53..1db6124 100644 --- a/proxmox-api-macro/src/api/method.rs +++ b/proxmox-api-macro/src/api/method.rs @@ -169,6 +169,12 @@ pub fn handle_method(mut attribs: JSONObject, mut func: syn::ItemFn) -> Result Result Result quote! { ::proxmox_router::ApiHandler::StreamingAsync(&#api_func_name) }, + (true, false) => quote! { ::proxmox_router::ApiHandler::StreamingSync(&#api_func_name) }, + (false, true) => quote! { ::proxmox_router::ApiHandler::Async(&#api_func_name) }, + (false, false) => quote! { ::proxmox_router::ApiHandler::Sync(&#api_func_name) }, }; Ok(quote_spanned! { func.sig.span() => @@ -279,6 +287,7 @@ fn handle_function_signature( func: &mut syn::ItemFn, wrapper_ts: &mut TokenStream, default_consts: &mut TokenStream, + streaming: bool, ) -> Result { let sig = &func.sig; let is_async = sig.asyncness.is_some(); @@ -414,6 +423,7 @@ fn handle_function_signature( wrapper_ts, default_consts, is_async, + streaming, ) } @@ -471,6 +481,7 @@ fn create_wrapper_function( wrapper_ts: &mut TokenStream, default_consts: &mut TokenStream, is_async: bool, + streaming: bool, ) -> Result { let api_func_name = Ident::new( &format!("api_function_{}", &func.sig.ident), @@ -512,45 +523,83 @@ fn create_wrapper_function( _ => Some(quote!(?)), }; - let body = quote! { - if let ::serde_json::Value::Object(ref mut input_map) = &mut input_params { - #body - Ok(::serde_json::to_value(#func_name(#args) #await_keyword #question_mark)?) - } else { - ::anyhow::bail!("api function wrapper called with a non-object json value"); - } - }; - - if is_async { - 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::ApiFuture<'a> { - //async fn func<'a>( - // mut input_params: ::serde_json::Value, - // api_method_param: &'static ::proxmox_router::ApiMethod, - // rpc_env_param: &'a mut dyn ::proxmox_router::RpcEnvironment, - //) -> ::std::result::Result<::serde_json::Value, ::anyhow::Error> { - // #body - //} - //::std::boxed::Box::pin(async move { - // func(input_params, api_method_param, rpc_env_param).await - //}) - ::std::boxed::Box::pin(async move { #body }) + let body = if streaming { + quote! { + if let ::serde_json::Value::Object(ref mut input_map) = &mut input_params { + #body + let res = #func_name(#args) #await_keyword #question_mark; + let res: ::std::boxed::Box = ::std::boxed::Box::new(res); + Ok(res) + } else { + ::anyhow::bail!("api function wrapper called with a non-object json value"); } - }); + } } else { - wrapper_ts.extend(quote! { - fn #api_func_name( - mut input_params: ::serde_json::Value, - api_method_param: &::proxmox_router::ApiMethod, - rpc_env_param: &mut dyn ::proxmox_router::RpcEnvironment, - ) -> ::std::result::Result<::serde_json::Value, ::anyhow::Error> { + quote! { + if let ::serde_json::Value::Object(ref mut input_map) = &mut input_params { #body + Ok(::serde_json::to_value(#func_name(#args) #await_keyword #question_mark)?) + } else { + ::anyhow::bail!("api function wrapper called with a non-object json value"); } - }); + } + }; + + match (streaming, 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> { + ::std::boxed::Box::pin(async move { #body }) + } + }); + } + (true, false) => { + wrapper_ts.extend(quote! { + fn #api_func_name( + mut input_params: ::serde_json::Value, + api_method_param: &::proxmox_router::ApiMethod, + rpc_env_param: &mut dyn ::proxmox_router::RpcEnvironment, + ) -> ::std::result::Result<::std::boxed::Box, ::anyhow::Error> { + #body + } + }); + } + (false, 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::ApiFuture<'a> { + //async fn func<'a>( + // mut input_params: ::serde_json::Value, + // api_method_param: &'static ::proxmox_router::ApiMethod, + // rpc_env_param: &'a mut dyn ::proxmox_router::RpcEnvironment, + //) -> ::std::result::Result<::serde_json::Value, ::anyhow::Error> { + // #body + //} + //::std::boxed::Box::pin(async move { + // func(input_params, api_method_param, rpc_env_param).await + //}) + ::std::boxed::Box::pin(async move { #body }) + } + }); + } + (false, false) => { + wrapper_ts.extend(quote! { + fn #api_func_name( + mut input_params: ::serde_json::Value, + api_method_param: &::proxmox_router::ApiMethod, + rpc_env_param: &mut dyn ::proxmox_router::RpcEnvironment, + ) -> ::std::result::Result<::serde_json::Value, ::anyhow::Error> { + #body + } + }); + } } Ok(api_func_name) diff --git a/proxmox-api-macro/tests/api1.rs b/proxmox-api-macro/tests/api1.rs index fd9a338..ef60370 100644 --- a/proxmox-api-macro/tests/api1.rs +++ b/proxmox-api-macro/tests/api1.rs @@ -235,6 +235,22 @@ pub fn basic_function() -> Result<(), Error> { Ok(()) } +#[api( + streaming: true, +)] +/// streaming async call +pub async fn streaming_async_call() -> Result<(), Error> { + Ok(()) +} + +#[api( + streaming: true, +)] +/// streaming sync call +pub fn streaming_sync_call() -> Result<(), Error> { + Ok(()) +} + #[api( input: { properties: { -- 2.30.2