#![allow(unused)] use std::{net::SocketAddr, str::FromStr, sync::Mutex}; use tina::{ app_error_from, config::{self, builder::DefaultState, ConfigBuilder}, once_cell::sync::Lazy, tina::{ data::AppResult, data::{app_error::AppError, grpc::request_data::GrpcReqData, number::RandomNumber}, log::LogConfig, server::{ application::{AppConfig, Application, FromApplication}, grpc::{service_ext::GrpcServiceRegister, IGrpcServer}, http::IHttpServer, session::Session, Server, }, }, tracing, Instrument, Span, }; use crate::hello_world::{Greeter, GreeterClient, GreeterService, HelloRequest}; #[macro_use] extern crate tina; static CONTENT: &str = include_str!("./resources/app-config.yml"); mod hello_world { use tina::{ prost::Message, tina::{ client::{GrpcChannel, GrpcClient, GrpcClientProps}, data::{ app_error::AppError, grpc::{request_data::GrpcReqData, response_data::GrpcResData}, AppResult, }, grpc::{request::Request, response::Response, ApiGrpcService, IntoGrpcResponse}, server::{application::Application, session::Session}, }, tower_service::Service, }; use tina::{ serde, tina::{ client::registry::IRegistryClient, grpc::{FromGrpcRequest, FromGrpcResponse}, util::string::AsStr, }, tower::ServiceExt, }; /// hello #[derive(Serialize, Deserialize, ::prost::Message, Clone)] #[serde(crate = "serde")] pub struct HelloRequest { /// id #[prost(int32, tag = "1")] pub id: i32, /// msg #[prost(string, tag = "2")] pub msg: ::prost::alloc::string::String, /// msg #[prost(string, optional, tag = "3")] pub msg2: Option<::prost::alloc::string::String>, /// msg #[prost(string, tag = "4")] pub msg3: String, /// msg #[prost(string, optional, tag = "5")] pub msg4: Option, } #[derive(Serialize, Deserialize, ::prost::Message)] #[serde(crate = "serde")] pub struct HelloResponse { /// id #[prost(int32, tag = "1")] pub id: i32, /// msg #[prost(string, tag = "2")] pub msg: String, } /// hello #[async_trait] pub trait Greeter { /// hello async fn say_hello( &self, application: Application, session: Session, request: GrpcReqData, ) -> AppResult>; /// hello async fn say_error( &self, application: Application, session: Session, request: GrpcReqData, ) -> AppResult>; } /// hello service #[derive(Clone)] pub struct GreeterService; /// hello client #[derive(Clone)] pub struct GreeterClient; #[async_trait] impl Greeter for GreeterClient { async fn say_hello( &self, application: Application, session: Session, request: GrpcReqData, ) -> AppResult> { let client = application.get_registry_client()?; let config = application.get_registry_config()?; let app_name = config.app_name.as_str(); let group = config.group_name.as_str(); let grpc_client = application.get_grpc_client()?; let props = client.get_grpc_client_props(app_name, GreeterService::NAME, group).await?; info!("===== 发送 ====: {request:?}"); let response: AppResult> = grpc_client.send(&props, (application, session, request), "greeter", "sayHello").await; info!("===== 响应 ====: {response:?}"); response } async fn say_error( &self, application: Application, session: Session, request: GrpcReqData, ) -> AppResult> { let client = application.get_registry_client()?; let config = application.get_registry_config()?; let app_name = config.app_name.as_str(); let group = config.group_name.as_str(); let grpc_client = application.get_grpc_client()?; let props = client.get_grpc_client_props(app_name, GreeterService::NAME, group).await?; info!("===== 发送 ====: {request:?}"); let response: AppResult> = grpc_client.send(&props, (application, session, request), "greeter", "sayError").await; info!("===== 响应 ====: {response:?}"); response } } #[async_trait] impl Greeter for GreeterService { async fn say_hello( &self, application: Application, session: Session, request: GrpcReqData, ) -> AppResult> { let data = request.data; let res = HelloResponse { msg: data.msg.to_uppercase(), id: data.id, }; Ok(GrpcResData::new(res).with_metadata("header2", "I am reply say_hello")?) } async fn say_error( &self, application: Application, session: Session, request: GrpcReqData, ) -> AppResult> { let data = request.data; let msg = data.msg; Err(app_system_error!("{msg}")) } } #[async_trait] impl ApiGrpcService for GreeterService { /// 服务名 const NAME: &'static str = "greeter"; /// 异常 type Rejection = AppError; /// 方法调用 async fn call(&self, req: Request) -> Result { match req.uri().path() { "/greeter/sayHello" => { let (application, session, request): (Application, Session, GrpcReqData) = FromGrpcRequest::from_grpc_request(req).await?; info!("===== 接收 ====: {request:?}"); let r = self.say_hello(application, session, request).await; let res = IntoGrpcResponse::into_grpc_response(r).await; Ok(Response::from(res)) } "/greeter/sayError" => { let (application, session, request): (Application, Session, GrpcReqData) = FromGrpcRequest::from_grpc_request(req).await?; info!("===== 接收 ====: {request:?}"); let r = self.say_error(application, session, request).await; let res = IntoGrpcResponse::into_grpc_response(r).await; Ok(Response::from(res)) } _ => Err(app_system_error!("Invalid method")), } } } } #[ignore] #[test] fn regist_server() -> AppResult<()> { GrpcServiceRegister::add_service(GreeterService); let config = ConfigBuilder::::default() .add_source(config::File::from_str(CONTENT, config::FileFormat::Yaml)) .build() .map_err(app_error_from!())?; Server::new() .init(|app_config, _config| async { LogConfig::default().init().await?; Ok(app_config) }) .run_grpc(config); Ok(()) } #[ignore] #[test] fn regist_client() -> AppResult<()> { let config = ConfigBuilder::::default() .add_source(config::File::from_str(CONTENT, config::FileFormat::Yaml)) .build() .map_err(app_error_from!())?; Server::new() .init(|app_config, _config| async { LogConfig::default().init().await?; // let client = app_config.get_grpc_client()?; // client.get_instance(props) Ok(app_config) }) .run_http(config); Ok(()) } #[ignore] #[test] fn regist_client_server_and_grpc_call() -> AppResult<()> { GrpcServiceRegister::add_service(GreeterService); AppError::enable_backtrace(false); let config = ConfigBuilder::::default() .add_source(config::File::from_str(CONTENT, config::FileFormat::Yaml)) .build() .map_err(app_error_from!())?; let grpc_config = config.clone(); let http_config = config; Server::new() .init(move |mut app_config, _config| async move { // tina::tracing_subscriber::fmt() // .with_thread_names(false) // .with_file(true) // .with_level(true) // .with_line_number(true) // .with_thread_ids(false) // .with_max_level(tina::tracing_core::LevelFilter::DEBUG) // .init(); LogConfig::default().set_root_level(tina::log::LevelFilter::Debug).with_enable_span(false).init().await?; app_config.port = None; Ok(app_config) }) .after_start(move |application| { async move { // let res = hello_world2::start_client3(application, addr).await.map_err(|err| app_system_error!("{err:?}"))?; // info!("response: {:?}", res); // let res = hello_world2::start_client(application).await.map_err(|err| app_system_error!("{err:?}"))?; // info!("response: {:?}", res); let session = Session::from_application(application.clone(), true)?; let mut msg = HelloRequest { id: 1, msg: "hello".to_string(), ..Default::default() }; { let request = GrpcReqData::new(msg.clone()).with_metadata("header1", "I am say hello")?; let response = GreeterClient.say_hello(application.clone(), session.clone(), request).await; info!("response: {:?}", response); } // { // let request = GrpcReqData::new(msg); // let response = GreeterClient.say_error(application.clone(), session.clone(), request).await; // info!("response: {:?}", response); // } Ok(()) } .instrument(info_span!("test hello", request_id = "abcde")) }) .run_grpc(grpc_config); Ok(()) }