A bit of history
Nowadays, modern software architecture moves more and more towards the cloud. Developers want to build resilient applications that can scale indefinitely. One of the techniques to achieve this is to use asynchronous messaging. These patterns are now well known and are battle-tested. However, one major issue remains. Everyone did their implementation with their enterprise standards, making interoperability between vendors almost impossible without a translation layer. That's why all the major vendors (Microsoft, Google, Amazon, Redhat, etc.) created a new industry standard called CloudEvent. This standard is also part of the Cloud Native Computing Foundation (CNCF). Everyone is now migrating toward this new format.
I've personally used it in many projects, and it works pretty well. However, the C# SDK never had what I wanted, and I found it quite hard to use without constantly looking at the documentation. It motivated me to create my abstractions on top of it to make it more user-friendly to C# developers.
- Provide reasonable defaults, but make everything extensible
- More userfriendly to use than the default C# SDK
- Type safety to avoid runtime errors
- Avoid confusion regarding the content of the
- Modern design using C# 9 records
- Structural equality (Freebie with C# 9 records)
- Intended to be used in your application's business/domain layer (carries all the metadata you need without the serialization information)
- Very opinionated
Make it type-safe
One of the main goals was first to re-enforce the type safety of the
CloudEvent object. I didn't like the fact that the
Data property was of type
object. It just makes everything hard to use later on in your business/domain layer as you need to cast it to the right type at runtime; Hello
One of the first things I implemented is
CloudEvent<T>, which expose a type
T version of the
Data property. That class also enforces the CloudEvent spec with new types like
NonEmptyString. These new types make sure that your CloudEvent is always valid at compile-time and helps the developer avoid common pitfalls. Making the
Data property of type
T also enables many compiler features like IntelliSense.
record UserCreated(string Name); var userCreated = new UserCreated("Miguel"); var ce = new CloudEvent<UserCreated>(userCreated); ce.Data.Name; // Name is now available with intellisense
I like all the metadata carried with the
CloudEvent. I find that those properties are beneficial even to perform business logic in some cases. Now that
CloudEvent<T> is typed, why not use it in our domain layer. To do, so I decided to get rid of all the serialization information (Remember I said the lib was opinionated :P). That way, the
CloudEvent<T> can be used in your domain layer as we removed all the infrastructure concepts, e.g., serialization and transport information. What does it mean in plain English?
Datais of type
Datais always assumed to be deserialized
dataschemahas been removed. Not needed as
Datais assumed to be deserialized
dataContentType. Not needed as
Datais assumed to be deserialized
In a nutshell
Until next time
This library won't fit everyone, and it's not its goal. It's a very opinionated way to use the cloud event standard in C#. Stay tuned as I'm planning on writing a few posts on the subject and show all the features and shortcuts I implemented in that library. In the meantime, any feedback or contribution is appreciated.