Expose `into_service` functions that provide Sync and/or Clone Services
- Dominant language
- Rust
- Stars
- 12.5k
- Forks
- 1.3k
- Avg merge
- 4d 7h
- Merged PRs (30d)
- 24
Description
## Feature Request
### Motivation
I have the following code:
```
use anyhow::{Context as AnyhowContext, Result};
use aptos_api::context::Context;
use aptos_protos::api::v2::{
api_v2_server::{ApiV2, ApiV2Server},
GetAccountModuleRequest, GetAccountModuleResponse,
};
use poem::{endpoint::TowerCompatExt, IntoEndpoint, Route};
use std::sync::Arc;
use tonic::{transport::Server, Request, Response, Status};
use sync_wrapper::SyncWrapper;
#[derive(Clone)]
pub struct ApiV2Service {
pub context: Arc,
}
pub fn build_api_v2_service(context: Arc) -> Result {
let service = ApiV2Service { context };
let tower_service = Server::builder()
.add_service(ApiV2Server::new(service))
.into_service();
let tower_service = SyncWrapper::new(tower_service).compat();
// https://github.com/poem-web/poem/issues/536
let routes = Route::new().nest("/", tower_service);
Ok(routes)
}
#[tonic::async_trait]
impl ApiV2 for ApiV2Service {
async fn get_account_module(
&self,
request: Request,
) -> Result, Status> {
unimplemented!();
}
}
```
In this code you see that I have a Tonic service which I convert into a Tower service. I then run it through this compat function from Poem so I can use it with Poem. The problem is that compat function (https://docs.rs/poem/latest/poem/endpoint/trait.TowerCompatExt.html) requires that the service be Sync, but tonic services are not Sync. Diving deeper, it is not as simple as making the Service Sync in tonic, that doesn't work. However when I look at Tower, I see that they have this BoxService which _is_ Sync (https://github.com/tower-rs/tower/pull/702). But with that I'm also having a variety of problems, because that isn't Clone (another requirement).
In any case, getting a Service that is either Clone or Sync is possible using these various utilities from Tower. IT seems like getting one that is both Clone and Sync is also possible, but TBA on that: https://github.com/tower-rs/tower/issues/691. See also https://github.com/tower-rs/tower/issues/663.
### Proposal
So the request here is for Tonic to provide functions that give you these different Services out of the box. Figuring all this out took quite a while, it'd be nice if future Tonic users didn't have to worry about this and could just use functions like this:
- `into_service`: Already exists.
- `into_service_sync`: Like `into_service` but the service is Sync.
- `into_service_clone`: Like `into_service` but the service is Clone.
- `into_service_sync_clone`: Like `into_service` but the service is Sync + Clone.
Under the hood Tonic would utilize all these Tower utilities for us.
### Alternatives
Users can do it all on their own after getting the service from `into_service`, but it is quite complicated. It'd be nice if this was just possible out of the box.
Contributor guide
Assessment
This issue has not been assessed yet.