catalogue
Introduction to event traceability
Comparison with other event traceability implementations
A library for demonstrating event traceability as Azure's data persistence mechanism.
Introduction to event traceability
In the simplest case, event traceability is a way to store the state (for an entity), which works by storing the sequential history of all events that occur in the entity. Changes to entities are written as new events attached to the end of the entity event stream.
When a query or business process needs to use the current state of an entity, it obtains this state by running a projection on the event flow. This is a very simple piece of code. For each event, it determines (a) whether I care about this type of event and (b) if so, what should I do when I receive it.
example
Here is an example of a basic "retail bank account" (as Blazor) Front end)( Source repository on github ), which demonstrates the different types of operations on the event flow, and the source code contained in the repository. This is a completely serverless system without a "zoom to zero" underlying database.
How to use
The library allows you to interact with the event flow of the entity without any additional pipeline in Azure Functions itself - you can access the event flow or run the projection through the binding variables instantiated when executing Azure Functions.
To add an event to an event flow, use the event flow properties and classes, so:
[FunctionName("OpenAccount")] public static async Task<HttpResponseMessage> OpenAccountRun( [HttpTrigger(AuthorizationLevel.Function, "POST", Route = "OpenAccount/{accountnumber}")]HttpRequestMessage req, string accountnumber, [EventStream("Bank", "Account", "{accountnumber}")] EventStream bankAccountEvents) { if (await bankAccountEvents.Exists()) { return req.CreateResponse(System.Net.HttpStatusCode.Forbidden , $"Account {accountnumber} already exists"); } else { // Get request body AccountOpeningData data = await req.Content.ReadAsAsync<AccountOpeningData>(); // Append a "created" event DateTime dateCreated = DateTime.UtcNow; Account.Events.Opened evtOpened = new Account.Events.Opened() { LoggedOpeningDate = dateCreated }; if (! string.IsNullOrWhiteSpace( data.Commentary)) { evtOpened.Commentary = data.Commentary; } await bankAccountEvents.AppendEvent(evtOpened); return req.CreateResponse(System.Net.HttpStatusCode.Created , $"Account {accountnumber} created"); } }
To get values from the event flow, you can use the Projection property and class:
[FunctionName("GetBalance")] public static async Task<HttpResponseMessage> GetBalanceRun( [HttpTrigger(AuthorizationLevel.Function, "GET", Route = "GetBalance/{accountnumber}")]HttpRequestMessage req, string accountnumber, [Projection("Bank", "Account", "{accountnumber}", nameof(Balance))] Projection prjBankAccountBalance) { string result = $"No balance found for account {accountnumber}"; if (null != prjBankAccountBalance) { Balance projectedBalance = await prjBankAccountBalance.Process<Balance>(); if (null != projectedBalance ) { result = $"Balance for account {accountnumber} is ${projectedBalance.CurrentBalance} (As at {projectedBalance.CurrentSequenceNumber}) "; } } return req.CreateResponse(System.Net.HttpStatusCode.OK, result); }
All properties of these two properties are set to AutoResolve so that they can be set at run time.
Selected technology
For production purposes, especially for higher capacity streams, I recommend Azure Tables Back end.
Or, because the event flow is essentially a system that can only be appended, the underlying storage technology can be AppendBlob ——It is allowed to append a Blob to the end of a particular type of Blob. Each Blob can store up to 50000 events, and the container path can be nested in the same way as any other Azure Blob storage.
The selection of storage technology and storage target can be switched on the basis of each domain / entity through the configuration settings on the application.
Azure Functions The code is based on azure functions SDK version 2.0 and is written in C# language.
Comparison with other event traceability implementations
In this library, the state of the entity must be retrieved on demand - this is to allow the function application to be rotated to null, and actually allow multiple independent Azure Functions applications to use the same underlying event flow without any "always online" consistency service.
requirement
In order to use this library, you need one that can create storage containers and hosting Azure Functions Azure account for the application.
If you want to use the notification function, you also need to set the information that the library will push notifications to Event grid topics.
road map
The current version allows the entities supported by the event flow to be stored and projected in Azure table storage (recommended) or AppendBlob. This includes the concurrency protection required to safely perform this operation in a write many read scenario.
It also has outgoing notifications -- actually change feeds -- that are raised whenever a new entity is created or a new event is attached to the event flow of an existing entity. This is through Event grid Completed to allow large-scale assembly of entities supported by traceability of these events into the ecosystem.
The next stage is to enable the notification derivation trigger to listen to these outgoing notifications and trigger the serverless function when they occur, and provide a support for creating CQRS system on Azure serverless.
This article was originally published in GitHub - MerrionComputing/EventsSourcing-on-Azure-Functions: A library to demonstrate doing Event Sourcing as a data persistence mechanism for Azure Functions
https://www.codeproject.com/Articles/5205463/Event-Sourcing-on-Azure-Functions