Domanda

Perché la mia prima domanda è stata così a lungo, mi sto chiedendo questo come una questione a sé stante. Si tratta di un altro sull'architettura di un'applicazione attore-based.

Tenere traccia dei percorsi dei messaggi attraverso un Application

Diamo un pezzo di codice Java:

public void deleteTrades(User user, Date date) {
    PermissionSet ps = permissionService.findPermissions(user)
    if (ps.hasPermission("delete")) {
        Set<Trade> ts = peristence.findTrades(date);
        reportService.sendCancelReports(ts);
        positionService.updateWithDeletedTrades(ts);
    }
}

In questo codice ho 4 componenti separati e l'interazione tra loro per il procedimento deleteTrades è ben definito. E 'completamente contenuto nel metodo deleteTrades.

Modellazione questo con Actors e sostituendo i miei 4 componenti con 4 attori separati, come faccio a tenere traccia (nella mia mente) di quello che una procedura comporta? In particolare, se sto evitando di usare il !? operatore, allora è probabile che sarò inviando un messaggio al mio ConditionalDelete PermissionActor, che invierà un messaggio alla mia GetTradesAndDelete PersistenceActor che poi inviare ulteriori messaggi ecc ecc Il codice per elaborare una cancellazione sarà disseminata in tutta la mia domanda.

Questo significa anche che praticamente ogni attore ha bisogno di una maniglia su ogni altro attore (in modo da inoltrare i messaggi).

Come nel mio precedente domanda, come fanno le persone ad affrontare con questo? C'è un buon strumento di modellazione che consente di tenere traccia di tutto questo? Le persone usano !? Sono girando troppi componenti in Actors?

È stato utile?

Soluzione

Si utilizza 5 componenti, sicuramente. Ci sono attori che si occupano di compiti specifici, e c'è un orchestratore pure.

La domanda che deve avere, naturalmente, è come si fa a concatenano questo assynchronously. Beh, in realtà è un po 'facile, ma può oscurare il codice. In sostanza, si invia ogni componenent la risposta che si desidera.

react {
  case DeleteTrades(user,dates) => 
    PermissionService ! FindPermissions(user, DeleteTradesPermissions(dates) _)
  case DeleteTradesPermissions(dates)(ps) =>
    if (ps hasPermission "delete")
      Persistence ! FindTrades(date, DeleteTradesTradeSet _)
  case DeleteTradesTradeSet(ts) =>
    ReportService ! SendCancelReports(ts)
    PositionService ! UpdateWithDeletedTrades(ts)
}

Qui usiamo currying di passare "date" nella prima risposta di ritorno. Se c'è un sacco di parametri associati a un'interazione, potrebbe essere meglio per mantenere le informazioni per tutte le transazioni in corso in un HashSet locali, e solo passare un token che verranno utilizzate per individuare le informazioni quando si riceve la risposta.

Si noti che questo singolo attore in grado di gestire più azioni simultanee. In questo caso particolare, basta eliminare le transazioni, ma si potrebbe aggiungere qualsiasi numero di azioni diverse per esso da gestire. Quando i dati necessari per un'azione è pronto, quindi, che l'azione continua.

Modifica

Ecco un esempio di lavoro di come queste classi possono essere definite:

class Date
class User
class PermissionSet

abstract class Message
case class DeleteTradesPermission(date: Date)(ps: PermissionSet) extends Message
case class FindPermissions(u: User, r: (PermissionSet) => Message) extends Message

FindPermissions(new User, DeleteTradesPermission(new Date) _)

Alcuni spiegazioni sulle currying e funzioni. La classe è DeleteTradesPermission curry in modo da poter passare un Date su di esso, e hanno qualche altra funzione completarlo con un PermissionSet. Questo sarebbe il modello dei messaggi di risposta.

Ora, la FindPermissions classe riceve come secondo parametro di una funzione. L'attore che riceve questo messaggio passerà il valore di ritorno a questa funzione, e riceverà un Message da inviare come risposta. In questo esempio, il messaggio avrà sia la Date, che l'attore chiamata mandato e PermissionSet, che l'attore risposta sta fornendo.

Se si prevede nessuna risposta, come ad esempio il caso di DeleteTrades, SendCancelReports e UpdateWithDeletedTrades ai fini di questo esempio, allora non c'è bisogno di passare una funzione del messaggio di ritorno.

Dato che ci aspettiamo una funzione che restituisce un messaggio come parametro per i messaggi che richiedono una risposta, potremmo definire i tratti in questo modo:

trait MessageResponse1[-T1] extends Function1[T1, Message]
trait MessageResponse2[-T1, -T2] extends Function2[T1, T2, Message]
...

Altri suggerimenti

Gli attori non devono essere utilizzati per sostituire componenti di servizio tradizionali senza considerazioni.

La maggior parte dei componenti di servizio che scriviamo al giorno d'oggi, attraverso la formazione, sono apolidi. componenti di servizio senza stato sono più facili da gestire (classe sans messaggio, ecc) di attori. Una delle cose che mancano però, quando confrontarle attori, è esecuzione asincrona. Ma quando i clienti si aspettano i risultati per restituire in modo sincrono la maggior parte del tempo, componenti di servizio senza stato sincroni sono più che bene per il lavoro.

attore è una buona misura quando ci sono stati interni da gestire. Non c'è bisogno di fare alcuna sincronizzazione dentro "atto ()" per accedere stati interni e di preoccuparsi di condizioni di gara. Fintanto che "!?" non viene usata all'interno "atto ()", deadlocking dovrebbe essere minimizzata pure.

Gli attori dovrebbero diffidare di qualsiasi trattamento di blocco fatto mentre la gestione dei messaggi. Poiché attori elaborano i loro messaggi in sequenza, ogni volta che vengono bloccati in attesa di I / O interna "atto ()", non possono elaborare altri messaggi nei loro cassette postali. L'idioma Scala da utilizzare è quello di iniziare un altro attore ad hoc che fa l'effettivo funzionamento di blocco. Questo anti-pattern influenza (reagiscono) attore basato evento ancora più perché blocca la filettatura l'attore basato su eventi è piggy-back pure.

Da quello che ho potuto capire, tutte e quattro le chiamate ai componenti di servizio sono potenzialmente il blocco, in modo da cure dovrebbero essere prese per renderli scala quando convertirli in attori.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top