I am trying to see if this is the right tool for my use case and playing with some hello worlds.
I currently have two proto definitions:
helloworld.proto, implementing the serviceGreeter(with associated messages, the same as in the hellowworld example)wonderfulworld.proto, implementing the serviceWonderful(with associated messages, very similar, but does not take any argument in the request and returns something else).
I followed the Hello World example of Tonic, and created my service with
Server::builder()
.add_service(GreeterServer::new(greeter))
.add_service(WonderfulServer::new(wonderful))
.serve(addr)
.await?;
Now the thing is that I would like to have a common variable, let's say world_name, for both services Greeter and Wonderful to use and modify.
Could I do this, and what would be the recommended way to proceed?
I have tried:
Implementing both
WonderfulandGreeteron the sameMyGreeterstruct, but then I can't chain theadd_serviceas I did here, since thenew()constructor uses value and not borrow, and I don't know how else to do.Creating a
MyServerstruct with aworld_namevariable, and look on the API/online if I could somehow use this struct as the server to add services, but I didn't find anything at all.Using some form of global singleton... I guess it works but meh... not a big fan if it's possible to do otherwise
Following is my full server.rs file in case it's useful.
use tonic::{transport::Server, Request, Response, Status};
use hello_wonderful_world::greeter_server::{Greeter, GreeterServer};
use hello_wonderful_world::{HelloReply, HelloRequest};
use hello_wonderful_world::wonderful_server::{Wonderful, WonderfulServer};
use hello_wonderful_world::{WonderfulRequest, WonderfulReply};
pub mod hello_wonderful_world {
tonic::include_proto!("helloworld");
tonic::include_proto!("wonderfulworld");
}
#[derive(Debug, Default)]
pub struct MyGreeter {}
#[derive(Debug, Default)]
pub struct MyWonderfulWorld{}
#[tonic::async_trait]
impl Greeter for MyGreeter {
async fn say_hello(
&self,
request: Request<HelloRequest>, // Accept request of type HelloRequest
) -> Result<Response<HelloReply>, Status> { // Return an instance of type HelloReply
println!("Got a request: {:?}", request);
let reply = hello_wonderful_world::HelloReply {
message: format!("Hello {}!", request.into_inner().name).into(), // We must use .into_inner() as the fields of gRPC requests and responses are private
};
Ok(Response::new(reply)) // Send back our formatted greeting
}
}
#[tonic::async_trait]
impl Wonderful for MyWonderfulWorld {
async fn its_a_wonderful_world(
&self,
request: Request<WonderfulRequest>)
-> Result<Response<WonderfulReply>, Status> {
let reply = hello_wonderful_world::WonderfulReply {
message: format!("And I said to {}: What a Wonderful World", request.into_inner().name),
};
Ok(Response::new(reply))
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let addr = "[::1]:50051".parse()?;
let greeter = MyGreeter::default();
let my_wonderful = MyWonderfulWorld::default();
Server::builder()
.add_service(GreeterServer::new(greeter))
.add_service(WonderfulServer::new(my_wonderful))
.serve(addr)
.await?;
Ok(())
}
You can try something like this
I used
std::sync::Mutexbut you maybe can usestd::sync::RwLock.