将 redis-rs 与 actix-web 一起使用
Using redis-rs with actix-web
我正在尝试将 redis 作为 web::Data
上下文添加到我的 actix-web rust 应用程序中:
extern crate redis;
// std imports
use std::net::SocketAddr;
// external imports
use actix_web::{App, HttpServer};
use redis::Client
#[actix_rt::main]
async fn main() -> std::io::Result<()> {
// connect to redis
let redis_con = Client::open("redis://127.0.0.1:6379")
.unwrap()
.get_connection()
.unwrap();
HttpServer::new(move || App::new().data(redis_con).service(api::get_healthz))
.bind(SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 8080)?
.run()
.await
}
我收到以下错误:
the trait bound 'redis::Connection: std::clone::Clone' is not satisfied in '[closure@src/main.rs:48:21: 48:81 redis_con:redis::Connection]'
我已经尝试将其包装为 Arc<redis::Connection>
,这对于 redis::Connection
的子模块深处的某些类型也不起作用,这些子模块没有实现 Sync
。
在这种情况下是否有我没有看到的 Rust 概念?
这是我第一个真正的 Rust 项目,所以可能有些东西我粗略地忽略了。
这个答案是 Actix 解决您问题的最简单的例子。虽然可能有更短的方法来实现您想要的。
首先你需要导入 actix
包:
[package]
name = "test-actix-redis"
version = "0.1.0"
authors = ["Njuguna Mureithi <email@gmail.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
actix-web = "2.0"
actix-rt = "1.0"
redis = "0.15"
actix = "0.10.0-alpha.3"
然后定义你的演员:
use actix_web::{web, App, HttpResponse, HttpServer, Responder};
use redis::{Client, aio::MultiplexedConnection};
use actix::prelude::*;
struct RedisActor {
conn: MultiplexedConnection,
}
impl RedisActor {
pub async fn new(redis_url: &'static str) -> Self {
let client = Client::open(redis_url).unwrap();// not recommended
let (conn, call) = client.get_multiplexed_async_connection().await.unwrap();
actix_rt::spawn(call);
RedisActor { conn }
}
}
#[derive(Message, Debug)]
#[rtype(result = "Result<Option<String>, redis::RedisError>")]
struct InfoCommand;
impl Handler<InfoCommand> for RedisActor {
type Result = ResponseFuture<Result<Option<String>, redis::RedisError>>;
fn handle(&mut self, _msg: InfoCommand, _: &mut Self::Context) -> Self::Result {
let mut con = self.conn.clone();
let cmd = redis::cmd("INFO");
let fut = async move {
cmd
.query_async(&mut con)
.await
};
Box::pin(fut)
}
}
impl Actor for RedisActor {
type Context = Context<Self>;
}
async fn info(redis: web::Data<Addr<RedisActor>>) -> impl Responder {
let res = redis.send(InfoCommand).await.unwrap().unwrap().unwrap();
HttpResponse::Ok().body(res)
}
#[actix_rt::main]
async fn main() -> std::io::Result<()> {
let actor = RedisActor::new("redis://127.0.0.1:6379").await;
let addr = actor.start();
HttpServer::new(move || {
App::new()
.data(addr.clone())
.route("/", web::get().to(info))
})
.bind("127.0.0.1:8088")?
.run()
.await
}
现在运行你的项目:
cargo run
去 http://localhost:8088/
应该给你你的 redis 信息作为一个字符串。
我正在尝试将 redis 作为 web::Data
上下文添加到我的 actix-web rust 应用程序中:
extern crate redis;
// std imports
use std::net::SocketAddr;
// external imports
use actix_web::{App, HttpServer};
use redis::Client
#[actix_rt::main]
async fn main() -> std::io::Result<()> {
// connect to redis
let redis_con = Client::open("redis://127.0.0.1:6379")
.unwrap()
.get_connection()
.unwrap();
HttpServer::new(move || App::new().data(redis_con).service(api::get_healthz))
.bind(SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 8080)?
.run()
.await
}
我收到以下错误:
the trait bound 'redis::Connection: std::clone::Clone' is not satisfied in '[closure@src/main.rs:48:21: 48:81 redis_con:redis::Connection]'
我已经尝试将其包装为 Arc<redis::Connection>
,这对于 redis::Connection
的子模块深处的某些类型也不起作用,这些子模块没有实现 Sync
。
在这种情况下是否有我没有看到的 Rust 概念? 这是我第一个真正的 Rust 项目,所以可能有些东西我粗略地忽略了。
这个答案是 Actix 解决您问题的最简单的例子。虽然可能有更短的方法来实现您想要的。
首先你需要导入 actix
包:
[package]
name = "test-actix-redis"
version = "0.1.0"
authors = ["Njuguna Mureithi <email@gmail.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
actix-web = "2.0"
actix-rt = "1.0"
redis = "0.15"
actix = "0.10.0-alpha.3"
然后定义你的演员:
use actix_web::{web, App, HttpResponse, HttpServer, Responder};
use redis::{Client, aio::MultiplexedConnection};
use actix::prelude::*;
struct RedisActor {
conn: MultiplexedConnection,
}
impl RedisActor {
pub async fn new(redis_url: &'static str) -> Self {
let client = Client::open(redis_url).unwrap();// not recommended
let (conn, call) = client.get_multiplexed_async_connection().await.unwrap();
actix_rt::spawn(call);
RedisActor { conn }
}
}
#[derive(Message, Debug)]
#[rtype(result = "Result<Option<String>, redis::RedisError>")]
struct InfoCommand;
impl Handler<InfoCommand> for RedisActor {
type Result = ResponseFuture<Result<Option<String>, redis::RedisError>>;
fn handle(&mut self, _msg: InfoCommand, _: &mut Self::Context) -> Self::Result {
let mut con = self.conn.clone();
let cmd = redis::cmd("INFO");
let fut = async move {
cmd
.query_async(&mut con)
.await
};
Box::pin(fut)
}
}
impl Actor for RedisActor {
type Context = Context<Self>;
}
async fn info(redis: web::Data<Addr<RedisActor>>) -> impl Responder {
let res = redis.send(InfoCommand).await.unwrap().unwrap().unwrap();
HttpResponse::Ok().body(res)
}
#[actix_rt::main]
async fn main() -> std::io::Result<()> {
let actor = RedisActor::new("redis://127.0.0.1:6379").await;
let addr = actor.start();
HttpServer::new(move || {
App::new()
.data(addr.clone())
.route("/", web::get().to(info))
})
.bind("127.0.0.1:8088")?
.run()
.await
}
现在运行你的项目:
cargo run
去 http://localhost:8088/
应该给你你的 redis 信息作为一个字符串。