生锈的演员框架
Any类型)要使用actix ,请将其添加到您的Cargo.toml :
[ dependencies ]
actix = " 0.13 "为了使用Actix,您首先需要创建System 。
fn main ( ) {
let system = actix :: System :: new ( ) ;
system . run ( ) ;
} Actix使用Tokio运行时。 System::new()创建一个新的事件循环。 System.run()启动Tokio事件循环,一旦System演员收到SystemExit消息,将完成。
为了定义参与者,您需要定义结构并实现Actor特征。
use actix :: { Actor , Context , System } ;
struct MyActor ;
impl Actor for MyActor {
type Context = Context < Self > ;
fn started ( & mut self , _ctx : & mut Self :: Context ) {
println ! ( "I am alive!" ) ;
System :: current ( ) . stop ( ) ; // <- stop system
}
}
fn main ( ) {
let system = System :: new ( ) ;
let _addr = system . block_on ( async { MyActor . start ( ) } ) ;
system . run ( ) . unwrap ( ) ;
}产卵是通过start并create演员特征的方法来实现新演员的。它提供了几种创建演员的方式。有关详细信息,请检查文档。您可以实施started , stopping和stopped演员特征的方法。当演员开始时,演员开始并stopping时, started打电话。检查API文档以获取有关演员生命周期的更多信息。
演员通过发送消息与另一个演员进行交流。在actix中,所有消息均已键入。让我们定义一个使用两个usize参数的简单Sum消息和一个Actor,该消息将接受此消息并返回这两个数字的总和。在这里,我们将#[actix::main]属性用作启动System并驱动主要功能的一种更简单的方法,以便我们可以轻松地.await ,以获取从Actor那里发送的响应。
use actix :: prelude :: * ;
// this is our Message
// we have to define the response type (rtype)
# [ derive ( Message ) ]
# [ rtype ( usize ) ]
struct Sum ( usize , usize ) ;
// Actor definition
struct Calculator ;
impl Actor for Calculator {
type Context = Context < Self > ;
}
// now we need to implement `Handler` on `Calculator` for the `Sum` message.
impl Handler < Sum > for Calculator {
type Result = usize ; // <- Message response type
fn handle ( & mut self , msg : Sum , _ctx : & mut Context < Self > ) -> Self :: Result {
msg . 0 + msg . 1
}
}
# [ actix :: main ] // <- starts the system and block until future resolves
async fn main ( ) {
let addr = Calculator . start ( ) ;
let res = addr . send ( Sum ( 10 , 5 ) ) . await ; // <- send message and get future for result
match res {
Ok ( result ) => println ! ( "SUM: {}" , result ) ,
_ => println ! ( "Communication to the actor has failed" ) ,
}
}与演员的所有通信都通过Addr对象。您可以do_send消息,而无需等待响应,也可以向演员send特定消息。 Message特征定义了消息的结果类型。
您可能已经注意到, Actor和Handler特质的方法接受&mut self ,因此,欢迎您将任何东西存储在演员中并在必要时进行变异。
地址对象需要Actor类型,但是如果我们只想向可以处理该消息的演员发送特定消息,我们可以使用Recipient接口。让我们创建一个使用Recipient的新演员。
use actix :: prelude :: * ;
use std :: time :: Duration ;
# [ derive ( Message ) ]
# [ rtype ( result = "()" ) ]
struct Ping {
pub id : usize ,
}
// Actor definition
struct Game {
counter : usize ,
name : String ,
recipient : Recipient < Ping > ,
}
impl Actor for Game {
type Context = Context < Game > ;
}
// simple message handler for Ping message
impl Handler < Ping > for Game {
type Result = ( ) ;
fn handle ( & mut self , msg : Ping , ctx : & mut Context < Self > ) {
self . counter += 1 ;
if self . counter > 10 {
System :: current ( ) . stop ( ) ;
} else {
println ! ( "[{0}] Ping received {1}" , self . name , msg . id ) ;
// wait 100 nanoseconds
ctx . run_later ( Duration :: new ( 0 , 100 ) , move |act , _| {
act . recipient . do_send ( Ping { id : msg . id + 1 } ) ;
} ) ;
}
}
}
fn main ( ) {
let system = System :: new ( ) ;
system . block_on ( async {
// To create a cyclic game link, we need to use a different constructor
// method to get access to its recipient before it starts.
let _game = Game :: create ( |ctx| {
// now we can get an address of the first actor and create the second actor
let addr = ctx . address ( ) ;
let addr2 = Game {
counter : 0 ,
name : String :: from ( "Game 2" ) ,
recipient : addr . recipient ( ) ,
}
. start ( ) ;
// let's start pings
addr2 . do_send ( Ping { id : 10 } ) ;
// now we can finally create first actor
Game {
counter : 0 ,
name : String :: from ( "Game 1" ) ,
recipient : addr2 . recipient ( ) ,
}
} ) ;
} ) ;
// let the actors all run until they've shut themselves down
system . run ( ) . unwrap ( ) ;
}请参阅此聊天示例,该示例在网络客户/服务器服务中显示了更全面的用法。
欢迎所有贡献,如果您有一个功能请求,请随时打开问题!
该项目均在任何一个下获得许可
可以选择。
对Actix Repo的贡献是根据贡献者盟约的条款组织的。 Actix团队承诺要干预以维护该行为守则。