Hi there, is it possible to use another database instance for recurring jobs to save outbox messages records instead of reading/persisting the current database in order to decrease latency from API requests?
Thanks for the video ! I have already implemented the outbox pattern but following your other video using Quartz. I have a question about the outbox implementation for domain events in general: Would it make sense to save in the database just the failed domain events? I mean, we could send the domain events right away after saving the changes and if some handler fails to handle the event, we could save the necessary info for later retry of that specific event and handler.
That could increase the latency of the original request. And we'd be publishing the events twice, so we have to start thinking about duplicating some side effects
Thanks Milan ❤ You have already implemented it using Quartz. What do u think which one is better between of these? Could plz make any video on ef core migration and which approach should to use between code first and db first?
| What do u think which one is better between of these? I slightly prefer Quartz for recurring jobs, as I find it easier to configure. I like Hangfire for on-demand background jobs, though. | ef core migration and which approach should to use between code first and db first? Yes, planning to make one!
Hangfire console add on makes it even more attractive then quartz if you need a UI for your jobs as it will render realtime logging information
5 หลายเดือนก่อน +1
Almost all popular databases provide functionality for getting triggers when data was changed. We could use such triggers for outbox processing. Instead of the background process, we get notifications on new events.
How would you retrigger a retrigger in case you fail to process it?
5 หลายเดือนก่อน
@@MilanJovanovicTech Just forward it to a message bus and use queue retries on failing. Also then you can add it to a database table to implement inbox pattern and allow quickly accept events from the bus. The key is both outbox and inbox can be implemented using polling or by change detection capture (CDC)
Great video Milan. What do you suggest to use when I have multi-tenant application using Finbuckle Multitenant? I cannot configure hangfire storage on Startup as I get the actual tenant and its connectionstring in httpcontext.
Recently I discovered your channel and learn a lot thanks to your videos. With this video in particular I have a question of the use case of the outbox pattern. For example, if you are building a real-time application let’s say a twitter clone and you send a retweet to a post, once the retweet has been processed for a command then dispatch an event to notify the clients of the numbers of retweets had increased. This example can be archived with MediatR and HangFire? This could be a valid example of the use cases of the outbox pattern?
We could definitely use it like this. But Outbox also introduces lag. With real-time applications such as social networks we may want to consider a different approach. On the other side, a few seconds of lag from user action to clients finding out may not be an issue.
A question: How can I know which tenant to take to execute a background job (I have a method that brings the dates of upcoming maintenance for a vehicle); when it is raised in background job the tenant comes out in null, how can I enter the tenant? It is an onion architecture. thanks
While Hangfire is a cool library I would implement this OutBox messages processing using Background Service with Periodic timer and won't bother about concurrent executions
@@MilanJovanovicTech simple and reliable, you can have resiliency with Polly with retries, everything that you can come up with. In this case, scheduling library doesn't add any value. First, you can't miss an outbox message scan with my approach. Second, when you restart the app, the background job will trigger. It's not a criticism but another point of view. I would use scheduling library if I have tasks that occur everyday, every few days or every few hours. But not in the case of scanning database for outbox messages every few seconds/minutes
Thanks for the great video. It would be interesting to look at how to correctly implement jobs that should be launched after some time from business logic. For example, after my entity is created in the handler in my business logic, I need this entity to change after a day (for example, the status has changed so that it is considered overdue).
Hey there! I assume using SKIP LOCKED gives no ordering guarantees and should be used when ordering doesnt matter. I would say either use a database level lock in a distributed systems or just split those outbox messages to different tables based on some specific type. Please correct me if im wrong. Nonetheless, good content :)
@@MilanJovanovicTech thanks for the response, please clarify further does this mean I shouldn't use efcore with Hangfire as it won't handle concurrency issues, or is there a way I can use it safely.
What do you think of Pros and Cons of using OutBox Pattern using MassTransit. I have used the word "using" since its already implemented in MassTransit. In which scenarios one would use MassTransit for outbox and cases Hangfire like in this video ?
@@masterdimar Its because once he started a transaction, you cant commit for every operation. Once one commit has been done, if you try to commit again an error will be thrown.
@@MilanJovanovicTech You can do the same without applying too many configurations, also to use the hangfire UI console it require to be authenticate and maybe with some privileges as well, yet hangfire is very nice, useful and worth to give a try.
I love hangfire and using it. But it is an overkill for an outbox processor. It could be easily done with IHostedService and there will never be concurrency issue. Hangfire shines most when we don't not know when to trigger the job at design time, such as sending a welcome email in bg when a new user is registered to the system. Btw. Thanks for the video, excellent job.
But the application instance itself may die, then we will lose everything that was in the background And if there are many instances of the same application, then IHostedService is especially not suitable Correct me if I'm wrong.
@@ВладиславРудаков-е4з 1 - There is nothing to lose, this outbox messages are already persisted in db before. We just fetch them, publish them and update their state to "Processed". So you won't loose anything in case of application failure. You might just republish same event after application restart but that's the same case with Hangfire, no difference. 2 - The same concern applies alsp when using Hangfire, no difference again. It is wiser that you run all background related things in a separate app, process regardless of how much webapi instance you have. Of course, you should configure a single app to be hangfire server also, not every instances
Thanks for the evidences. I will know for the future videos that the ideas behind them is your! Your are one of my favourite content creators and I wish you much success
Want to master Clean Architecture? Go here: bit.ly/3PupkOJ
Want to unlock Modular Monoliths? Go here: bit.ly/3SXlzSt
Hi there, is it possible to use another database instance for recurring jobs to save outbox messages records instead of reading/persisting the current database in order to decrease latency from API requests?
Yes
Thanks for the video ! I have already implemented the outbox pattern but following your other video using Quartz. I have a question about the outbox implementation for domain events in general:
Would it make sense to save in the database just the failed domain events? I mean, we could send the domain events right away after saving the changes and if some handler fails to handle the event, we could save the necessary info for later retry of that specific event and handler.
That could increase the latency of the original request. And we'd be publishing the events twice, so we have to start thinking about duplicating some side effects
Great video! But doesn't Hangfire have a DisableConcurrentExecution attribute you can use instead of database locks?
Which also uses locks: github.com/HangfireIO/Hangfire/blob/main/src/Hangfire.Core/DisableConcurrentExecutionAttribute.cs#L51
Thanks Milan ❤
You have already implemented it using Quartz. What do u think which one is better between of these?
Could plz make any video on ef core migration and which approach should to use between code first and db first?
| What do u think which one is better between of these?
I slightly prefer Quartz for recurring jobs, as I find it easier to configure. I like Hangfire for on-demand background jobs, though.
| ef core migration and which approach should to use between code first and db first?
Yes, planning to make one!
Hangfire console add on makes it even more attractive then quartz if you need a UI for your jobs as it will render realtime logging information
Almost all popular databases provide functionality for getting triggers when data was changed. We could use such triggers for outbox processing. Instead of the background process, we get notifications on new events.
How would you retrigger a retrigger in case you fail to process it?
@@MilanJovanovicTech Just forward it to a message bus and use queue retries on failing. Also then you can add it to a database table to implement inbox pattern and allow quickly accept events from the bus. The key is both outbox and inbox can be implemented using polling or by change detection capture (CDC)
Great video Milan.
What do you suggest to use when I have multi-tenant application using Finbuckle Multitenant? I cannot configure hangfire storage on Startup as I get the actual tenant and its connectionstring in httpcontext.
Haven't worked with Funbuckle at all
Recently I discovered your channel and learn a lot thanks to your videos.
With this video in particular I have a question of the use case of the outbox pattern.
For example, if you are building a real-time application let’s say a twitter clone and you send a retweet to a post, once the retweet has been processed for a command then dispatch an event to notify the clients of the numbers of retweets had increased.
This example can be archived with MediatR and HangFire?
This could be a valid example of the use cases of the outbox pattern?
We could definitely use it like this. But Outbox also introduces lag. With real-time applications such as social networks we may want to consider a different approach. On the other side, a few seconds of lag from user action to clients finding out may not be an issue.
A question: How can I know which tenant to take to execute a background job (I have a method that brings the dates of upcoming maintenance for a vehicle); when it is raised in background job the tenant comes out in null, how can I enter the tenant? It is an onion architecture. thanks
Pass the tenant as the Job argument
While Hangfire is a cool library I would implement this OutBox messages processing using Background Service with Periodic timer and won't bother about concurrent executions
I think that's too simplistic. I'd want something more robust. But if it works, it works.
@@MilanJovanovicTech simple and reliable, you can have resiliency with Polly with retries, everything that you can come up with. In this case, scheduling library doesn't add any value. First, you can't miss an outbox message scan with my approach. Second, when you restart the app, the background job will trigger.
It's not a criticism but another point of view. I would use scheduling library if I have tasks that occur everyday, every few days or every few hours. But not in the case of scanning database for outbox messages every few seconds/minutes
If your app is running on a multi node cluster how are you accounting for concurrent execution?
Thanks for the great video.
It would be interesting to look at how to correctly implement jobs that should be launched after some time from business logic.
For example, after my entity is created in the handler in my business logic, I need this entity to change after a day (for example, the status has changed so that it is considered overdue).
Hangfire let's you schedule delayed jobs, so that's an avenue I would explore
Hey there!
I assume using SKIP LOCKED gives no ordering guarantees and should be used when ordering doesnt matter.
I would say either use a database level lock in a distributed systems or just split those outbox messages to different tables based on some specific type.
Please correct me if im wrong.
Nonetheless, good content :)
SKIP LOCKED should respect the ORDER BY clause
If you were using EFCore would you have needed to lock any rows or would EFCore do that automatically
No, EF Core doesn't do locking
@@MilanJovanovicTech thanks for the response, please clarify further does this mean I shouldn't use efcore with Hangfire as it won't handle concurrency issues, or is there a way I can use it safely.
instead of using a lock, will rabbit mq be used instead to ensure a record is not processed twice?
There's two problems to solve - not publishing twice, and not consuming twice
What do you think of Pros and Cons of using OutBox Pattern using MassTransit. I have used the word "using" since its already implemented in MassTransit. In which scenarios one would use MassTransit for outbox and cases Hangfire like in this video ?
I need to dedicate some time to talk about that! Thanks for the reminder :)
Would you like to make a video how to register service in DI using static functional approach by features?
Perhaps this? th-cam.com/video/tKEF6xaeoig/w-d-xo.html
Can we use system.text to decode the outbox messages?
Yes, but it's limited for serializing so I just use Newtonsoft
Why you put the commit outside the foreach? Why not in every message?
You commit the transaction once
@@MilanJovanovicTech yes, but i want to understantd why you are commiting once all the message from the foreach were sent and not for every message
@@masterdimar Its because once he started a transaction, you cant commit for every operation. Once one commit has been done, if you try to commit again an error will be thrown.
Hangfire is a powerful library, but i prefer to use azure function timer
Why?
@@MilanJovanovicTech You can do the same without applying too many configurations, also to use the hangfire UI console it require to be authenticate and maybe with some privileges as well, yet hangfire is very nice, useful and worth to give a try.
SKIP LOCKED should be the default behavior. It doesn't make sense to lock ALL rows in the table if you are selecting just a few.
It doesn't lock ALL rows, just the ones you select in that query.
If you're doing a SELECT without a WHERE statement, well, that's on you...
Hangfire, Quartz for that simple task? :)
I prefer Quartz for recurring jobs
great video tho
Thanks! :)
I love hangfire and using it. But it is an overkill for an outbox processor. It could be easily done with IHostedService and there will never be concurrency issue. Hangfire shines most when we don't not know when to trigger the job at design time, such as sending a welcome email in bg when a new user is registered to the system.
Btw. Thanks for the video, excellent job.
But the application instance itself may die, then we will lose everything that was in the background
And if there are many instances of the same application, then IHostedService is especially not suitable
Correct me if I'm wrong.
@@ВладиславРудаков-е4з
1 - There is nothing to lose, this outbox messages are already persisted in db before. We just fetch them, publish them and update their state to "Processed". So you won't loose anything in case of application failure. You might just republish same event after application restart but that's the same case with Hangfire, no difference.
2 - The same concern applies alsp when using Hangfire, no difference again. It is wiser that you run all background related things in a separate app, process regardless of how much webapi instance you have. Of course, you should configure a single app to be hangfire server also, not every instances
I still consider Hangfire a general-purpose background job scheduling tool
Interesting video! But is it a coincidence that Nick Chapsas recently uploaded a video about HangFire ?
*Checks notes*: recorded this on February 21st... Can post proof 😁
Heads up, also recorded an OpenTelemetry video with Aspire Dashboard back in February... That's coming out next week 😁
And you can also clearly see logs in the video dated to February 21st: prnt.sc/2rERFH6aqXRq
Thanks for the evidences. I will know for the future videos that the ideas behind them is your! Your are one of my favourite content creators and I wish you much success