Skip to content

Commit

Permalink
Add tower example
Browse files Browse the repository at this point in the history
  • Loading branch information
AndreyErmilov committed Apr 10, 2022
1 parent 7f6d37c commit c990d07
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 0 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ members = [
"hitbox-backend",
"hitbox-derive",
"hitbox-redis",
"hitbox-tower",
"examples",
]
6 changes: 6 additions & 0 deletions examples/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,9 @@ actix_derive = "0.6"
actix-web = "3"
tracing = "0.1"
tracing-subscriber = "0.2"

hyper = { version = "0.14", features = ["full"] }
tokio = { version = "1", features = ["full"] }
tower = { version = "0.4", features = ["full"] }
tower-http = { version = "0.2", features = ["full"] }
http = "0.2"
23 changes: 23 additions & 0 deletions examples/examples/tower.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use std::{convert::Infallible, net::SocketAddr};
use hyper::{Body, Server};

use tower::make::Shared;
use http::{Request, Response};

async fn handle(_: Request<Body>) -> Result<Response<Body>, Infallible> {
Ok(Response::new("Hello, World!".into()))
}

#[tokio::main]
async fn main() {
let service = tower::ServiceBuilder::new()
.layer(tower_http::trace::TraceLayer::new_for_http())
.service_fn(handle);

let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
Server::bind(&addr)
.serve(Shared::new(service))
.await
.expect("server error");
}

9 changes: 9 additions & 0 deletions hitbox-tower/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[package]
edition = "2021"
name = "hitbox-tower"
version = "0.1.0"

[dependencies]
tower = "0.4"


8 changes: 8 additions & 0 deletions hitbox-tower/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
let result = 2 + 2;
assert_eq!(result, 4);
}
}
77 changes: 77 additions & 0 deletions hitbox-tower/src/runtime.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
use std::{future::Future, marker::PhantomData};

use async_trait::async_trait;

use hitbox::{
runtime::{AdapterResult, RuntimeAdapter},
CacheError, CacheState, CacheableResponse, Cacheable,
};
use hitbox_backend::CacheBackend;
use serde::de::DeserializeOwned;

pub struct TowerAdapter<'b, Request, Response, Service, B>
where
Request: Cacheable,
{
_response: PhantomData<Response>,
backend: &'b B,
upstream: Service,
request: Option<Request>,
cache_key: String,
cache_ttl: u32,
cache_stale_ttl: u32,
}

impl<'b, Request, Response, Service, B> FutureAdapter<'b, Request, Response, Service, B>
where
Request: Cacheable,
{
pub fn new(upstream: U, request: Request, backend: &'b B) -> Result<Self, CacheError> {
Ok(Self {
cache_key: request.cache_key()?,
cache_ttl: request.cache_ttl(),
cache_stale_ttl: request.cache_stale_ttl(),
request: Some(request),
upstream,
backend,
_response: PhantomData::default(),
})
}
}

#[async_trait]
impl<Request, Response, Service, B, 'b> crate::runtime::RuntimeAdapter for FutureAdapter<'b, Request, Response, U, B>
where
Request: Cacheable + Send + Sync,
{
type UpstreamResult = Response;
async fn update_cache<'a>(
&self,
cached_value: &'a hitbox_backend::CachedValue<Self::UpstreamResult>,
) -> crate::runtime::AdapterResult<()> {
Ok(self
.backend
.set(self.cache_key.clone(), cached_value, Some(self.cache_ttl))
.await?)
}

async fn poll_cache(&self) -> crate::runtime::AdapterResult<CacheState<Self::UpstreamResult>> {
Ok(self.backend.get(self.cache_key.clone()).await?.into())
}

async fn poll_upstream(&mut self) -> crate::runtime::AdapterResult<Self::UpstreamResult> {
let request = self.request.take();
let request = request.ok_or_else(|| {
CacheError::CacheKeyGenerationError("Request already sent to upstream".to_owned())
})?;
Ok(self.upstream.call(request).await)
}

fn eviction_settings(&self) -> hitbox_backend::EvictionPolicy {
let ttl_settings = hitbox_backend::TtlSettings {
ttl: self.cache_ttl,
stale_ttl: self.cache_stale_ttl,
};
hitbox_backend::EvictionPolicy::Ttl(ttl_settings)
}
}

0 comments on commit c990d07

Please sign in to comment.