In un'applicazione CQRS / ES, le proiezioni possono dipendere?

3

Con il sourcing di eventi, è possibile proiettare un evento per creare modelli di lettura ottimizzati per le query. Questo capisco. Quello di cui non sono sicuro è se questi modelli di lettura possono dipendere l'uno dall'altro?

Sto considerando di pre-generare pagine HTML e report PDF in una certa parte di un'applicazione. Le pagine HTML non sono interattive, ma piuttosto informazioni, proprio come i report PDF. Tuttavia, per generare i report, i dati devono essere ottenuti da un'altra proiezione. Vale a dire, una proiezione SQL. Quindi l'architettura dell'applicazione dovrebbe essere la seguente:

 +-----------+
 |Event Store|                              +------------+
 +--^-----+--+                              |SQL Database+-------+
    |     |                                 +------^-----+       |
    |     |                                        |             |
    |     |                                        |             |
+---+-----v---+        +------------+         +----+----+        |
|Command Model+-------->Event Stream+----+---->Projector|        |
+-------------+        +------------+    |    +---------+        |
                                         |                       |
                                         |                       |
                                         |    +-------------+    |
                                         +---->HTML Renderer<----+
                                         |    +-------------+    |     +---------+
                                         |           +---------------->+HTML Page|
                                         |                       |     +---------+
                                         |    +------------+     |
                                         +---->PDF Renderer<-----+
                                              +------------+           +------------+
                                                     +---------------->+PDF Document|
                                                                       +------------+

Il problema di cui sopra è che HTML Renderer e PDF Renderer dipendono da un'altra proiezione, il che significa che l'ordine in cui le proiezioni sono costruite diventa importante. È un problema significativo?

L'alternativa a quanto sopra è:

  1. Tratta il rendering HTML / PDF come una query, eseguita per richiesta.
  2. Fai in modo che i proiettori HTML e PDF utilizzino le proprie strutture di dati interne (ad esempio una tabella SQL simile al proiettore SQL), rimuovendo il problema di ordinamento.
  3. Tratta il rendering HTML / PDF come un livello separato "sopra" il livello della query. Ad esempio, una query dice "dammi gli oggetti che corrispondono ai criteri C e formattali usando il formattore F". La query recupera i dati dal database e viene utilizzato il renderer appropriato per produrre l'output.
posta magnus 23.06.2016 - 03:01
fonte

2 risposte

1

Is this a significant problem?

Forse? Quanto sono importanti le differenze temporali tra le diverse proiezioni? Supponendo che queste proiezioni stiano ascoltando gli eventi indipendentemente l'una dall'altra, ci può essere un po 'di deriva quando il proiettore arriva avanti o indietro rispetto al renderer html. Cosa succede al renderer html se il database non è disponibile? O molto indietro perché abbiamo buttato via la vecchia copia corrotta e ora stiamo riproducendo l'intero flusso di eventi nel proiettore?

Treat the HTML/PDF rendering as a query, performed per request.

Questo non aiuta molto con i problemi di sincronizzazione. Ma stand alone non è una cattiva idea: il caching delle risposte alle richieste http è abbastanza ben compreso.

Make the HTML and PDF projectors use their own internal data structures (i.e., an SQL table similar to the SQL projector), removing the ordering issue.

Non è una brutta cosa, specialmente se lo schema nel database non corrisponde molto bene al caso d'uso html.

Un'altra possibilità sarebbe quella di trattare le operazioni come un processo batch; le proiezioni, invece di leggere dalla manichetta antincendio il più velocemente possibile, invece di parlare con un coordinatore, che concede il permesso di leggere solo al punto che le cose non si faranno rovinare.

    
risposta data 23.06.2016 - 06:58
fonte
0

Se comprendo correttamente il tuo diagramma:

  • Gli eventi del tuo flusso di eventi vengono inviati al proiettore (non importa se si tratta di un push in stile lettura, come in Kafka).
  • Quindi il proiettore muta imperativamente il database SQL.
  • Ma alcuni eventi vanno anche ai proiettori di rendering, che li inducono ad aggiornare un qualche tipo di rapporto (o modello utilizzato per la generazione rapida di).
  • Ma alcuni di questi aggiornamenti hanno informazioni insufficienti, quindi devono interrogare la proiezione SQL. (Questa è la parte che non sono sicuro di aver capito correttamente. Se ho ragione, la freccia qui ha un significato completamente diverso rispetto al resto delle frecce, poiché invece dell'SQL spinge qualsiasi cosa a questi servizi quando lo desidera, i servizi vieni query sql una volta prodotte da un evento.)
  • Ma ciò crea una condizione di competizione tra l'evento a cui stanno reagendo e lo stato del database SQL che vedranno.

Se ciò è corretto, ma se il proiettore HTML contiene il proprio stato che altrimenti otterrebbe dalla proiezione SQL porterebbe a troppe duplicazioni di codice / infrastruttura, si potrebbe invece fare quanto segue:

Avere il tuo proiettore , ogni volta che aggiornerebbe i valori SQL pertinenti, emettere un evento (un messaggio, non un evento di dominio persistente) nei renderer. Ci sono almeno due approcci a questo:

  1. L'evento fa riferimento all'evento che ha causato tale modifica. In questo modo, i servizi di consumo possono correlare (accoppiare) l'evento originale e il messaggio / evento elaborati da SQL risultanti e disporre di tutte le informazioni necessarie per creare un report coerente. Possono semplicemente abbandonare tutte le metà più vecchie della coppia più recente completa, indipendentemente dal fatto che stessero già aggrappandole o che siano in arrivo ora.
  2. Chiedi al proiettore di inviare tutte le informazioni richieste per aggiornare le proiezioni di rendering in un unico messaggio, costituito sia da una parte dei dati che accuratamente calcolata in base alla "cache" SQL e parte dell'originale dati dell'evento che non sono stati conservati in SQL.

Infine, oltre a far parte di Projector , potrebbe essere un servizio separato che abbina il DB, specialmente se TUTTE le informazioni per formulare il messaggio per il servizio di rendering sono disponibili in SQL. Nell'opzione 2 e in questo caso, il servizio di rendering non sarà necessariamente sottoscritto al Stream eventi .

    
risposta data 30.08.2018 - 01:12
fonte

Leggi altre domande sui tag