Delen via


Basisprincipes van JournaledGrain

Logboekkorrels afgeleid van JournaledGrain<TGrainState,TEventBase>, met de volgende typeparameters:

  • De TGrainState status van het graan wordt vertegenwoordigd. Het moet een klasse met een openbare standaardconstructor zijn.
  • TEventBase is een algemeen supertype voor alle gebeurtenissen die voor dit graan kunnen worden gegenereerd en kan elke klasse of interface zijn.

Alle status- en gebeurtenisobjecten moeten serialiseerbaar zijn (omdat de providers voor logboekconsistentie deze mogelijk moeten behouden en/of in meldingsberichten moeten verzenden).

Voor korrels waarvan de gebeurtenissen POCOs (gewone oude C#-objecten) zijn, JournaledGrain<TGrainState> kunnen worden gebruikt als een afkorting voor JournaledGrain<TGrainState,TEventBase>.

De korrelstatus lezen

Als u de huidige korrelstatus wilt lezen en het versienummer wilt bepalen, heeft journaledGrain eigenschappen

GrainState State { get; }
int Version { get; }

Het versienummer is altijd gelijk aan het totale aantal bevestigde gebeurtenissen en de status is het resultaat van het toepassen van alle bevestigde gebeurtenissen op de oorspronkelijke status. De oorspronkelijke status, die versie 0 heeft (omdat er geen gebeurtenissen op zijn toegepast), wordt bepaald door de standaardconstructor van de klasse GrainState.

Belangrijk: De toepassing mag het object dat door Statede toepassing wordt geretourneerd nooit rechtstreeks wijzigen. Het is bedoeld om alleen te lezen. Wanneer de toepassing de status wil wijzigen, moet de toepassing dit indirect doen door gebeurtenissen op te halen.

Gebeurtenissen genereren

Het genereren van gebeurtenissen wordt bereikt door de RaiseEvent functie aan te roepen. Een korrel die een chat vertegenwoordigt, kan bijvoorbeeld een PostedEvent verhogen om aan te geven dat een door de gebruiker verzonden bericht:

RaiseEvent(new PostedEvent()
{
    Guid = guid,
    User = user,
    Text = text,
    Timestamp = DateTime.UtcNow
});

Houd er rekening mee dat RaiseEvent een schrijfbewerking naar opslagtoegang wordt gestart, maar niet wacht totdat de schrijfbewerking is voltooid. Voor veel toepassingen is het belangrijk om te wachten totdat we hebben bevestigd dat de gebeurtenis is behouden. In dat geval volgen we altijd op:ConfirmEvents

RaiseEvent(new DepositTransaction()
{
    DepositAmount = amount,
    Description = description
});
await ConfirmEvents();

Houd er rekening mee dat zelfs als u niet expliciet aanroept ConfirmEvents, de gebeurtenissen uiteindelijk worden bevestigd. Dit gebeurt automatisch op de achtergrond.

Overgangsmethoden voor status

De runtime werkt de korrelstatus automatisch bij wanneer gebeurtenissen worden gegenereerd. Het is niet nodig dat de toepassing de status expliciet bijwerkt nadat een gebeurtenis is gegenereerd. De toepassing moet echter nog steeds de code opgeven die aangeeft hoe de status moet worden bijgewerkt als reactie op een gebeurtenis. Dit kan op twee manieren worden gedaan.

(a) De GrainState klasse kan een of meer Apply methoden op de StateTypeklasse implementeren. Normaal gesproken wordt er meerdere overbelastingen gemaakt en wordt de dichtstbijzijnde overeenkomst gekozen voor het runtime-type van de gebeurtenis:

class GrainState
{
    Apply(E1 @event)
    {
        // code that updates the state
    }

    Apply(E2 @event)
    {
        // code that updates the state
    }
}

b) De korrel kan de TransitionState functie overschrijven:

protected override void TransitionState(
    State state, EventType @event)
{
   // code that updates the state
}

Bij de overgangsmethoden wordt ervan uitgegaan dat ze geen andere bijwerkingen hebben dan het wijzigen van het statusobject en moeten deterministisch zijn (anders zijn de effecten onvoorspelbaar). Als de overgangscode een uitzondering genereert, wordt die uitzondering gevangen en opgenomen in een waarschuwing in het Orleans logboek, uitgegeven door de provider voor logboekconsistentie.

Wanneer, precies, de runtime de overgangsmethoden aanroept, is afhankelijk van de gekozen logboekconsistentieprovider en de configuratie ervan. Toepassingen moeten niet afhankelijk zijn van een bepaalde timing, behalve wanneer ze specifiek worden gegarandeerd door de logboekconsistentieprovider.

Sommige providers, zoals de Orleans.EventSourcing.LogStorage provider voor logboekconsistentie, herhalen de gebeurtenisvolgorde telkens wanneer het graan wordt geladen. Zolang de gebeurtenisobjecten nog steeds correct kunnen worden gedeserialiseerd vanuit de opslag, is het daarom mogelijk om de GrainState klasse en de overgangsmethoden ingrijpend te wijzigen. Maar voor andere providers, zoals de Orleans.EventSourcing.StateStorage provider voor logboekconsistentie, blijft alleen het GrainState object behouden, zodat ontwikkelaars ervoor moeten zorgen dat het correct kan worden gedeserialiseerd wanneer het wordt gelezen uit de opslag.

Meerdere gebeurtenissen genereren

Het is mogelijk om meerdere aanroepen te RaiseEvent doen voordat u belt ConfirmEvents:

RaiseEvent(e1);
RaiseEvent(e2);
await ConfirmEvents();

Dit is echter waarschijnlijk het gevolg van twee opeenvolgende toegang tot opslag en er ontstaat een risico dat het graan mislukt nadat alleen de eerste gebeurtenis is geschreven. Daarom is het meestal beter om meerdere gebeurtenissen tegelijk te genereren, met behulp van

RaiseEvents(IEnumerable<EventType> events)

Dit garandeert dat de opgegeven reeks gebeurtenissen naar de opslag atomisch wordt geschreven. Aangezien het versienummer altijd overeenkomt met de lengte van de gebeurtenisreeks, verhoogt het verhogen van meerdere gebeurtenissen het versienummer met meer dan één voor één.

De gebeurtenisvolgorde ophalen

Met de volgende methode uit de basisklasse JournaledGrain kan de toepassing een opgegeven segment van de volgorde van alle bevestigde gebeurtenissen ophalen:

Task<IReadOnlyList<EventType>> RetrieveConfirmedEvents(
    int fromVersion,
    int toVersion);

Het wordt echter niet ondersteund door alle logboekconsistentieproviders. Als dit niet wordt ondersteund of als het opgegeven segment van de reeks niet meer beschikbaar is, wordt er een NotSupportedException gegenereerd.

Als u alle gebeurtenissen wilt ophalen tot de meest recente bevestigde versie, wordt er een aangeroepen

await RetrieveConfirmedEvents(0, Version);

Alleen bevestigde gebeurtenissen kunnen worden opgehaald: er wordt een uitzondering gegenereerd als toVersion deze groter is dan de huidige waarde van de eigenschap Version.

Aangezien bevestigde gebeurtenissen nooit veranderen, zijn er geen races om zich zorgen over te maken, zelfs in aanwezigheid van meerdere exemplaren of vertraagde bevestiging. In dergelijke situaties kan de waarde van de eigenschap Version echter groter zijn op het moment dat de await cv's worden hervat dan op dat moment RetrieveConfirmedEvents wordt aangeroepen, zodat het raadzaam is om de waarde ervan in een variabele op te slaan. Zie ook de sectie over gelijktijdigheidsgaranties.