Thank you for the video, Milan! From the asynchrony perspective I think that nothing has changed between using INotification and IEventBus. You couldn't make your code MORE asynchronous. Even in the second approach you were still using await and returned response to the client only after the method for publishing was awaited on. So you're not making your program work any different if we consider only asynchrony - you still use the same threadpool mechanism. What you should have pointed out in your video is that you've enforced decoupling between the party that publishes and the party that processes event messages.
What is the difference between a Websocket API, and a REST API when working with C# and how do set one up? Can you use a REST architecture on top of the Websocket API? Maybe you can make a video covering some flavor of these questions.
@@bobek8030there's no CPU load as there's no wait state for the CPU; when items are written to the channel, (task based) readers are notified by means of queuing tasks on the threadpool. It effectively releases the iterating thread to do other tasks until the channel is asking for work to be processed. You should (very high level) think of channels as a high level producer/consumer API around task queues.
@@MilanJovanovicTech Because you publish a WorkoutRemovedIntegrationEvent object but instantiate a Channel of IIntegrationEvent so in the background service, reading from the Channel, we have access only to the property of IIntegrationEvent and not the WorkoutId property of WorkoutRemovedIntegrationEvent
I think that you incorrectly use word asynchronous. Your first publish was asynchronous. The job was taken out of IO thread. I think you should saythat task is not parallel
If nobody subscribes to the events, there will be be a memory leak P.S. - better to create channels on the subscription to the the events, and if no subscription then to drop messages
@@MilanJovanovicTech That's about the maintenance of a project. Sombody will remove a subscription because it is not needed anymore, and forget to remove the publishing.
Когда я увидел публикацию, то подумал, что увижу что-то родное. Но опять же этот MediatR, его нельзя использовать в проектах со слишком большим количеством сущностей, он добавляет совершенно ненужную сложность восприятию проекта и его отладке
Медиатр в этом примере - всего лишь средство для достижения цели. Я использовал его только для того, чтобы упростить публикацию событий. При желании вы можете реализовать все с нуля. Извините, если по-русски неправильно - это вина Google Translate. С уважением!
Сложности он явно не добавляет, даже сказал бы, особенно в большом проекте. Посмотри в сторону Vertical Slice архитектуры (или ее подобия), если у вас файлики разбросаны по всему проекту. Чтобы повысить функциональный cohesion. У Milan был недавно видео на эту тему :)
Want to master Clean Architecture? Go here: bit.ly/3PupkOJ
Want to unlock Modular Monoliths? Go here: bit.ly/3SXlzSt
If you only knew how timely this was for me to find by accident after watching some of your other videos. Thanks!
Awesome, glad to hear it 😁
Great work Milan. Very well explaned with a good real-world scenario
Thanks!
Nice approach using the Channels feature. 👍🏻
Thanks :)
Also, the reader/writer pattern is often referred to as the producer/consumer pattern. It would be so nice to have transactional memory ..
A man can dream
whats the benefit of using the abstract class implementing the interface for the integration event ínstead of just using the interface?
The implementing class only needs to define its own fields (without implementing the interface)
I didn't know channels, it is a very amazing but unknown feature!
Glad you learned about it :)
Thanks for sharing this ....Hope it will all be covered in clean architecture course i purchased
This one not in particular (you can see the whole curriculum), but you'll see an elegant Outbox implementation
Thank you for the video, Milan! From the asynchrony perspective I think that nothing has changed between using INotification and IEventBus. You couldn't make your code MORE asynchronous. Even in the second approach you were still using await and returned response to the client only after the method for publishing was awaited on. So you're not making your program work any different if we consider only asynchrony - you still use the same threadpool mechanism. What you should have pointed out in your video is that you've enforced decoupling between the party that publishes and the party that processes event messages.
"you've enforced decoupling between the party that publishes and the party that processes event messages." - which is what I mean by asynchronous here
What is the difference between a Websocket API, and a REST API when working with C# and how do set one up? Can you use a REST architecture on top of the Websocket API? Maybe you can make a video covering some flavor of these questions.
learn.microsoft.com/en-us/aspnet/core/fundamentals/websockets
Great Milan, how would you do an integrated test on a background service that consumes messages from the servicebus?
Wait X time in the test, and check for the consequences
@@MilanJovanovicTech Precisely, test processing time. I'm going through this.
why there is no need to have while loop inside background task?
Because the Task doesn't complete
@@MilanJovanovicTech what about cpu load in this approach? isnt it like while true loop without task.delay?
@@bobek8030there's no CPU load as there's no wait state for the CPU; when items are written to the channel, (task based) readers are notified by means of queuing tasks on the threadpool. It effectively releases the iterating thread to do other tasks until the channel is asking for work to be processed. You should (very high level) think of channels as a high level producer/consumer API around task queues.
Great video
Thanks!
Thanks ,Why don't you add the githup repo?
I share the code on Patreon, but you can find most of it here: www.milanjovanovic.tech/blog/lightweight-in-memory-message-bus-using-dotnet-channels
Thanks again
Always welcome
Maybe the InMemeoryMessageQueue class should be generic to be able to get the WorkoutId from the Reader of the channel
Why is that necessary?
@@MilanJovanovicTech Because you publish a WorkoutRemovedIntegrationEvent object but instantiate a Channel of IIntegrationEvent so in the background service, reading from the Channel, we have access only to the property of IIntegrationEvent and not the WorkoutId property of WorkoutRemovedIntegrationEvent
I think bounded channel is 'limited capacity', limited with the number of items it can hold.
Yep
At ruclips.net/video/gox065POif4/видео.htmlruclips.net/video/gox065POif4/видео.html, could you explain why the implementation is not reliable?
Simply because it works IN MEMORY only. If your app crashes, or there's an exception, the message is lost and you don't have a way to recover it.
I think that you incorrectly use word asynchronous. Your first publish was asynchronous. The job was taken out of IO thread. I think you should saythat task is not parallel
Is MediatR Publish IO or CPU heavy? It doesn't really do any IO last time I checked. The notification handler might, but that's a different thing.
If nobody subscribes to the events, there will be be a memory leak
P.S. - better to create channels on the subscription to the the events, and if no subscription then to drop messages
That's true, but if this is an in-memory pub-sub model, why would you a publish a message that you don't want to handle?
@@MilanJovanovicTech That's about the maintenance of a project. Sombody will remove a subscription because it is not needed anymore, and forget to remove the publishing.
you're ripping
I first read this as "you're tripping" 😁
Когда я увидел публикацию, то подумал, что увижу что-то родное. Но опять же этот MediatR, его нельзя использовать в проектах со слишком большим количеством сущностей, он добавляет совершенно ненужную сложность восприятию проекта и его отладке
Mediatr это больше про DDD и чистую архитектуру. Идею шины (bus) и Thread channel можно использовать и в громадном монолите.
Медиатр в этом примере - всего лишь средство для достижения цели. Я использовал его только для того, чтобы упростить публикацию событий. При желании вы можете реализовать все с нуля. Извините, если по-русски неправильно - это вина Google Translate. С уважением!
@@ANTONZUBAREV Какое отношение имеет mediatr к DDD и чистой архитектуре?
Ни там ни там нет упоминания про него. Это просто инструмент.
Сложности он явно не добавляет, даже сказал бы, особенно в большом проекте.
Посмотри в сторону Vertical Slice архитектуры (или ее подобия), если у вас файлики разбросаны по всему проекту. Чтобы повысить функциональный cohesion.
У Milan был недавно видео на эту тему :)
@@MilanJovanovicTech No apologies or respect for the ᵣussians...