Build Messaging in .NET with Wolverine
2024 ж. 14 Ақп.
56 900 Рет қаралды
Use code MODULAR and get 20% off the brand new "Getting Started with Modular Monoliths" course on Dometrain: dometrain.com/course/getting-...
Get the source code: mailchi.mp/dometrain/p1gsk69m94y
Become a Patreon and get special perks: / nickchapsas
Hello, everybody, I'm Nick, and in this video, I will show you how you can get started with messaging in .NET using a Nuget package called Wolverine.
This video is sponsored by AWS
Workshops: bit.ly/nickworkshops
Don't forget to comment, like and subscribe :)
Social Media:
Follow me on GitHub: github.com/Elfocrash
Follow me on Twitter: / nickchapsas
Connect on LinkedIn: / nick-chapsas
Keep coding merch: keepcoding.shop
#csharp #dotnet
Can you do a video about difference between Masstransit and this. From a Masstransit user's perspective, you don't need any queue and exchange configuration at all. It can create all endpoints for you. More streamlined You don't have to explitly tell listen to that queue etc.
16:35 Transactional Outbox pattern. So glad you talk about it.
Great timing. I was looking for a video on Wolverine.
Awesome! Eagerly awaiting NServiceBus video🥳
In a previous project we were using Rebus, which I quite enjoyed, I am not sure if the project is still active but I would choose if again any time :)
Look nice, thanks for sharing this!
I kind of wanna watch that "Nick the Great" comedy 😅
Nice video. I am a fan of MassTransit. It feels a bit more mature, but it’s good there are choices. When looking into the way to implement Sagas in Wolverine, they look very similar to the NServiceBus implementation, though I prefer the state machine Sagas of MassTransit. Keep these videos coming. 👌🏻
Setup wolverine with azure service bus and it just works. Amazing!
Automagically 😂 this is brilliant!
I also think the fact that he's embedded his messaging solution with his custom DI is pretty crappy. One not abstracted out so we could choose our own DI provider
Not trying to say one way is better or crappier, but the author (Jeremy Miller @jeremymiller9966 ) was also the author of StructureMap - the original IOC container for .NET. That project was eventually obsoleted by Lamar, as he created it to be compatible with the .NET Service Provider, faster, and while offering many of the additional features available in StructureMap (e.g., registries, decorators, diagnostics, conventional registration, etc.). His choice in using this is probably so he supports convention-based wiring of handlers without using runtime reflection tricks which can be a tad slower. By doing that, and also pushing for a Wolverine best practice approach favoring pure functions and method injection vs. constructor injection (though still supported), he can provide better runtime performance of the Wolverine framework. Also worth noting that WolverineFX is part of his broader Critter Stack, which includes Marten for event sourcing with Postgresql.
@@tafs7 My issue is that he's forcing an implementation of a non-messaging solution in his messaging solution. It should be open to extension.
Great video!
thx for all your video Nick, and i have a little confusion between Wolverine and event,please answer me.Wolverine it can replace "event" in dotnet???
Cool! Any idea how hard it is to implement your own transports?
Hey I really find your videos and insight helpful and was wondering if you can make a video explaining how to structure and organize big solutions, where they might have multiple parts like say SDKs they made for integrations and Helper libraries and so on that they are using in their main UI app. Also would like to know how do you do source control on them.... From what I've read some do multiple projects, some do folders within the same project some do nuget packages. Would really appreciate your take on this topic.
I haven't dived into its source code but it seems to have some aspects of an actor model implementation e.g. remoting, discovery and persistence features. You can also respond to the sender
Hi Nick, thank you for the video. what is better? MassTransit or Wolverine
This looks like a neat package. Although I don't like the fact that the messaging configuration for the individual messages is abstracted away from the message contract. This creates some fragility in the solution as both the sender and receiver of the message need to individually properly configure the queue name to the same queue. I'd much rather be able to decorate my messages with attributes that have that configuration data. That way when I share contract, I'm also sharing the Queue or topic name. I'd also like some designation on the contract whether or not this is intended to dispatch work or a notification. If I'm dispatching work, it's likely to go to a queue, and if I am sending a notification, I am likely to use a pub sub solution.
Awesome content as always 😁. Would you prefer MassTransit over Wolverine or contrary and why so ? :)
Looks interesting. I'd say auto-creation of queues/exchanges is great for dev purposes. When you have many queues, I'd prefer to have separate script that can create all of them - much easier for things like creating a new environment (e.g. for load testing)
Perfect :)
This is very similar to a library I built not too long ago. The main differences are that I had an attribute on the consumer to indicate it's an event consumer, and also, I didn't replace the entire DI container..
8:18 for most duck typing, I think the method or class should have an attribute. Otherwise what's stopping the messaging system from assuming *all* Handle methods are message handlers? The built in ducktyping in C# I know of are Deconstruct, and 'void Dispose(), which makes allows you to use something like 'using var x = new MyDucktypedDispose()' with ref structs, which can't have interfaces. Both of those are to allow language features, not to let some system slurp them up. Tldr; unless it's to enable language features, don't use purely duck typing.
I'm still unsure as to the conventions vs contract thingy. On the one hand, I think that not having the bloat of extra Interfaces is pretty neat. Don't have to repeat myself myriads of time. On the other hand, it gives me some kind of safety in a way. Since I'm someone who also misspells his own name from time to time, that naming by convention thing is bound to fail here and there from time to time. I'm 49 : 51 on this.
It's a bit "springlike", but not as much magic as spring, so it's OK I think, I'll give it a go. But I'm not sure it'll work well with kafka where you need to carefully plan your keys for scaling. It's the same woth most service bus abstractions I find
That's an awesome video. Thank you. I d like your 2 cents on a project that I am working, and also whether I could use Wolverine for that particular project. I have a Windows Service app in .NET Core that works as a bridge between a system and a Web Service (SOAP if that matters). The Windows Service reads a sql table if there are any new records every X time and it adds them to a BlockingCollection and updates a bit on the db that those records were loaded . The app needs to be quick so there are 3-4 tasks that check the BlockingCollection for new entries and consume an item in order to communicate with the Web Service and record the response into a different database table. Could I replace that part of the code with wolverine and the SqlServer nuget to have the same effect, instead of using my not so well written code ?
Looks excellent for use.
Great video, can one use Wolverine with MongoDB ?
Fantastic video as usual. I am curious though why you would need to specify a queue for publishing in RabbitMQ? The queue should be defined by the consumer no?
Yeap you are right. Originally when I planned the video I showed the consumer first so I used the wrong code sample.
THANKS 👍👏👏👏🤝🤝
WOW. One of the most best videos!!! Like++++++++++
Would be cool if you can do from configuration like add bearer auth is working right now.
Great vid! But what about MassTransit with its messaging/request-response? It is still more usable IMO.
Interested how this compares to MassTransit. What are the reasons to pick one over the other?
This is important, especially if this one replaces the DI container silently. That's a big ask, so there needs to be enough reason, or MassTransit is simply an easy choice.
From what I read and heard so far, Wolverine looks very nice, but it also looks like it mainly just has feature parity, and in this case I do not know why I would want to use it over MassTransit, which is a tried and tested framework
It's totally different to MassTransit, which is a framework that forces ideas upon you, unlike Wolverine. Much more flexible and easy to use.
How would you feel about the conventional stuff if they also packaged a set of roslyn analyzers that would check against these conventions?
I hate conventional stuff in almost any case. It forces ALL developers in the team to be aware of ALL conventions. That makes onboarding new people on the project harder, because it is easier when you have contracts everywhere, since you can already see/navigate into the package which does something with that piece of code aka it is self documented.
@@Scroapyfair enough, many developers don’t like conventional magic, and without good tooling it can lead to situations where it’s hard to figure out what’s going on. Though in Wolverine it is btw possible to configure the discovery manually with your own conventions, or disable automatic discovery all together and rely on attributes if you so wish (worse or better than forcing interfaces on your code?) For learning and adapting to a new set of conventions there are two starting points. 1) green field project, or introducing a new framework, where there is some initial learning curve and probably some failures and frustrations. And 2) an existing project with already written code with these conventions, then just reading the existing code should guide you in that direction. If the developers struggle to adapt to conventions in a code base with guidance then I would worry about other problems
Hi Nick, I think it would be interesting to create video content on how to read messages from event hub and send that messages to data source Mimir and consume the data from Mimir in another web api that displays it, instead displaying it in grafana.
While this really looks nice, i hate implicit frameworks like this. It's the same problem i had with reflection in WPF apps and AutoMapper IL code generation. MassTransit for me is just explicit, i can track what is happening without having to learn the conventions. And i imagine - debugging issues with implicit framework like that might end up with nightmares
So, can you return a result type that also contains events to be published? Result types make it easy to have a uniform API end points, as the API part can parse the which result type is returned and create a proper message to return on your API. But if you want to publish an event that could be cool too. I suppose you could just manually publish the event if you are doing that. But it would be nice to see an example of this pattern. One thing that I like to say about the Result type is that it doesn't handle errors, it handles short circuiting your code and returning a message. So, it is more of a messaging way to talk to upper level codes explicitly. Without the cost of throwing exceptions.
Why did I have a feeling at first that the magic is based on reflection, and not NativeAOT-friendly?
Is it AOT-friendly?
Isn't that why the dev uses his own DI so that it is nativeAOT friendly?
It uses code generation from what I can see.
It uses source generators. There are some examples on the wolverine website of the generated code.
Hi Nick, Thanks for the video. I'm using MassTransit and would it would be awesome to have a video about it as well. And with some comparison points between Wolverine with your opinion would be even better!
Been waiting for this ever since I saw you joined the Critter Stack Discord. This is a great overview, Ive sent the link to all my co-workers in hopes they'll start using Wolverine more😅
I'm not in the Critter Stack Discord 🤔
@@nickchapsas lol
"Deadpool & Wolverine (2024) Trailer Now Out!"
Threadpool and Wolverine (2024)
Is there a way to publish the messages without a BackgroundService class? like normal windows or console apps that don't need to run constantly
What are the main pros and cons with this over classics like MassTransit and RabbitMQ?
Can this be used to monitor an Azure service bus queue where messages are written to it from other things which aren't using Wolverine?
string matching for method names!? in 2024!? what are we, javascript developers??
11:43: That won't happen in this scenario. Logging alone IS a side effect next to handling the original request. If you call the method multiple times, the timestamp of the log entry will always be different as an example
What I really wanna see is a good framework that can also deal with dead-lettering
We use MediatR and I wonder if by the time we upgrade (we are many versions back), the API will be like that of Wolverine.
It won't. The internal approach between MediatR & Wolverine is very different.
Sometime, please do a video on your thoughts on MassTransit. It might have a bit more config than something like MediatR, but also very versatile.
He already has
@@logantcooper6, I'm sure, but once a channel has as many videos as what Nick does it is not always as obvious... My memory isn't that good anymore 😂
I was hoping you would show how it handles topics.
Is there a course planned related to asynchronous communication or something similar?
There is
Would like to see an NServiceBus Video
I don't use any of those libraries. They are all very opinionated. I build simple Web API projects with Outbox pattern. I then use Change Feed to dispatch the messages (I use CosmosDb). Then on the receiving end I have a simple service that receives a message and simply makes POST http requests with the received message. Will add tiny but of latency for sure but when you use messaging you already accept the fact that you add extra latency to your applications. I can that way also test my service end to end using tools like Postman.
Love that you're highlighting Wolverine! It, and the entire Critter Stack of libraries from JasperFX are excellent.
All implementation on an async messaging pattern. My personal preference is to think through the business process, and then speak to patterns that are reliable and asynchronous. Tough to do in a short video. However, showing implementation without business context will likely mean devs will jump on this and not be prepared for the complexity of managing a distributed, multi threaded (or process) application.
I am not a fan of how the handlers simply "do stuff". It's weird. Was it based on naming or the arguments of the "Handle" method? Hmm.
A ServiceBus video would be great! It's not a great experience registering a bunch of consumers with background services e.t.c. Would be great to get your view on it all and make our daily life a bit better.
I don't think this has any functional benefits over tried and true MassTransit. Both have Sending/Publishing/Responding. MassTransit can do a lot more with Sagas. I don't like the DI Container replacement. I would never do that. I also don't like that the initialization syntax is transport-dependent. Which means I will have to re-write all my initialization syntax if I ever want to change transports (which may happen especially in early stages of a project). In MassTransit, initialization is done outside the boundaries of transport definition, which allows me to switch transports without any changes to my code.
What did you mean by "use the @ symbol to deconstruct the object"?
In structured logging, as with a logging lib like Serilog, you can "destructure" all public object properties into your log message as part of the log payload, so you don't have to manually define a message template string that provides each separate public property. Warning: This can be dangerous as you could overexpose data from your objects into your log, and accidentally log secrets or PII data, etc.
Dear Nick, Can you please create a tutorial on how to do integration testing for Generic host non-Web application eg - Background service which acts as a RabbitMQ Subscriber.
Reasoning the duct type with "having one class handling multiple messages" is not very convenient as you can achieve the same with multiple interfaces.
Forcing its own DI container stopped me right there... Sorry, I can't do it in my projects.
This is a long video. Does it support domain events that need to participate in the same transaction? Does it support Postgres as an event queue? Can it be used with Autofac?!
Deadpool & Wolverine (2024) Trailer Now Out!
So it’s like a more opinionated Rebus or even MassTransit which is a much larger framework.
It's a library, MassTransit is a framework and works very very differently. MassTransit forces you to use it in a certain way, Wolverine is much more flexible.
@@jessestruyvelt7593 Hence why I mentioned Rebus first.
@@EraYaN I see. We are using Wolverine in production, couldn’t be happier
I think that this could have been a simpler api, if you went for something like what minimal api did, but instead of MapGet() you could have SubscribeTo() and pass the DI services and the message itself. No need for separate classes unless you decide to create them. What do you think?
Is Wolverine a MassTransit killer, like Bun is Node killer?
Wolverine is a joke compared to MassTransit.
@@xRealHackerx so i said
Wolverine will definitely be slower than MassTransit due to reflection based code handlers.
@@deathrace-bx5ne Have you even investigated this? Wolverine relies heavily on code generation and actually wraps itself around your code instead of relying on reflection
The simple fact that a messaging library will replace your DI library is ridiculous. Masstransit already wins there.
I really don't like the way in which Wolverine relies upon conventions instead of contracts. To me it feels wrong, unsafe, to write code as opinionated as this. Contracts make it clear and simple what is expected and thus what should be implemented. Now, however, with Wolverine you can't rely on these tools. I know this is personal but I would dread writing code like this. It's too much "magic" which obfuscates the way in which it works which results in it being harder to read and parse. Saving the "bloat" of interfaces doesn't seem worth it to me.
So, from handler side it must be using Reflection that means performance hit. Hmmmm...
There's no Reflection at runtime in Wolverine
I hate opinionated code if it does not match my opinion
2:16 after weeks of 'we just launced..' maybe replace 'we just' with 'some time ago we'.. 🙂
this shit at 0:12 just cost me $12.49
Wolverine docs: Build clean messaging with: - Todo - Todo Todo - Todo Todo todo
Dude, there's a handful of "TODO" scattered in there in between about 75 pages full of documentation with examples everywhere. Maybe chill out a little bit on the quick criticism.
Too much magic going on behind the scenes. This will lead to debugging hell in the real-world projects.