2012-12-19 14 views
22

Sto lavorando a un'applicazione Web scritta in Scala, utilizzando il Play! quadro e Akka. Il codice è organizzato fondamentalmente in questo modo: i controller Play inviano messaggi agli attori Akka. Gli attori, a loro volta, parlano con un livello di persistenza, che astrae l'accesso al database. Un tipico esempio di utilizzo di questi componenti dell'applicazione:Uso di attori Akka in un'applicazione Web CRUD

class OrderController(orderActor: ActorRef) extends Controller { 
    def showOrders(customerId: Long) = { 
    implicit request => Async { 
     val futureOrders = orderActor ? FindOrdersByCustomerId(id) 

     // Handle the result, showing the orders list to the user or showing an error message. 
    } 
    } 
} 

object OrderActor extends Actor { 
    def receive = { 
    case FindOrdersByCustomerId(id) => 
     sender ! OrderRepository.findByCustomerId(id) 
    case InsertOrder(order) => 
     sender ! OrderRepository.insert(order) 
     //Trigger some notification, like sending an email. Maybe calling another actor. 
    } 
} 

object OrderRepository { 
    def findByCustomerId(id: Long): Try[List[Order]] = ??? 
    def insert(order: Order): Try[Long] = ??? 
} 

Come potete vedere, questo è il modello di base CRUD, molto simile a quello che si vede in altre lingue e quadri. Una query viene passata ai livelli sottostanti e, quando l'applicazione ottiene un risultato dal database, tale risultato viene ripristinato fino a raggiungere l'interfaccia utente. L'unica differenza rilevante è l'uso di attori e chiamate asincrone.

Ora, sono molto nuovo al concetto di attori, quindi non riesco ancora a capirlo. Ma, da quello che ho letto, questo non è il modo in cui gli attori dovrebbero essere usati. Si osservi, tuttavia, che in alcuni casi (ad esempio l'invio di un messaggio di posta elettronica quando viene inserito un ordine) è necessario il vero passaggio di messaggi asincroni.

Quindi, la mia domanda è: è una buona idea usare gli attori in questo modo? Quali sono le alternative per scrivere applicazioni CRUD in Scala, sfruttando Futures e le altre funzionalità di concorrenza di Akka?

+1

Dai un'occhiata ai canali digitati: sono usciti dopo che l'hai pubblicato. Hanno alcune caratteristiche interessanti per il flusso dei messaggi, quindi puoi fare cose come passare un messaggio attraverso diversi attori: OrderRepository.insert (order) -! -> sender -? -> sendEmail -? -> displayResult. –

risposta

5

Sebbene la concorrenza basata sugli attori non si adatti alle operazioni transazionali pronte all'uso, ma ciò non impedisce di utilizzare gli attori in questo modo se si gioca bene con il livello di persistenza. Se puoi garantire che l'inserisci (scrivi) sia atomico, puoi tranquillamente avere un gruppo di attori che lo fanno per te. Normalmente i database hanno una lettura thread-safe, quindi trova dovrebbe funzionare come previsto. A parte il fatto che se lo inserisce non è protetto da thread, è possibile avere un solo WriteActor dedicato semplicemente per le operazioni di scrittura e l'elaborazione sequenziale dei messaggi garantirà l'atomicità per l'utente.

2

Una cosa di cui essere a conoscenza è che un attore elabora un messaggio alla volta, il che sarebbe piuttosto limitante in questo caso. È possibile utilizzare un pool di attori utilizzando routers.

L'esempio definisce un blocco del repository, che potrebbe essere l'unica cosa che si può fare, a seconda del driver del database. Se possibile, dovresti andare anche lì per una async asincrona, cioè i future di ritorno. Nell'attore dovresti invece pipe il risultato del futuro per il mittente.

+0

Sì, il controller dipende da un 'ActorRef', che potrebbe essere un semplice attore e un router. –

Problemi correlati