更新情報
RustのWebフレームワークgothamでPostgreSQLとRedisにアクセスする(async/await対応版 gotham0.6)
概要
RustのWebフレームワークのGothamでコネクションプールされたPostgreSQLとRedisにアクセスするコードです。
200tpsくらいでました。
Cargo.toml
[package]
name = "app"
version = "0.1.0"
[dependencies]
futures = "~0.1"
hyper = "~0.11"
gotham = "~0.2"
gotham_derive = "~0.2"
mime = "~0.3"
r2d2 = "*"
r2d2_redis = "*"
redis = "*"
r2d2_postgres = "*"
postgres = "*"
main.rs
extern crate futures;
extern crate gotham;
#[macro_use]
extern crate gotham_derive;
extern crate hyper;
extern crate mime;
extern crate r2d2;
extern crate r2d2_redis;
extern crate r2d2_postgres;
extern crate redis;
extern crate postgres;
use hyper::{Response, StatusCode};
use gotham::http::response::create_response;
use gotham::state::State;
use gotham::pipeline::new_pipeline;
use gotham::pipeline::single::single_pipeline;
use gotham::router::Router;
use gotham::router::builder::*;
use gotham::handler::HandlerFuture;
use gotham::middleware::Middleware;
use gotham::state::FromState;
use std::error::Error;
use std::env;
use r2d2_redis::RedisConnectionManager;
use redis::Commands;
use r2d2_postgres::{PostgresConnectionManager, TlsMode};
#[derive(StateData)]
pub struct ConfigMiddlewareData {
pub redis_conn: r2d2::PooledConnection<RedisConnectionManager>,
pub pg_conn: r2d2::PooledConnection<PostgresConnectionManager>,
}
#[derive(Clone, NewMiddleware)]
pub struct ConfigMiddleware {
pub redis_pool: r2d2::Pool<RedisConnectionManager>,
pub pg_pool: r2d2::Pool<PostgresConnectionManager>,
}
impl Middleware for ConfigMiddleware {
fn call<Chain>(self, mut state: State, chain: Chain) -> Box<HandlerFuture>
where
Chain: FnOnce(State) -> Box<HandlerFuture>,
{
state.put(ConfigMiddlewareData{
redis_conn: self.redis_pool.get().unwrap(),
pg_conn: self.pg_pool.get().unwrap()
});
chain(state)
}
}
impl std::panic::RefUnwindSafe for ConfigMiddleware {}
pub fn handler(state: State) -> (State, Response) {
let content = {
let data = ConfigMiddlewareData::borrow_from(&state);
let redis_res: String =
data.redis_conn.get("予定表〜①ハンカクだ").unwrap();
let pg_res: String =
data.pg_conn.query(
"SELECT $1::TEXT",
&[
&"予定表〜①ハンカクだ3".to_string(),
],
).unwrap().get(0).get(0);
format!("{}:{}", redis_res, pg_res)
};
let res = create_response(
&state,
StatusCode::Ok,
Some((content.into_bytes(), mime::TEXT_PLAIN_UTF_8)),
);
(state, res)
}
fn router(redis_uri: &str, pg_uri: &str) -> Result<Router, Box<Error>> {
let redis_pool = r2d2::Pool::builder()
.build(RedisConnectionManager::new(redis_uri)?)?;
let pg_pool = r2d2::Pool::builder()
.build(PostgresConnectionManager::new(pg_uri, TlsMode::None)?)?;
let config_milldeware = ConfigMiddleware {
redis_pool: redis_pool,
pg_pool: pg_pool,
};
let (chain, pipelines) = single_pipeline(
new_pipeline()
.add(config_milldeware)
.build()
);
Ok(build_router(chain, pipelines, |route| {
// 全てのリクエストをhandlerで実行
route.get("/").to(handler);
route.get("*").to(handler);
}))
}
// cargo run -- redis://localhost:6379/0 postgres://user:pass@localhost:5432/test
pub fn main() {
let args: Vec<String> = env::args().collect();
let addr = "127.0.0.1:7878";
println!("Listening for requests at http://{}", addr);
gotham::start(addr, router(&args[1], &args[2]).unwrap())
}