Base solution for your next web application
Open Closed

hangfire integration #591


User avatar
0
apexdodge created

The problem with Hangfire is with Castle Windsor (or any IoC for that matter). When you run a background task from something like the Services layer, the background task does not have HttpContext and so an exception is thrown.

See:

<a class="postlink" href="http://docs.hangfire.io/en/latest/background-methods/using-ioc-containers.html">http://docs.hangfire.io/en/latest/backg ... iners.html</a>

I tried messing around with it, but not having any luck.

Ideally, I achieve something like this:

private readonly ISearchAppService _searchAppService;

        public CronController(
            ISearchAppService searchAppService)
        {
            _searchAppService = searchAppService;
        }

        public JsonResult InitiateRecurringIndex()
        {
            RecurringJob.AddOrUpdate("nightly-index", () => _searchAppService.DestroyAndCreateArticlesIndex(), Cron.Daily);
            return Json(new { }, JsonRequestBehavior.AllowGet);
        }

Has anyone here figured out how to get Hangfire, Castle Windsor, and ABP to work nicely with each other?

Thanks


14 Answer(s)
  • User Avatar
    0
    hikalkan created
    Support Team

    Hi,

    It's normal to not have HttpContext. Also, ne need to it as you say. I think these can be problems:

    • Your background job should use dependency injection. It can itself be created via DI or it can use IocManager.Instance.Resolve to get a service from DI.
    • You should not use an app service from a background job since app services are designed to be used by UI. You can move DestroyAndCreateArticlesIndex to a domain service (Also, if you add DestroyAndCreateArticlesIndex to app service, it becomes usable by clients which can be a security problem. But if you need it in UI too, you can use same domain service from your app service).
  • User Avatar
    0
    ardrian created

    Hi,

    What would be the best way of implementing an application which was used specifically to run background jobs, but also took advantage of the ABP framework. (i.e. DI, logging etc).

    Ideally I would like to create a background job, which will be run as a separate application (not the main ASP.NET MVC application). When it starts, it will have access to the same DB through EF.

    From your post above, I understand that I should only be using classes which inherit from the {SolutionName}DomainServiceBase class (defined in the Core layer), and not anything from the Application layer (inheriting from {SolutionName}AppServiceBaseclass)?

    Should I be implementing a class in a new project which inherits from the AbpModule class? Thanks

  • User Avatar
    0
    ardrian created

    Ok it looks like I should follow this guide:

    <a class="postlink" href="http://www.aspnetboilerplate.com/Pages/Documents/Module-System">http://www.aspnetboilerplate.com/Pages/ ... ule-System</a>

    In order to create a new module, which uses the ABP infrastructure. Is this the right thinking?

  • User Avatar
    0
    hikalkan created
    Support Team

    I understand that you need such a background Windows service. And you want that your Windows service is based on ABP and can use your project's domain layer. If so, that's the right way and easy to accomplish.

    There is no Windows Service sample yet, but a Windows Service is similar to a Console application. You can check console application samples (<a class="postlink" href="https://github.com/aspnetboilerplate/aspnetboilerplate-samples/tree/master/SimpleTaskSystem/SimpleTaskSystem.ConsoleApp">https://github.com/aspnetboilerplate/as ... ConsoleApp</a> or <a class="postlink" href="https://github.com/aspnetboilerplate/aspnetboilerplate-samples/tree/master/AbpEfConsoleApp">https://github.com/aspnetboilerplate/as ... ConsoleApp</a>) and create a windows service.

  • User Avatar
    0
    ardrian created

    This example is exactly what I was after. Thanks!

  • User Avatar
    0
    john_kattenhorn created

    We've been using Hangfire with ABP for a while now and it took a while to figure out the Castle Windsor issues but it works fine now.

    We use it as a WebJob in Azure as we didn't want to affect the performance of App whilst the jobs was running.

    Let me know if you want us to share some code and I'll see what I can do.

  • User Avatar
    0
    john_kattenhorn created

    We've been using Hangfire with ABP for a while now and it took a while to figure out the Castle Windsor issues but it works fine now.

    We use it as a WebJob in Azure as we didn't want to affect the performance of App whilst the jobs was running but it's actually a Console App.

    Let me know if you want us to share some code and I'll see what I can do.

  • User Avatar
    0
    ardrian created

    Hey John,

    If you could share any example code of your console app (with any proprietary code stripped out), that would be fantastic. I appreciate that you might not be able to do this, but if you could that would be great.

    Just knowing that you have implemented this as a console which runs as an Azure Webjob is a great start, as that was the arrangement I had in mind.

  • User Avatar
    0
    guillaumemorin created

    I'm also interested if you can share this code.

  • User Avatar
    0
    apexdodge created

    Would love to see your sample code.

    I only got Hangfire working by creating a Static Class and manually invoking IocResolver. It's not pretty and not the way I wanted to accomplish it in my original post, but it works. I can share that solution here if anyone is interested as well.

    On a side note, even with my above solution, Hangfire isn't working with Lazy Loading in EntityFramework. I had to write my own Repository and create a method that pulls data in an eager fashion.

    I did not anticipate so much headache considering how 'easy' the hangfire.io website makes it look in getting started haha.

  • User Avatar
    0
    ardrian created

    Would love to see your sample as well.

    In the past I haven't had problems getting Hangfire to work in a non-ASP.NET Boilerplate solution (just a normal ASP.NET setup), however I haven't had any luck thusfar combining the two.

    Using separate web-jobs and avoiding Hangfire has been the workaround so far.

  • User Avatar
    0
    apexdodge created

    Sure thing. I created a file in my .Web project called BackgroundTaskFactory.cs. It's just a static class where each function would wrap the calling of a service layer function. In the case below, I have SearchAppService and I want to call its DestroyAndCreateArticlesIndex().

    public static class BackgroundTaskExecuter
        {
            public static void DestroyAndCreateArticlesIndex()
            {
                using (var service = IocManager.Instance.ResolveAsDisposable<SearchAppService>())
                {
                    service.Object.DestroyAndCreateArticlesIndex();
                }
            }
        }
    

    Then to use it, I call

    BackgroundJob.Enqueue(() => BackgroundTaskExecuter.DestroyAndCreateArticlesIndex());
    
  • User Avatar
    0
    tav created

    Is there a way to view all the sagas in a view? i.e. how do you know the health of the background services.

  • User Avatar
    0
    apexdodge created

    Yeah, hangfire provides you with a live dashboard at <a class="postlink" href="http://">http://</a><your-site>/hangfire

    <a class="postlink" href="http://hangfirechinese.readthedocs.org/en/latest/quick-start.html">http://hangfirechinese.readthedocs.org/ ... start.html</a>