Brainix.GoalsCommon
1.0.0-beta-112
See the version list below for details.
dotnet add package Brainix.GoalsCommon --version 1.0.0-beta-112
NuGet\Install-Package Brainix.GoalsCommon -Version 1.0.0-beta-112
<PackageReference Include="Brainix.GoalsCommon" Version="1.0.0-beta-112" />
paket add Brainix.GoalsCommon --version 1.0.0-beta-112
#r "nuget: Brainix.GoalsCommon, 1.0.0-beta-112"
// Install Brainix.GoalsCommon as a Cake Addin #addin nuget:?package=Brainix.GoalsCommon&version=1.0.0-beta-112&prerelease // Install Brainix.GoalsCommon as a Cake Tool #tool nuget:?package=Brainix.GoalsCommon&version=1.0.0-beta-112&prerelease
Documentation
Summary
The GoalsCommon Package is a package that consists of three main parts: a RabbitMQ bus, the learning tree structure and a DataLoad helper.
Dependencies
The GoalsCommon Package has the following dependencies:
Usage
Installation
To install the GoalsCommon Package, the following command must be executed in the project's folder:
dotnet add package Brainix.GoalsCommon --prerelease
Initialization of the RabbitMQ bus
The RabbitMQ bus is to be controlled via the Brainix.GoalsCommon.RabbitMQ.Bus.IBrainixEventBus
interface. There are two implementations for this in the Goals-Common package. The Brainix.GoalsCommon.RabbitMQ.Bus.DefaultRabbitMQBus
class is used for normal communication with a RabbitMQ server. The Brainix.GoalsCommon.RabbitMQ.Bus.TestRabbitMQBus
class was written to efficiently create integration tests with RabbitMQ.
DefaultRabbitMQBus
The DefaultRabbitMQBus is initialised with a RabbitMQConfiguration. This contains the complete ConnectionString
and an ApplicationName
. A normal initialisation would look like this:
using Brainix.GoalsCommon.RabbitMQ.Bus;
...
var brainixEventBus = new DefaultRabbitMQBus(new RabbitMQConfiguration(
"amqp://username:password@url:port/",
"serviceName"
));
In a real use case, the values for the ConnectionString
and the ApplicationName
would of course have to be chosen appropriately.
A classic initialisation in the context of a dependency injection would look like this:
using Brainix.GoalsCommon.RabbitMQ.Bus;
...
services.AddSingleton<IBrainixEventBus, DefaultRabbitMQBus>(conf => new DefaultRabbitMQBus(
new RabbitMQConfiguration(
Configuration.GetConnectionString("rabbit_mq").Replace(<%password%>",vault.rabbitMQPassword),
"TrainingCenter"
)
));
TestRabbitMQBus
The TestRabbitMQBus is only initialised with a messageDelayInMs
. The number of milliseconds by which the transmission of a new message to the consumer should be delayed is passed here.
A classic initialisation in the context of a dependency injection would look as follows:
using Brainix.GoalsCommon.RabbitMQ.Bus;
...
services.AddSingleton<IBrainixEventBus, TestRabbitMQBus>((messageDelayInMs) => new TestRabbitMQBus(1));
BrainixEvents
All events that should be processed by the RabbitMQ bus must inherit from the generic, abstract class Brainix.GoalsCommon.RabbitMQ.Models.BrainixEvent
. Each event shall contain a clearly defined data structure. The purpose of each event shall be explained in a short DocString.
Each BrainixEvent also has the possibility to declare different event types. This can be done by declaring a public, internal enum with the name EventType
for the respective BrainixEvent (Here it is very important that the name of the enum is written exactly like this).
Here is a short example:
using System;
namespace Brainix.GoalsCommon.RabbitMQ.Models.DomainEvents
{
/// <summary>
/// This event is used for publishing Notifications that were produced by a specific user.
/// </summary>
public class NotificationEvent: BrainixEvent
{
public Guid SenderUserId { get; set; }
public string NotificationContent { get; set; }
public enum EventType
{
Information,
Warning
}
}
}
Routing logic for BrainixEvents
The routing logic in RabbitMQ EventBus is based on topic exchanges and work queues. The underlying idea is that each event is published via its own exchange. Each individual microservice that wants to consume this event has its own queue that is bound to the respective exchange via one or more binding keys. The individual instances of the microservice consume directly from the queue. In concrete terms, this means that when a new Brainix event is published, an exchange with the name of the event is created. If a microservice specifies that it consumes an event, a queue is created and bound to the exchange. Here, all events - regardless of type - are consumed initially. If the consumer specifies that only a certain event types should be consumed, the binding key (between the exchange and the queue) will carry the names of the event types. From now on, only events of that types will be placed in the respective queue. This logic is illustrated by the following diagram:
Publish
To send an event, the method Publish<T>(T brainixEvent, Func<BrainixEventCallback, Task> callbackDelegate) where T : BrainixEvent
must be called from the Brainix.GoalsCommon.RabbitMQ.Bus.IBrainixEventBus
. This will take the event to be sent and optionally a callback function which will be called once the event has been successfully sent to the RabbitMQServer and the reception has been confirmed. By default, an event is initialised with the Default
event type, where the EventTypeNumber
has the value 0. If a special EventType should be set, then the EventTypeNumber
property must be filled with the number of the matching element of the respective EventType
enumeration. Here is a short example:
brainixEventBus.Publish(new NotificationEvent
{
EventTypeNumber = (int) NotificationEvent.EventType.Information,
SenderUserId = new Guid("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"),
NotificationContent = "Hello World!"
}, async (brainixEventCallback) =>
{
if(brainixEventCallback.Success){
//Handle successful publish
}
else
{
//Handle unsuccessful publish
}
});
Consume
To consume an event, the method Subscribe<T>(Func<T, Task> handlerFunction, List<int> eventTypeNumbers) where T : BrainixEvent
must be called from the Brainix.GoalsCommon.RabbitMQ.Bus.IBrainixEventBus
. This receives a handler function which is called as soon as a new event has been consumed. It should be noted that if this function cannot be successfully executed (an exception is caught), the event is put back into the queue and will no longer be consumed. It is also important to note that you cannot call the database directly from the handler function, because you are in a different thread and context. More information on this can be found in the corresponding documentation. Optionally, a list with the numbers of the respective event types that are to be consumed can be given to the method. This parameter determines the individual binding between the queues and exchanges that has already been explained. Here is a short example:
brainixEventBus.Subscribe<NotificationEvent>(async (notificationEvent) =>
{
//Do something with notificationEvent
}, new List<int>
{
(int) NotificationEvent.EventType.Information
});
Testing
For testing with the RabbitMQ bus, the IBrainixEventBus
interface must be implemented by the Brainix.GoalsCommon.RabbitMQ.Bus.TestRabbitMQBus
. Events can be sent and consumers defined in the integration test in the same way as in the normal implementation. However, it is important to note that the handler function of the consumer is always called in a different thread and thus executed with a time delay. This is especially important when writing to cross-thread objects within the integration test and comparing them with the expected object using Assert
. It is advisable to pause the main thread for a few milliseconds to ensure that all other threads have successfully completed their work. Alternatively, you can do the ``assert'' directly in the handler function, which is cleaner in many cases, but does not cover the case where an event is never consumed.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 is compatible. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
-
net5.0
- Brainix.Common.Classes-v2 (>= 1.0.1)
- Newtonsoft.Json (>= 13.0.1)
- Polly (>= 7.2.2)
- RabbitMQ.Client (>= 6.2.2)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
1.0.2-beta-311 | 214 | 12/9/2022 |
1.0.2-beta-307 | 238 | 12/6/2022 |
1.0.2-beta-305 | 161 | 12/5/2022 |
1.0.2-beta-303 | 138 | 12/5/2022 |
1.0.2-beta-300 | 149 | 11/30/2022 |
1.0.2-beta-298 | 150 | 11/30/2022 |
1.0.2-beta-296 | 155 | 11/30/2022 |
1.0.2-beta-292 | 276 | 11/16/2022 |
1.0.2-beta-290 | 140 | 11/16/2022 |
1.0.2-beta-288 | 152 | 11/16/2022 |
1.0.2-beta-286 | 155 | 11/16/2022 |
1.0.2-beta-283 | 405 | 10/19/2022 |
1.0.2-beta-282 | 180 | 10/18/2022 |
1.0.2-beta-280 | 185 | 10/18/2022 |
1.0.2-beta-279 | 164 | 10/18/2022 |
1.0.2-beta-277 | 194 | 10/14/2022 |
1.0.2-beta-270 | 2,029 | 4/19/2022 |
1.0.2-beta-269 | 200 | 4/19/2022 |
1.0.2-beta-267 | 206 | 4/19/2022 |
1.0.2-beta-264 | 289 | 4/18/2022 |
1.0.2-beta-261 | 196 | 4/15/2022 |
1.0.2-beta-258 | 209 | 4/15/2022 |
1.0.2-beta-255 | 208 | 4/12/2022 |
1.0.2-beta-253 | 262 | 4/5/2022 |
1.0.2-beta-247 | 205 | 3/28/2022 |
1.0.2-beta-244 | 299 | 3/16/2022 |
1.0.2-beta-241 | 191 | 3/13/2022 |
1.0.2-beta-234 | 464 | 3/9/2022 |
1.0.2-beta-232 | 392 | 3/8/2022 |
1.0.2-beta-230 | 200 | 3/8/2022 |
1.0.2-beta-228 | 190 | 3/8/2022 |
1.0.2-beta-226 | 205 | 3/8/2022 |
1.0.2-beta-224 | 201 | 3/8/2022 |
1.0.2-beta-221 | 201 | 3/8/2022 |
1.0.2-beta-217 | 217 | 3/8/2022 |
1.0.2-beta-214 | 215 | 3/6/2022 |
1.0.2-beta-212 | 342 | 3/2/2022 |
1.0.2-beta-209 | 210 | 3/2/2022 |
1.0.2-beta-208 | 766 | 3/2/2022 |
1.0.2-beta-203 | 266 | 3/1/2022 |
1.0.2-beta-200 | 590 | 2/28/2022 |
1.0.2-beta-198 | 208 | 2/27/2022 |
1.0.2-beta-195 | 213 | 2/26/2022 |
1.0.2-beta-193 | 202 | 2/26/2022 |
1.0.2-beta-191 | 205 | 2/26/2022 |
1.0.2-beta-184 | 499 | 2/11/2022 |
1.0.2-beta-181 | 233 | 2/9/2022 |
1.0.2-beta-178 | 459 | 2/5/2022 |
1.0.2-beta-175 | 197 | 2/5/2022 |
1.0.2-beta-173 | 189 | 2/5/2022 |
1.0.2-beta-171 | 272 | 2/4/2022 |
1.0.2-beta-169 | 216 | 2/3/2022 |
1.0.2-beta-165 | 333 | 1/31/2022 |
1.0.2-beta-162 | 223 | 1/31/2022 |
1.0.2-beta-159 | 246 | 1/29/2022 |
1.0.2-beta-154 | 513 | 1/25/2022 |
1.0.2-beta-152 | 210 | 1/25/2022 |
1.0.2-beta-147 | 322 | 1/24/2022 |
1.0.2-beta-145 | 235 | 1/24/2022 |
1.0.2-beta-141 | 233 | 1/21/2022 |
1.0.2-beta-139 | 221 | 1/20/2022 |
1.0.2-beta-132 | 217 | 1/19/2022 |
1.0.2-beta-125 | 377 | 1/18/2022 |
1.0.2-beta-000 | 220 | 1/19/2022 |
1.0.1 | 547 | 1/18/2022 |
1.0.1-beta-120 | 203 | 1/18/2022 |
1.0.0-beta-99 | 216 | 1/17/2022 |
1.0.0-beta-96 | 205 | 1/16/2022 |
1.0.0-beta-94 | 212 | 1/16/2022 |
1.0.0-beta-92 | 218 | 1/16/2022 |
1.0.0-beta-9 | 218 | 1/6/2022 |
1.0.0-beta-88 | 273 | 1/15/2022 |
1.0.0-beta-85 | 234 | 1/14/2022 |
1.0.0-beta-82 | 211 | 1/14/2022 |
1.0.0-beta-80 | 198 | 1/14/2022 |
1.0.0-beta-78 | 220 | 1/14/2022 |
1.0.0-beta-75 | 231 | 1/11/2022 |
1.0.0-beta-73 | 275 | 1/11/2022 |
1.0.0-beta-71 | 208 | 1/11/2022 |
1.0.0-beta-7 | 263 | 1/6/2022 |
1.0.0-beta-69 | 226 | 1/11/2022 |
1.0.0-beta-67 | 217 | 1/11/2022 |
1.0.0-beta-65 | 205 | 1/11/2022 |
1.0.0-beta-63 | 271 | 1/11/2022 |
1.0.0-beta-61 | 198 | 1/11/2022 |
1.0.0-beta-58 | 203 | 1/11/2022 |
1.0.0-beta-56 | 210 | 1/11/2022 |
1.0.0-beta-53 | 229 | 1/10/2022 |
1.0.0-beta-51 | 223 | 1/10/2022 |
1.0.0-beta-50 | 221 | 1/10/2022 |
1.0.0-beta-48 | 216 | 1/10/2022 |
1.0.0-beta-46 | 222 | 1/10/2022 |
1.0.0-beta-44 | 209 | 1/10/2022 |
1.0.0-beta-42 | 294 | 1/8/2022 |
1.0.0-beta-40 | 222 | 1/8/2022 |
1.0.0-beta-4 | 209 | 1/6/2022 |
1.0.0-beta-38 | 228 | 1/8/2022 |
1.0.0-beta-36 | 213 | 1/8/2022 |
1.0.0-beta-35 | 201 | 1/8/2022 |
1.0.0-beta-32 | 217 | 1/8/2022 |
1.0.0-beta-26 | 213 | 1/8/2022 |
1.0.0-beta-24 | 218 | 1/8/2022 |
1.0.0-beta-22 | 203 | 1/8/2022 |
1.0.0-beta-20 | 220 | 1/8/2022 |
1.0.0-beta-15 | 221 | 1/8/2022 |
1.0.0-beta-13 | 215 | 1/7/2022 |
1.0.0-beta-128 | 206 | 1/19/2022 |
1.0.0-beta-112 | 203 | 1/18/2022 |
1.0.0-beta-109 | 204 | 1/18/2022 |
1.0.0-beta-104 | 219 | 1/17/2022 |