Kerangka kerja aktor untuk karat
Any ) Untuk menggunakan actix , tambahkan ini ke Cargo.toml Anda:
[ dependencies ]
actix = " 0.13 " Untuk menggunakan Actix, Anda harus pertama -tama perlu membuat System .
fn main ( ) {
let system = actix :: System :: new ( ) ;
system . run ( ) ;
} Actix menggunakan runtime Tokio. System::new() Membuat Loop Acara Baru. System.run() Memulai Loop Acara Tokio, dan akan selesai setelah aktor System menerima pesan SystemExit .
Untuk mendefinisikan aktor, Anda perlu mendefinisikan struct dan menerapkannya sifat 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 ( ) ;
} Mempersatkan aktor baru dicapai melalui start dan create metode sifat aktor. Ini menyediakan beberapa cara berbeda untuk menciptakan aktor; Untuk detailnya, periksa dokumen. Anda dapat mengimplementasikan metode started , stopping dan stopped sifat aktor. started dipanggil ketika aktor mulai dan stopping ketika aktor selesai. Periksa dokumen API untuk informasi lebih lanjut tentang siklus hidup aktor.
Seorang aktor berkomunikasi dengan aktor lain dengan mengirim pesan. Di Actix semua pesan diketik. Mari kita tentukan pesan Sum sederhana dengan dua parameter usize dan seorang aktor yang akan menerima pesan ini dan mengembalikan jumlah dari dua angka tersebut. Di sini kami menggunakan atribut #[actix::main] sebagai cara yang lebih mudah untuk memulai System kami dan mendorong fungsi utama kami sehingga kami dapat dengan mudah .await untuk tanggapan yang dikirim kembali dari 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" ) ,
}
} Semua komunikasi dengan aktor melalui objek Addr . Anda dapat do_send pesan tanpa menunggu tanggapan, atau Anda dapat send pesan tertentu kepada aktor. Sifat Message mendefinisikan jenis hasil untuk pesan.
Anda mungkin telah memperhatikan bahwa metode Actor dan ciri -ciri Handler menerima &mut self , jadi Anda dipersilakan untuk menyimpan apa pun dalam aktor dan bermutasinya kapan pun diperlukan.
Objek alamat memerlukan jenis aktor, tetapi jika kita hanya ingin mengirim pesan tertentu ke aktor yang dapat menangani pesan, kita dapat menggunakan antarmuka Recipient . Mari kita buat aktor baru yang menggunakan 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 ( ) ;
}Lihat contoh obrolan ini yang menunjukkan penggunaan yang lebih komprehensif dalam layanan klien/server jaringan.
Semua kontribusi dipersilakan, jika Anda memiliki permintaan fitur, jangan ragu untuk membuka masalah!
Proyek ini dilisensikan di bawah keduanya
di pilihan Anda.
Kontribusi untuk Repo Actix diselenggarakan berdasarkan ketentuan Kovenan Kontributor. Tim Actix berjanji untuk campur tangan untuk menegakkan kode etik itu.