Trying to create a fairly simple outbox pattern without taking dependencies on external libraries. Core thing I am trying to accomplish is handle transient failures. I use CQRS along with Mediatr to keep my view DB in eventual consistency with my transaction DB. I update view DB via in-process events via handlers. (E.g. UserCreatedEvent -> UserCreatedEventHandler)
In order to ensure events are not lost due to transient failures, I am storing them in a DB and publish them through a background process. Since handlers are typed to a class, only a single handler will execute (UserCreatedEvent is handled by UserCreatedEventHandler).
I can have X number of events types defined in a project, and they are all independent of each other in terms of properties. They will all have a common marker interface (INotification). In order to handle transient failures, when saving the transaction DB, I serialize my event and stored in DB like below.
public record SampleMessage(string Value, string Type);
//serialization
string typeOfNotification = typeof(T).AssemblyQualifiedName;
SampleMessage message = new(JsonSerializer.Serialize(content), typeOfNotification);
//deserialization
Type messageType = Type.GetType(message.Type)
var dvalue = JsonSerializer.Deserialize(message.Value, messageType);
await publisher.Publish(dvalue);
I have a big concern with storing type info in my objects. I might end up moving from storing these in a DB to publishing them to a broker and handle processing via an external system. I believe storing types is also no longer recommended due to vulnerabilities. What would be a good alternative to this that is maintainable?
One idea I had was storing a “Type” enum, that would just store something related to the event (e.g. UserCreated)
public record SampleMessage(string Value, MessageType Type);
public MessageType { UserCreated, UserDeleted };
//deserialize
var result = switch content.Type
{
UserCreated=> JsonSerializer.Deserialize<UserCreatedEvent>(content)
_ => //Throw exception
}
This is fairly straightforward but I will end up with a huge swath of switch statements and modifying this every time new events are added. Most of the answers I see related to this is using custom converters but they were mainly for polymorphic deserialization (e.g. Deserializing polymorphic json classes without type information using json.net). I need to deserialize into non-polymorphic typed objects that won’t have any inheritance.
What is the best practice around this?