Estrutura de ator para ferrugem
Any tipo) Para usar actix , adicione isso à sua Cargo.toml :
[ dependencies ]
actix = " 0.13 " Para usar o Actix, você primeiro precisa criar um System .
fn main ( ) {
let system = actix :: System :: new ( ) ;
system . run ( ) ;
} Actix usa o tempo de execução do Tokio. System::new() cria um novo loop de evento. System.run() inicia o loop de eventos Tokio e terminará assim que o ator System receber a mensagem SystemExit .
Para definir um ator, você precisa definir uma estrutura e implementar o traço 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 ( ) ;
} A desova de um novo ator é alcançada através do start e create os métodos do traço do ator. Ele fornece várias maneiras diferentes de criar atores; Para detalhes, verifique os documentos. Você pode implementar os métodos started , stopping e stopped da característica do ator. started é chamado quando o ator começa e stopping quando o ator termina. Verifique os documentos da API para obter mais informações sobre o ciclo de vida do ator.
Um ator se comunica com outro ator enviando mensagens. No Actix, todas as mensagens são digitadas. Vamos definir uma mensagem Sum simples com dois parâmetros usize e um ator que aceitará esta mensagem e retornará a soma desses dois números. Aqui, usamos o atributo #[actix::main] como uma maneira mais fácil de iniciar nosso System e dirigir nossa função principal para Actor possamos facilmente .await
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" ) ,
}
} Todas as comunicações com os atores passam por um objeto Addr . Você pode do_send uma mensagem sem esperar uma resposta ou send uma mensagem específica a um ator. O traço Message define o tipo de resultado para uma mensagem.
Você deve ter notado que os métodos das características do Actor e Handler aceitam &mut self , para poder armazenar qualquer coisa em um ator e mudar sempre que necessário.
Os objetos de endereço exigem um tipo de ator, mas se quisermos enviar uma mensagem específica para um ator que pode lidar com a mensagem, podemos usar a interface Recipient . Vamos criar um novo ator que usa 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 ( ) ;
}Veja este exemplo de bate -papo que mostra um uso mais abrangente em um serviço de cliente/servidor de rede.
Todas as contribuições são bem -vindas, se você tiver uma solicitação de recurso, não hesite em abrir um problema!
Este projeto está licenciado sob qualquer um dos
por sua opção.
A contribuição para o Repo Actix é organizada nos termos da aliança colaboradora. A equipe do Actix promete intervir para defender esse código de conduta.