我如何存储闭包并将它们与 Actix actors 一起使用?
How could I store closures and use them with Actix actors?
我正在尝试使用 Actix 通过 WebSockets 传达捕获事件并使用类似 https://github.com/foochi/how-store-closures-with-actix 的方法处理它们。这个想法是提供一个库,可用于存储闭包(事件),并在收到 WebSockets 文本消息时 运行 它们。
use actix::*;
use actix_web::ws::{Client, Message, ProtocolError};
use futures::Future;
struct MyActor {
handler: Box<Fn(String) + 'static>,
}
impl Actor for MyActor {
type Context = Context<Self>;
}
impl StreamHandler<Message, ProtocolError> for MyActor {
fn handle(&mut self, msg: Message, _ctx: &mut Context<Self>) {
match msg {
Message::Text(text) => {
(self.handler)(text)
},
_ => panic!(),
}
}
}
pub struct Event {
handler: Box<Fn(String) + 'static>,
}
pub struct EventManager {
events: Vec<Event>,
}
impl EventManager {
pub fn new() -> Self {
Self { events: vec![] }
}
pub fn capture<F>(&mut self, function: F)
where
F: for<'h> Fn(String) + 'static
{
let event = Event { handler: Box::new(function), };
self.events.push(event);
}
pub fn run(&self) {
let runner = System::new("example");
let event = &self.events[0];
Arbiter::spawn(
Client::new("example")
.connect()
.map(|(reader, _writer)| {
MyActor::create(|ctx| {
MyActor::add_stream(reader, ctx);
MyActor { handler: event.handler }
});
})
.map_err(|err| {})
);
runner.run();
}
}
我的问题是我有这个错误:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
--> src/events.rs:48:22
|
48 | let event = &self.events[0];
| ^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 46:5...
--> src/events.rs:46:5
|
46 | / pub fn run(&self) {
47 | | let runner = System::new("example");
48 | | let event = &self.events[0];
49 | |
... |
62 | | runner.run();
63 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/events.rs:48:22
|
48 | let event = &self.events[0];
| ^^^^^^^^^^^
= note: but, the lifetime must be valid for the static lifetime...
note: ...so that the type `[closure@src/events.rs:54:37: 57:22 reader:actix_web::ws::ClientReader, event:&&events::Event]` will meet its required lifetime bounds
--> src/events.rs:54:21
|
54 | MyActor::create(|ctx| {
| ^^^^^^^^^^^^^^^
我想我部分理解了根本原因:我试图将引用(事件)传递给 StreamHandler
,但生命周期不匹配。
我该如何解决?
免责声明:对于 Actix 这是否是一个好的设计模式,我无法发表评论,因为我才刚刚开始了解该框架。
正如您已经发现的,问题与寿命要求有关。
Actor::create
方法需要闭包参数的 'static
生命周期:
fn create<F>(f: F) -> Addr<Self>
where
Self: Actor<Context = Context<Self>>,
F: FnOnce(&mut Context<Self>) -> Self + 'static,
&self.events[0]
不满足 'static
生命周期要求。
一个解决方案是将 EventManager
对象的所有权移至 MyActor
:
use actix::*;
use actix_web::ws::{Client, Message, ProtocolError};
use futures::Future;
struct MyActor {
evm: EventManager,
}
impl Actor for MyActor {
type Context = Context<Self>;
}
impl StreamHandler<Message, ProtocolError> for MyActor {
fn handle(&mut self, msg: Message, _ctx: &mut Context<Self>) {
match msg {
Message::Text(text) => {
// just for sake of demo: execute all event handlers
for idx in 0..self.evm.events.len() {
(self.evm.events[idx].handler)(text.clone())
}
}
_ => panic!(),
}
}
}
pub struct Event {
handler: Box<Fn(String) + 'static>,
}
pub struct EventManager {
events: Vec<Event>,
}
impl EventManager {
pub fn new() -> Self {
Self { events: vec![] }
}
pub fn capture<F>(&mut self, function: F)
where
F: Fn(String) + 'static,
{
let event = Event {
handler: Box::new(function),
};
self.events.push(event);
}
pub fn run(self) {
let runner = System::new("example");
Arbiter::spawn(
Client::new("http://127.0.0.1:8080/ws/")
.connect()
.map(|(reader, _writer)| {
MyActor::create(|ctx| {
MyActor::add_stream(reader, ctx);
// move event manager inside the actor
MyActor { evm: self }
});
}).map_err(|err| println!("FATAL: {}", err)),
);
runner.run();
}
}
pub fn ready() {
let mut client = EventManager::new();
client.capture(|data| println!("processing the data: {:?}", data));
client.capture(|data| println!("processing AGAIN the data: {:?}", data));
client.run();
// here run client is not more available: it was moved inside the actor
}
fn main() {
ready();
}
我正在尝试使用 Actix 通过 WebSockets 传达捕获事件并使用类似 https://github.com/foochi/how-store-closures-with-actix 的方法处理它们。这个想法是提供一个库,可用于存储闭包(事件),并在收到 WebSockets 文本消息时 运行 它们。
use actix::*;
use actix_web::ws::{Client, Message, ProtocolError};
use futures::Future;
struct MyActor {
handler: Box<Fn(String) + 'static>,
}
impl Actor for MyActor {
type Context = Context<Self>;
}
impl StreamHandler<Message, ProtocolError> for MyActor {
fn handle(&mut self, msg: Message, _ctx: &mut Context<Self>) {
match msg {
Message::Text(text) => {
(self.handler)(text)
},
_ => panic!(),
}
}
}
pub struct Event {
handler: Box<Fn(String) + 'static>,
}
pub struct EventManager {
events: Vec<Event>,
}
impl EventManager {
pub fn new() -> Self {
Self { events: vec![] }
}
pub fn capture<F>(&mut self, function: F)
where
F: for<'h> Fn(String) + 'static
{
let event = Event { handler: Box::new(function), };
self.events.push(event);
}
pub fn run(&self) {
let runner = System::new("example");
let event = &self.events[0];
Arbiter::spawn(
Client::new("example")
.connect()
.map(|(reader, _writer)| {
MyActor::create(|ctx| {
MyActor::add_stream(reader, ctx);
MyActor { handler: event.handler }
});
})
.map_err(|err| {})
);
runner.run();
}
}
我的问题是我有这个错误:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
--> src/events.rs:48:22
|
48 | let event = &self.events[0];
| ^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 46:5...
--> src/events.rs:46:5
|
46 | / pub fn run(&self) {
47 | | let runner = System::new("example");
48 | | let event = &self.events[0];
49 | |
... |
62 | | runner.run();
63 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/events.rs:48:22
|
48 | let event = &self.events[0];
| ^^^^^^^^^^^
= note: but, the lifetime must be valid for the static lifetime...
note: ...so that the type `[closure@src/events.rs:54:37: 57:22 reader:actix_web::ws::ClientReader, event:&&events::Event]` will meet its required lifetime bounds
--> src/events.rs:54:21
|
54 | MyActor::create(|ctx| {
| ^^^^^^^^^^^^^^^
我想我部分理解了根本原因:我试图将引用(事件)传递给 StreamHandler
,但生命周期不匹配。
我该如何解决?
免责声明:对于 Actix 这是否是一个好的设计模式,我无法发表评论,因为我才刚刚开始了解该框架。
正如您已经发现的,问题与寿命要求有关。
Actor::create
方法需要闭包参数的 'static
生命周期:
fn create<F>(f: F) -> Addr<Self>
where
Self: Actor<Context = Context<Self>>,
F: FnOnce(&mut Context<Self>) -> Self + 'static,
&self.events[0]
不满足 'static
生命周期要求。
一个解决方案是将 EventManager
对象的所有权移至 MyActor
:
use actix::*;
use actix_web::ws::{Client, Message, ProtocolError};
use futures::Future;
struct MyActor {
evm: EventManager,
}
impl Actor for MyActor {
type Context = Context<Self>;
}
impl StreamHandler<Message, ProtocolError> for MyActor {
fn handle(&mut self, msg: Message, _ctx: &mut Context<Self>) {
match msg {
Message::Text(text) => {
// just for sake of demo: execute all event handlers
for idx in 0..self.evm.events.len() {
(self.evm.events[idx].handler)(text.clone())
}
}
_ => panic!(),
}
}
}
pub struct Event {
handler: Box<Fn(String) + 'static>,
}
pub struct EventManager {
events: Vec<Event>,
}
impl EventManager {
pub fn new() -> Self {
Self { events: vec![] }
}
pub fn capture<F>(&mut self, function: F)
where
F: Fn(String) + 'static,
{
let event = Event {
handler: Box::new(function),
};
self.events.push(event);
}
pub fn run(self) {
let runner = System::new("example");
Arbiter::spawn(
Client::new("http://127.0.0.1:8080/ws/")
.connect()
.map(|(reader, _writer)| {
MyActor::create(|ctx| {
MyActor::add_stream(reader, ctx);
// move event manager inside the actor
MyActor { evm: self }
});
}).map_err(|err| println!("FATAL: {}", err)),
);
runner.run();
}
}
pub fn ready() {
let mut client = EventManager::new();
client.capture(|data| println!("processing the data: {:?}", data));
client.capture(|data| println!("processing AGAIN the data: {:?}", data));
client.run();
// here run client is not more available: it was moved inside the actor
}
fn main() {
ready();
}