-
Notifications
You must be signed in to change notification settings - Fork 272
initial attempt to support rama in shuttle #1943
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 4 commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
0261a57
initial attempt to support rama in shuttle
GlenDC 3db0354
fix bot review
GlenDC bbf9ce5
bump rama to 0.2.0-alpha.5
GlenDC 2347c5f
Merge branch 'main' into feat/shuttle-rama
oddgrd af673a3
update deps
GlenDC 719e6ac
fix examples and adapt versions
GlenDC b2c3a57
Merge branch 'main' into feat/shuttle-rama
GlenDC 5b4e2e8
sync rama to 0.2 and update README
GlenDC 46ba8da
fix edition and version of shuttle-rama
GlenDC f25c835
improve rama code + sync lib code with rama 0.2
GlenDC a63c444
fix: cargo fmt
oddgrd bf6fd46
adapt rama http example + only expect h1 traffic
GlenDC File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
[package] | ||
name = "shuttle-rama" | ||
version = "0.49.0" | ||
edition = "2021" | ||
license = "Apache-2.0" | ||
description = "Service implementation to run a rama server on shuttle" | ||
repository = "https://github.com/shuttle-hq/shuttle" | ||
keywords = ["shuttle-service", "rama"] | ||
|
||
[dependencies] | ||
rama = { version = "0.2.0-alpha.5", features = ["tcp", "http-full"] } | ||
GlenDC marked this conversation as resolved.
Show resolved
Hide resolved
|
||
shuttle-runtime = { path = "../../runtime", version = "0.49.0", default-features = false } | ||
|
||
[features] | ||
default = [] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
## Shuttle service integration for the Rama framework | ||
|
||
Rama is still in early development and for now the latest | ||
alpha release is used, `0.2.0-alpha.5`. | ||
|
||
### Examples | ||
|
||
#### Application Service | ||
|
||
```rust,ignore | ||
use rama::{http, Service, service::service_fn}; | ||
|
||
async fn hello_world() -> &'static str { | ||
"Hello, world!" | ||
} | ||
|
||
#[shuttle_runtime::main] | ||
async fn main() -> Result<impl shuttle_rama::ShuttleService, shuttle_rama::ShuttleError> { | ||
Ok(shuttle_rama::RamaService::application( | ||
service_fn(hello_world), | ||
)) | ||
} | ||
``` | ||
|
||
#### Transport Service | ||
|
||
```rust,ignore | ||
use rama::{net, Service, service::service_fn}; | ||
use std::convert::Infallible; | ||
use tokio::io::AsyncWriteExt; | ||
|
||
async fn hello_world(mut stream: impl net::stream::Socket + net::Stream + Unpin) -> Result<(), Infallible> { | ||
println!( | ||
"Incoming connection from: {}", | ||
stream | ||
.peer_addr() | ||
.map(|a| a.to_string()) | ||
.unwrap_or_else(|_| "???".to_owned()) | ||
); | ||
GlenDC marked this conversation as resolved.
Show resolved
Hide resolved
GlenDC marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
const TEXT: &str = "Hello, Shuttle!"; | ||
|
||
let resp = [ | ||
"HTTP/1.1 200 OK", | ||
"Content-Type: text/plain", | ||
format!("Content-Length: {}", TEXT.len()).as_str(), | ||
"", | ||
TEXT, | ||
"", | ||
] | ||
.join("\r\n"); | ||
GlenDC marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
stream | ||
.write_all(resp.as_bytes()) | ||
.await | ||
.expect("write to stream"); | ||
|
||
jonaro00 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Ok::<_, std::convert::Infallible>(()) | ||
} | ||
|
||
#[shuttle_runtime::main] | ||
async fn main() -> Result<impl shuttle_rama::ShuttleService, shuttle_rama::ShuttleError> { | ||
Ok(shuttle_rama::RamaService::transport( | ||
service_fn(hello_world), | ||
)) | ||
} | ||
``` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
#![doc = include_str!("../README.md")] | ||
|
||
use shuttle_runtime::{tokio, CustomError, Error}; | ||
use std::{convert::Infallible, fmt, net::SocketAddr}; | ||
|
||
/// A wrapper type for [rama::Service] so we can implement [shuttle_runtime::Service] for it. | ||
pub struct RamaService<T, State> { | ||
svc: T, | ||
state: State, | ||
} | ||
|
||
impl<T: Clone, State: Clone> Clone for RamaService<T, State> { | ||
fn clone(&self) -> Self { | ||
Self { | ||
svc: self.svc.clone(), | ||
state: self.state.clone(), | ||
} | ||
} | ||
} | ||
|
||
impl<T: fmt::Debug, State: fmt::Debug> fmt::Debug for RamaService<T, State> { | ||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
f.debug_struct("RamaService") | ||
.field("svc", &self.svc) | ||
.field("state", &self.state) | ||
.finish() | ||
} | ||
} | ||
|
||
/// Private type wrapper to indicate [`RamaService`] | ||
/// is used by the user from the Transport layer (tcp). | ||
pub struct Transport<S>(S); | ||
|
||
/// Private type wrapper to indicate [`RamaService`] | ||
/// is used by the user from the Application layer (http(s)). | ||
pub struct Application<S>(S); | ||
|
||
macro_rules! impl_wrapper_derive_traits { | ||
($name:ident) => { | ||
impl<S: Clone> Clone for $name<S> { | ||
fn clone(&self) -> Self { | ||
Self(self.0.clone()) | ||
} | ||
} | ||
|
||
impl<S: fmt::Debug> fmt::Debug for $name<S> { | ||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
f.debug_tuple(stringify!($name)).field(&self.0).finish() | ||
} | ||
} | ||
}; | ||
} | ||
|
||
impl_wrapper_derive_traits!(Transport); | ||
impl_wrapper_derive_traits!(Application); | ||
|
||
impl<S> RamaService<Transport<S>, ()> { | ||
pub fn transport(svc: S) -> Self { | ||
Self { | ||
svc: Transport(svc), | ||
state: (), | ||
} | ||
} | ||
} | ||
|
||
impl<S> RamaService<Application<S>, ()> { | ||
pub fn application(svc: S) -> Self { | ||
Self { | ||
svc: Application(svc), | ||
state: (), | ||
} | ||
} | ||
} | ||
|
||
impl<T> RamaService<T, ()> { | ||
/// Attach state to this [`RamaService`], such that it will be passed | ||
/// as part of each request's [`rama::Context`]. | ||
pub fn with_state<State>(self, state: State) -> RamaService<T, State> | ||
where | ||
State: Clone + Send + Sync + 'static, | ||
{ | ||
RamaService { | ||
svc: self.svc, | ||
state, | ||
} | ||
} | ||
} | ||
|
||
#[shuttle_runtime::async_trait] | ||
impl<S, State> shuttle_runtime::Service for RamaService<Transport<S>, State> | ||
where | ||
S: rama::Service<State, tokio::net::TcpStream>, | ||
State: Clone + Send + Sync + 'static, | ||
{ | ||
/// Takes the service that is returned by the user in their [shuttle_runtime::main] function | ||
/// and binds to an address passed in by shuttle. | ||
async fn bind(self, addr: SocketAddr) -> Result<(), Error> { | ||
rama::tcp::server::TcpListener::build_with_state(self.state) | ||
.bind(addr) | ||
.await | ||
.map_err(|err| Error::BindPanic(err.to_string()))? | ||
.serve(self.svc.0) | ||
.await; | ||
GlenDC marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Ok(()) | ||
} | ||
} | ||
|
||
#[shuttle_runtime::async_trait] | ||
impl<S, State, Response> shuttle_runtime::Service for RamaService<Application<S>, State> | ||
where | ||
S: rama::Service<State, rama::http::Request, Response = Response, Error = Infallible>, | ||
GlenDC marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Response: rama::http::IntoResponse + Send + 'static, | ||
State: Clone + Send + Sync + 'static, | ||
{ | ||
/// Takes the service that is returned by the user in their [shuttle_runtime::main] function | ||
/// and binds to an address passed in by shuttle. | ||
async fn bind(self, addr: SocketAddr) -> Result<(), Error> { | ||
rama::http::server::HttpServer::auto(rama::rt::Executor::new()) | ||
.listen_with_state(self.state, addr, self.svc.0) | ||
.await | ||
.map_err(|err| CustomError::new(rama::error::OpaqueError::from_boxed(err)))?; | ||
Ok(()) | ||
} | ||
} | ||
|
||
#[doc = include_str!("../README.md")] | ||
pub type ShuttleRamaTransport<S, State = ()> = Result<RamaService<Transport<S>, State>, Error>; | ||
|
||
#[doc = include_str!("../README.md")] | ||
pub type ShuttleRamaApplication<S, State = ()> = Result<RamaService<Application<S>, State>, Error>; | ||
GlenDC marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
pub use shuttle_runtime::{Error as ShuttleError, Service as ShuttleService}; |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.