生鏽的演員框架
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團隊承諾要干預以維護該行為守則。