Hangfire background job remain enqueued
Asked Answered
H

4

8

I have a MVC application and I am trying to send an email using Hangfire and Postal. The email must be sent after a registration. The registration works properly, but the job I run remain enqueued and I not receive any email. So in my MVC controller I have the following code:

public async Task<ActionResult> Register(RegisterViewModel model)
{
    //register correctly the user

    //I send the email
    BackgroundJob.Enqueue(() => 
        NotifyRegistration(user.Id, user.UserName, user.Email)   
    );

    ...
 }

[AutomaticRetry(Attempts = 5)]
public async Task NotifyRegistration(string userId, string username, string email)
{
    //I calculate callbackUrl

    var viewsPath = Path.GetFullPath(HostingEnvironment.MapPath(@"~/Views/Emails"));
    var engines = new ViewEngineCollection();
    engines.Add(new FileSystemRazorViewEngine(viewsPath));

    var emailService = new EmailService(engines);

    var emailToSend = new NewRegisteredUserEmail
    {
        To = email, UserName = username, CallbackUrl = callbackUrl 
    };

    emailService.Send(emailToSend);
}

I cannot debug the NotifyRegistration method. I don't know why. I am using Postal, so EmailService is not my implementation. Here how I configured the smtp service:

<system.net>
  <mailSettings>
    <smtp deliveryMethod="Network">
      <network host="smtp.live.com" port="25" enableSsl="true" userName="***" password="***"></network>
    </smtp>
  </mailSettings>
</system.net>

If I run the hangfire dashboard I see the jobs enqued

enter image description here

But nothing else happened. What do I miss to send the email?

Thank you

UPDATE In the startup.cs I have written this:

var options = new SqlServerStorageOptions
{
    QueuePollInterval = TimeSpan.FromSeconds(1)
};

GlobalConfiguration.Configuration
     .UseSqlServerStorage("DbConnectionString", options)
     .UseFilter(new LogEmailFailureAttribute());

 app.UseHangfireDashboard();
 app.UseHangfireServer();

UPDATE 2 I transformed my NotifyRegistration in this way:

[AutomaticRetry(Attempts = 5)]
public async Task NotifyRegistration(string userId, string username, string email, EmailService emailService)
{
    //I calculate callbackUrl

    var emailToSend = new NewRegisteredUserEmail
    {
        To = email, UserName = username, CallbackUrl = callbackUrl 
    };

    emailService.Send(emailToSend);
}
Hennessy answered 16/9, 2016 at 12:4 Comment(4)
'I cannot debug the NotifyRegistration method. I don't know why' maybe you are running an older state of the file?Uncanny
Does the email get sent if you move the call out of the hangfire job?Excitement
@chris, I have tried to do aclean and a rebuild... nothing.. I think I cannot debug it because is a background job... or similarHennessy
@TomRedfern, yes, it works correctly outside hangfireHennessy
H
7

I Found the problem(s):

  1. The version of sql server was not supported. I was using 2005. Supported database is 2008R2 and later: http://docs.hangfire.io/en/latest/configuration/using-sql-server.html

  2. The method NotifyRegistration must be static: https://discuss.hangfire.io/t/jobs-in-enqueue-state-most-never-run/2367/4

.

[AutomaticRetry(Attempts = 5)]
public static void NotifyRegistration(string userId, string username, string email, EmailService emailService)
{
    //I calculate callbackUrl

    var emailToSend = new NewRegisteredUserEmail
    {
        To = email, UserName = username, CallbackUrl = callbackUrl 
    };

    emailService.Send(emailToSend);
}
Hennessy answered 19/9, 2016 at 13:6 Comment(1)
making the function static, does the job for me.Clementia
C
2

Without seeing your Hangfire configuration...

Do you have app.UseHangfireServer(); anywhere? That is what tells Hangfire that it needs to do the executing - otherwise you're simply queuing as it expects something else to do the execution.

Catinacation answered 16/9, 2016 at 12:33 Comment(3)
Yes I have it... However I have updated my post.... so you can see what I have done...Hennessy
Just to rule things out, and because I have read that polling too frequently can cause issues, can you remove your custom polling and see if it executes?Catinacation
Also see #39486070 Why is your method async Task instead of simply void? Because it was migrated over? Again - grasping at straws - but everything is worth a shot at this point. ;)Catinacation
E
0

My guess is that is has something to do with either

  1. the call to HostingEnvironment.MapPath(), or
  2. some internal construction detail of the EmailService type.

What strikes me is that there is an awful lot going on in this method and it could be made significantly simpler if:

  1. rather than instantiating a new EmailService, you passed one into the containing class as an already instantiated dependency, and also
  2. rather than trying to divine the physical file path to your templates directory from within the method you passed it into the method as an argument.

If you were to perform this refactoring I would bet a not insignificant number of kittens that this problem would go away.

Excitement answered 16/9, 2016 at 12:31 Comment(2)
I had copied the method from their web site: docs.hangfire.io/en/latest/tutorials/… they also suggest not to pass complex type to method run in backgroundjob, due to serialization complexity... however, give me some minutes that I try your solutionHennessy
I transformed the method as you said, but nothing changed and nothing raises an exception.. see the update 2Hennessy
P
0

Just to mention

It also happens when you are programatically adding scheduled job from say "alpha" queue but the schduled job enques in diffrent queue.

so while adding scheduled job mention the queue name alpha resolved my issue

Pollen answered 8/12, 2023 at 8:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.