2012-12-19 17 views
22

Pracuję nad aplikacją internetową napisaną w Scali, używając gry! ramy i Akka. Kod jest zorganizowany w następujący sposób: kontrolery Play wysyłają wiadomości do aktorów Akka. Aktorzy z kolei rozmawiają z warstwą uporczywości, która ogranicza dostęp do bazy danych. Typowym przykładem wykorzystania tych składników w aplikacji:Używanie aktorów Akka w aplikacji internetowej 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] = ??? 
} 

Jak widać, jest to podstawowy wzór CRUD, podobnie jak to, co można zobaczyć w innych językach i ram. Zapytanie zostanie przekazane do poniższych warstw, a gdy aplikacja otrzyma wynik z bazy danych, wynik ten powróci, aż dotrze do interfejsu użytkownika. Jedyną istotną różnicą jest użycie aktorów i wywołań asynchronicznych.

Teraz jestem bardzo nowy w koncepcji aktorów, więc jeszcze tego nie rozumiem. Ale z tego, co przeczytałem, nie wynika, w jaki sposób należy używać aktorów. Zauważ jednak, że w niektórych przypadkach (np. Wysłanie e-maila po wstawieniu zamówienia) potrzebujemy prawdziwego przekazywania wiadomości asynchronicznych.

Moje pytanie brzmi: czy to dobry pomysł, aby korzystać z aktorów w ten sposób? Jakie są alternatywy dla pisania aplikacji CRUD w Scali, korzystając z Futures i innych możliwości współbieżności Akki?

+1

Spójrz na wpisane kanały - pojawiły się po opublikowaniu tego. Mają kilka interesujących funkcji związanych z przepływem wiadomości, więc możesz zrobić takie rzeczy, jak przekazanie wiadomości przez kilku aktorów: OrderRepository.insert (kolejność) -! -> sender -? -> sendEmail -? -> displayResult. –

Odpowiedz

5

Chociaż współbieżność oparta na aktorach nie jest zgodna z operacjami transakcyjnymi po wyjęciu z pudełka, ale to nie powstrzyma cię od używania aktorów w ten sposób, jeśli dobrze grasz z warstwą trwałości. Jeśli możesz zagwarantować, że wstawić (zapis) jest atomowy, możesz bezpiecznie zabrać ze sobą grupę aktorów. Zwykle bazy danych mają bezpieczny odczyt wątków, więc znaleźć powinien również działać zgodnie z oczekiwaniami. Poza tym, jeśli wstaw nie jest bezpieczny dla wątków, możesz mieć jeden pojedynczy WriteActor dedykowany tylko do operacji zapisu, a sekwencyjne przetwarzanie wiadomości zapewni atomowość dla ciebie.

2

Należy zdawać sobie sprawę z tego, że aktor przetwarza jedną wiadomość na raz, co w tym przypadku jest raczej ograniczone. Możesz użyć puli aktorów, używając routers.

Twój przykład definiuje api blokujące repozytorium, co może być jedyną rzeczą, którą możesz zrobić, w zależności od sterownika bazy danych. Jeśli to możliwe, powinieneś również skorzystać z apiksu async, czyli zwracać Futures. W przypadku aktora zamiast tego uzyskasz wynik Future od nadawcy.

+0

Tak, kontroler zależy od 'ActorRef', który może być prostym aktorem, a także routerem. –

Powiązane problemy