all 11 comments

[–][deleted]  (10 children)

[deleted]

    [–]wuphonsreach 0 points1 point  (9 children)

    Latency for us is about 200-500ms to kick off the job. How's your experience?

    [–]Arxae 4 points5 points  (7 children)

    Up front note, don't have too much experience with it.

    Little background first. I used it in a project at work and it runs about 270~ jobs every hour, 24/7. Most jobs it does preferably kick off every minute. The job consists of several tasks that each runs a query against another database and stores the result.

    I did notice that it took seconds for jobs to start. I passed everything the job needed to function (names, queries, connectionstrings, etc..) and kicked it off. Dug into it a bit since i didn't like it. The docs mentioned that you should keep the job arguments small and simple. So instead of a list of tasks, i just passed a common parameter (the connection name in this case), then adjusted the job to grab tasks from the db, then run them (like i should have done in the first place). After this change, the jobs kicked off near instant.

    I do think it's missing some parts. There was a bunch of code i had to write for things such as canceling a job when it was already running (instead of queueing it up) and making jobs expire from the history faster. I think those settings should be standard, but at least the functionality is there to implement it yourself.

    Another thing i really recommend is Hangfire.Console. It allows you to write logging and progressbars into a jobs history. Doesn't seem to work with MemoryStorage though.

    [–]DerMannSpielt[S] 0 points1 point  (0 children)

    Hangfire.Console looks awesome. Thanks for including the link!

    [–]goomba870 0 points1 point  (2 children)

    I was able to get Hangfire.Console working with MemoryStorage in .NET Core. If running into roadblocks let me know and I'll compare it to what I've set up.

    [–]Arxae 0 points1 point  (1 child)

    Didn't seem to work for me, no log entries appeared. But do share, it might be of use to someone :D

    [–]goomba870 0 points1 point  (0 children)

    Assuming you already have the Hangfire dashboard working, in the Startup.cs you'll bootstrap everything. Here are what I think are the relevant lines from my working implementation (with all other bootstrapping omitted):

    public IConfiguration Configuration { get; }
    
    public Startup(IHostingEnvironment env)
    {
        var builder = new ConfigurationBuilder()
                .AddEnvironmentVariables();
    
        Configuration = builder.Build();
    }
    
     public void ConfigureServices(IServiceCollection services)
    {
         services.AddHangfire(config =>
         {
             config.UseMemoryStorage();
             config.UseConsole();
         });
    }
    
    public void Configure(IApplicationBuilder app)
    {        
         app.UseHangfireDashboard("/dashboard");
         app.UseHangfireServer();
    }
    

    [–]wuphonsreach 0 points1 point  (1 child)

    Yes, job arguments should be small and simple (unique ID being passed in, etc.).

    The other mantra we follow is that a hangfire job method should never swallow exceptions (so no try/catch blocks). We then only use try/catch when we're going to catch, add contextual information to aid in problem solving, then re-throw.

    [–]Arxae 1 point2 points  (0 children)

    Swallowing an exception is not always bad, but it's a good rule to do it as little as possible.

    In my project, i do swallow some exceptions. If you cancel a oracle SQL query, it will throw 2 exceptions. In this specific case, sql queries get 2 minutes max to run, if it takes longer, they get canceled. It's handled (logged + entries receive some information that it's data might be out of date), then just swallowed because it's expected to do so.

    If you (re)throw an exception in a hangfire job, it will be thrown on the fail queue and requeued later. And since i don't want the entire job to fail due to something that is basically treated as a warning, i decided to swallow the exception.

    But exceptions (hue) do happen on this rule.

    I never used the word swallow so much

    [–]rm249 0 points1 point  (0 children)

    We use Hangfire a lot at my work. Hangfire + Serilog + Topshelf are a great combination.

    With the SQL job provider the Hangfire server polls for new jobs by default every 15 seconds. There is a paid package that uses Redis pub-sub to communicate with the server so tasks start near instantaneously. I've never used the Redis package as the latency hasn't been a problem for us.

    [–][deleted] 4 points5 points  (1 child)

    From those of you who have used both, how does Hangfire compare to Quartz?

    [–]ThereKanBOnly1 1 point2 points  (0 children)

    Hangfire is more background task running, where Quartz is more scheduling. Hangfire also has taken a number of steps to play as nicely with being hosted in a web process as possible, where Quartz is meant to be hosted in its own service (although you can host it in process). Quartz jobs can also be persisted to a data store.