Conferme immediate e ritardate
In questo articolo verranno illustrate le differenze tra le conferme immediate e ritardate.
Conferma immediata
Per molte applicazioni, ci si vuole assicurare che gli eventi vengano confermati immediatamente, in modo che la versione persistente non abbia dei ritardi rispetto alla versione corrente in memoria e non si rischi di perdere lo stato più recente se il livello di granularità dovesse non riuscire. È possibile garantire questo comportamento seguendo queste regole:
- Confermare tutte le chiamate RaiseEvent usando ConfirmEvents prima che venga restituito il metodo granulare.
- Assicurarsi che le attività restituite da RaiseConditionalEvent si completino prima che venga restituito il metodo granulare.
- Evitare gli attributi ReentrantAttribute o AlwaysInterleaveAttribute, così che è possibile elaborare una sola chiamata granulare alla volta.
Se si seguono queste regole, significa che, dopo la generazione di un evento, nessun altro codice granulare può essere eseguito fino a quando l'evento non è stato scritto nella risorsa di archiviazione. Pertanto, è impossibile osservare incoerenze tra la versione in memoria e la versione nell'archiviazione. Anche se spesso è proprio quello che vogliamo, ha anche alcuni potenziali svantaggi.
Potenziali svantaggi
Se la connessione a un cluster remoto o a una risorsa di archiviazione viene interrotta temporaneamente, la granularità diventa non disponibile: in effetti, il livello di granularità non può eseguire alcun codice mentre è bloccato in attesa di confermare gli eventi, che può richiedere una quantità illimitata di tempo (il protocollo di coerenza dei log continua a riprovare fino a quando non viene ripristinata la connettività di archiviazione).
Quando si gestiscono molti aggiornamenti a una singola istanza di granularità, confermarli uno alla volta può diventare molto inefficiente, ad esempio causando una velocità effettiva scarsa.
Conferma ritardata
Per migliorare la disponibilità e la velocità effettiva nelle situazioni indicate in precedenza, i grani possono scegliere di eseguire una o entrambe le operazioni seguenti:
- Consentire ai metodi granulari di generare eventi senza attendere la conferma.
- Consentire la reentrancy, in modo che la granularità possa continuare a elaborare nuove chiamate anche se le chiamate precedenti rimangono bloccate in attesa di conferma.
Ciò significa che il codice granulare può essere eseguito mentre alcuni eventi sono ancora in corso di conferma. L'API JournaledGrain<TGrainState,TEventBase> include alcune disposizioni specifiche per fornire agli sviluppatori un controllo preciso su come gestire gli eventi non confermati attualmente distribuiti in anteprima.
È possibile esaminare la proprietà seguente per scoprire quali eventi sono attualmente non confermati:
IEnumerable<EventType> UnconfirmedEvents { get; }
Inoltre, poiché lo stato restituito dalla proprietà JournaledGrain<TGrainState,TEventBase>.State non include l'effetto degli eventi non confermati, esiste una proprietà alternativa
StateType TentativeState { get; }
Che restituisce uno stato "provvisorio", ottenuto da "Stato" applicando tutti gli eventi non confermati. Lo stato provvisorio è essenzialmente un’"ipotesi migliore" a ciò che probabilmente diventerà lo stato confermato successivo dopo che tutti gli eventi non confermati vengono confermati. Tuttavia, non c'è alcuna garanzia che lo faccia davvero, perché la granularità può non riuscire, o perché gli eventi possono correre contro altri eventi e perdere, causando l'annullamento (se sono condizionali) o appaiono in una posizione successiva nella sequenza rispetto a quella prevista (se sono incondizionati).
Garanzie di concorrenza
Si noti che le garanzie di pianificazione basata su turni (concorrenza cooperativa) Orleans si applicano sempre, anche quando si usa la reentrancy o la conferma ritardata. Ciò significa che, anche se possono essere in corso diversi metodi, solo uno può essere eseguito attivamente, tutti gli altri sono bloccati in attesa, quindi non ci sono mai vere gare causate da thread paralleli.
In particolare, si noti che:
- Le proprietà State, TentativeState, Version e UnconfirmedEvents possono cambiare durante l'esecuzione di un metodo.
- Ma tali modifiche possono verificarsi solo mentre sono bloccate in attesa.
Queste garanzie presuppongono che il codice utente rimanga all'interno della procedura consigliata relativa alle attività e async/await (in particolare, non usa le attività del pool di thread, o le usa solo per il codice che non chiama la funzionalità granulare e che sono attese correttamente).