Hangfire + MediatR = Message Dispatcher

Sdílet
Vložit
  • čas přidán 22. 05. 2024
  • You can use two popular libraries in MediatR and Hangfire to create a pretty cool solution to move messaging out-of-process into a separate worker. Here's how you can take these two libraries and use them together.
    🔔 Subscribe: / @codeopinion
    💥 Join this channel to get access to source code & demos!
    / @codeopinion
    🔥 Don't have the JOIN button? Support me on Patreon!
    / codeopinion
    📝 Blog: codeopinion.com
    👋 Twitter: / codeopinion
    ✨ LinkedIn: / dcomartin
    0:00 Intro
    0:38 MediatR Example
    1:25 Configure Hangfire
    2:27 MediatR Wrapper/Bridge
    3:20 MediatR Extension Method
    4:37 Hangfire Serialization
    8:00 Hangfire Extensibility
    9:53 Summary
    #dotnet #messaging #softwarearchitecture
  • Věda a technologie

Komentáře • 73

  • @CodeOpinion
    @CodeOpinion  Před 3 lety +29

    If you're interested in more content around using MediatR and Hangfire together let me know. There's a few different things such as event handlers, retries, timeouts and how you can deal with them. Let me know in the comments what your interested in.

    • @allannielsen4752
      @allannielsen4752 Před 3 lety +3

      This looks like a better solution that the previous Brighter demo. I'd be keen for more videos on extending this.

    • @codyspeck
      @codyspeck Před 3 lety +1

      After watching this video, I've been looking around for a way to ensure messages enqueued to Hangfire's SQL Server storage are committed in the same db transaction as my Entity Framework Core DbContext class. Do you have any insights on this?

    • @CodeOpinion
      @CodeOpinion  Před 3 lety +4

      @@codyspeck Good question! I haven't looked at this but I can see how you'd want this for something like the outbox pattern when using Hangfire. I might look into this further, stay tuned!

    • @codyspeck
      @codyspeck Před 3 lety

      @@CodeOpinion Exactly the pattern I'm trying to implement. Cheers!

    • @allannielsen4752
      @allannielsen4752 Před 2 lety

      @@CodeOpinion Any updates on this?

  • @chadox71
    @chadox71 Před 3 lety +5

    I'm binge watching your videos. Love the format, short and very informative. Thanks !

  • @jessestruyvelt7593
    @jessestruyvelt7593 Před 2 lety

    After some more trying out, I really like this approach since we are able to use both the MediatR Send or the extension method you wrote where needed to switch between in and out process.

    • @CodeOpinion
      @CodeOpinion  Před 2 lety +1

      Yup, its advantage is it the same model for in and out of process. For a lot of use cases this works pretty well.

  • @sampsonorson
    @sampsonorson Před 3 lety

    Thanks. Another great content.

  • @rainron2664
    @rainron2664 Před 3 lety +6

    Why is this channel is so underrated. 😔

    • @CodeOpinion
      @CodeOpinion  Před 3 lety

      Share! It's growing as time goes on and publish more content.

  • @alexprift2242
    @alexprift2242 Před 3 lety

    Good job Derek!!!

  • @majixx
    @majixx Před 3 lety +3

    Why do u have only 4k subs ?! Your videos are so good.. Keep it up

    • @CodeOpinion
      @CodeOpinion  Před 3 lety

      Good question! Share with your friends and co-workers! :)

  • @satyayuga0
    @satyayuga0 Před 5 měsíci

    Awesome!

  • @lost-prototype
    @lost-prototype Před 2 lety

    Very interesting!

  • @feelingeverfine
    @feelingeverfine Před 3 lety +2

    Would love more videos on this. Would you extend MediatR publish method too?

    • @CodeOpinion
      @CodeOpinion  Před 3 lety

      I have. It's a bit more involved but possible.

  • @ConradAkunga
    @ConradAkunga Před 9 měsíci +1

    Great video.
    Question - would you not get the same effect if you invoke hangfire in the MediatR handler?

    • @CodeOpinion
      @CodeOpinion  Před 9 měsíci

      You want hangfire to execute/invoke the handler or whatever code you want to run separately.

  • @Fury77_
    @Fury77_ Před 2 lety

    I have been using dependency injection using Dapper, I have tried several ways to get to my Handler using MediatR but when I run Hangfire and get to the controller I find that I must correct the problem with dependency injection. I have also tried configuring my controller by creating an additional service to go through there, but I always run into the same problem. any recommendation or help

  • @thedacian123
    @thedacian123 Před 2 lety

    I did't understand how you managed to use mediator to talk with a separate process(the worker which hosts hangfire).As fire as i know medior works only in process.I think would me more suitable a message broker for interprocesses comunications

  • @suhasbothe6407
    @suhasbothe6407 Před 2 lety +1

    how to combine recurring job and mediator pattern?

  • @velkumars26
    @velkumars26 Před 2 lety +2

    Awesome, Great article.
    I have a doubt, is there any way to run the worker project inside my API.
    I don't want to run two applications.

    • @CodeOpinion
      @CodeOpinion  Před 2 lety +1

      Yes, you can run Hangfire right along side ASP.NET Core
      docs.hangfire.io/en/latest/getting-started/aspnet-core-applications.html

    • @velkumars26
      @velkumars26 Před 2 lety

      @@CodeOpinion Thank you.
      I'm facing some weird issue like, I'm throwing "NotImplementedException" but my hangfire wasn't retry.
      Status of my job is "Succeeded"

  • @_PhOeNiX_13
    @_PhOeNiX_13 Před rokem

    Hello,
    Is it possible to share data between Hangfire jobs using this pattern ?
    Or do you know a solution to make it possible with an other way ?

  • @PedroHenrique-di8lb
    @PedroHenrique-di8lb Před rokem

    the hangfire can job with topic equals rabbit mq? in this example, when have a implementation witch listen a new Order event receive? i said this because, i need to execute anothers methods after create event new Order. can explain?

  • @noahginsburg6140
    @noahginsburg6140 Před rokem

    Is the use of MediatR relevant to hooking a CQRS implementation up to HangFire? Or is it a matter of extending whatever CQRS implementation you have to another method that moves that work out of process?"

  • @GambitVil
    @GambitVil Před 3 lety

    Thanks for video! Very helpful!
    One question. Where should be located "Handle" method for processing data and do something? I suppose that it should be inside "Handfire.Mediatr" project, am I right? So "Handfire.Mediatr" project included in "Worker" and in "AspNetCore". "AspNetCore" use it to serialize information about data and method to be called and send ti Handfire storage. And "Worker" use "Handfire.Mediatr" to deserialized record from Handfire storage and execute needed method?

    • @CodeOpinion
      @CodeOpinion  Před 3 lety +2

      Yes, Hangfire.MediatR is referenced in AspNetCore and Worker projects. The the relevant message and handlers would be in their own respective projects like Sales, Shipping, etc.

  • @feelingeverfine
    @feelingeverfine Před 3 lety +1

    What do you think on this version vs Brighter. I know you are the author of Brighter so I'm curious on your thoughts.

    • @CodeOpinion
      @CodeOpinion  Před 3 lety +1

      I'm not the author of Brighter. Ian Cooper (twitter.com/ICooper) and other contributors are who created Brighter. I just enjoy looking at different message/command processors and how they work. I wanted to illustrate how you could use Hangfire as message dispatcher and MediatR as the processor, mainly because Hangfire has a bunch of nice features out of the box like retries and failed queue.

    • @feelingeverfine
      @feelingeverfine Před 3 lety

      @@CodeOpinion ah sorry. I saw your name on the Paramore Brighter CommandStore page and thought you were one of them.

  • @xaviar7247
    @xaviar7247 Před 3 lety

    Did you abandon this concept after digging in realizing it wasn't a good approach? Just haven't seen anything along these lines since Sep 3 2020 and am trying to determine if this is still a valid approach. Also, if it is - does the worker have to depend on Hangfire.AspNetCore && Hangfire.SqlServer (this seems to be the only way for me to get it to allow the service add) && there doesn't seem to be any libraries of hangfire that I can see that combines the two into a dependency injection situation.

    • @CodeOpinion
      @CodeOpinion  Před 3 lety +2

      No it's still valid for many simple use-cases. Yes you would depend Hangfire.AspNetCore which has the IServiceCollection.AddHangfire() and IApplicationBuilder.UseHangfireServer(). You also need a package for storage, this could be Hangfire.SqlServer or others.

  • @jeremyhb1393
    @jeremyhb1393 Před rokem

    Hii , Is it good approach to use Hangfire with the EntityFrameworkCore.Triggered library to easily replicate data from the write database to the read database whenever there are changes.
    What are your thoughts on this approach? Do you think it's a good idea or are there any potential issues we should be aware of?

    • @CodeOpinion
      @CodeOpinion  Před rokem

      Never heard of that library, I'll have to check it out.

    • @jeremyhb1393
      @jeremyhb1393 Před rokem

      @@CodeOpinion This library allows you to easily add triggers to your database operations, similar to how triggers work in a traditional SQL database. These triggers can perform additional actions, such as updating related records, when certain conditions are met, making it easier to maintain data integrity and enforce business rules.

  • @avineshwar
    @avineshwar Před 2 lety

    At first, Postman showed "842ms". So, is that a lot of latency (say, by-product of process level indirection, or rather MVC?)?. It will be helpful if you could give some insights on improving on that front should be equally in part due to the use of MediatR, etc.
    Of course, this will only increase from what it looks (though, benefits outweigh given the "pre implement" latency)?.
    Overall, feels like a bit too much for achieving something which should be available in the language with relative simplicity?.

    • @mekowgli
      @mekowgli Před rokem

      That's because it was the first call. It's .NET so it uses JIT compilation (IL into machine code, when you execute a path in the program). Subsequent requests would probably be 2 orders of magnitude faster.

  • @kamarchand
    @kamarchand Před 2 lety +1

    Hi, How do you get back to the CreateShippingLabel with this code? I never reach the Inotification point entry? thanks

    • @jessestruyvelt7593
      @jessestruyvelt7593 Před 2 lety

      I was wondering as well. I read through the comments and Derek seemed to have tried out the MediatR Publish as well. Since he used the Send method instead of Publish it will never reach that code. Was considering this approach as well but can't seem to figure out if the Hangfire+MediatR publish could be a substitute to NServiceBus/CAP or similar packages. Hopefully Derek can shed some light on this!

    • @jessestruyvelt7593
      @jessestruyvelt7593 Před 2 lety

      After some searching.. some comments below by "Gabriel B" shows the exact answer of what we wanted to know :)

    • @CodeOpinion
      @CodeOpinion  Před 2 lety +1

      You would need to know the mapping between the Event and the Consumer Handlers so you could create a hangfire job for each handler type. Then for each job, have it resolve/create that specific handler and invoke it.

  • @clashclan4739
    @clashclan4739 Před rokem

    Can i run hangfire completely different machine or container in kubernetes? Will it work 🤔

    • @CodeOpinion
      @CodeOpinion  Před rokem

      Yes

    • @clashclan4739
      @clashclan4739 Před rokem

      @@CodeOpinion yes tested that but its not an efficient way to use hang fire. Better option is rabbitmq

  • @ersenbasaransen2665
    @ersenbasaransen2665 Před rokem

    Hi, nice. But!
    Why do we code all these bridge and extensions staff but not call the mediator Send as below? In the end we can switch out of process like this. What is the benefit or difference?
    BackgroundJob.Enqueue(m => m.Send());
    public interface IMyJob
    {
    [DisplayName("My Job")]
    Task Send();
    }
    public class MyJob : IMyJob
    {
    private readonly ISender _mediator;
    public MyJob(ISender mediator)
    {
    _mediator = mediator;
    }
    public async Task Send()
    {
    await _mediator.Send(new MyRequest());
    }
    }

  • @gabrielbarriost
    @gabrielbarriost Před 3 lety

    Dumb question, what's the difference from this method versus mediatr.Publish, other than the persistance and the retry mechanism?

    • @CodeOpinion
      @CodeOpinion  Před 3 lety +1

      Publish is for publishing an event/notification. Which may have zero or many handlers. All of them are done in-process when you call Publish. Meaning if one event handler throws an exception it will bubble up to where you call Publish. Using Hangfire jobs to process the handlers make them independent and execute in isolation out of process.

    • @gabrielbarriost
      @gabrielbarriost Před 3 lety

      @@CodeOpinion thanks, I really liked this approach, is way way better than having to publish another event!

    • @coderanger75
      @coderanger75 Před 3 lety

      @@CodeOpinion Great content -- thank you! How would you extend what you have learned here to Publish an event using MediatR but ensure that the zero to many published event handlers are enqueued and processed out-of-process with Hangfire?

    • @CodeOpinion
      @CodeOpinion  Před 3 lety +1

      @@coderanger75 Yes you could do the same thing for event handlers. You would need to means to know which event handlers exist for an event at publish time (using reflection or some mapping), then enqueue a job for each event handler. You would then need to extend MediatR to execute an event handler for an event individually that was the job in Hangfire.

    • @coderanger75
      @coderanger75 Před 3 lety

      @@CodeOpinion I greatly appreciate the advice! Can't wait to try this out today.

  • @joycalcutta
    @joycalcutta Před 3 lety

    Hangfire + MediatR vs Brighter -->what's your opinion?

    • @CodeOpinion
      @CodeOpinion  Před 3 lety

      Hangfire is awesome. Adding MediatR to the mix is just a way to add a command pattern to the mix instead of Hangfires built in way of performing background jobs. Brighter by design does this plus a bunch of things you will have to implement manually with a Hangfire + MediatR setup (such as custom retry logic, outbox pattern, etc).

    • @joycalcutta
      @joycalcutta Před 3 lety

      @@CodeOpinion Thanks for quick reply. Looks like it takes a lot of boiler plate code to implement hangfire + mediatr compared to brighter. Other than that, any suggestions on which one to choose for production scenario? The setup pretty much is similar to python+celery+rabbitmq/others.

  • @srik790
    @srik790 Před 3 lety +1

    Where can I find the source code?

    • @CodeOpinion
      @CodeOpinion  Před 3 lety +2

      github.com/dcomartin/LooselyCoupledMonolith/tree/HangfireMediatR

    • @srik790
      @srik790 Před 3 lety

      @@CodeOpinion please also cover saga and distributed transaction.. also in above example... Doest it mean we can use hangfire instead of Rabbitmq to publish our integration events...

    • @srik790
      @srik790 Před 3 lety

      @@CodeOpinion got the answer for second part i.e Rabbitmq in your comments.. thanks...
      Also waiting for saga and distributed transaction... Thanks in advance

  • @SwampyFox
    @SwampyFox Před 3 lety

    Is the code available?

    • @CodeOpinion
      @CodeOpinion  Před 3 lety

      Sorry, should of included it in the description.
      github.com/dcomartin/LooselyCoupledMonolith/tree/HangfireMediatR

    • @SwampyFox
      @SwampyFox Před 3 lety

      @@CodeOpinion Thanks - Just looking over the code I think I just got the idea of bounded contexts! I do have a question about this video and if you have had this in your experience of using Mediatr, Hangfire and DbContext...specifically with the dreaded "Second operation started on this context before a previous completed?" This happened in my setup and I think I gave up.

    • @CodeOpinion
      @CodeOpinion  Před 3 lety +1

      @@SwampyFox So this is because the DbContext is probably Scoped at the root level DI service provider so you have the same DbContext being used between different handlers that are running concurrently. I'll try and replicate and fix it in my code sample.