Base solution for your next web application
Open Closed

Hangfire job schedule/ Castle.MicroKernel.ComponentNotFound #1310


User avatar
0
soulmate created

Hello,

I have following problem: I created a module based on the AbpModule. In that module I like to configure recurring jobs with hangfire. A recurring job in this scenario notifies users. I have following code:

[DependsOn(typeof(AbpHangfireModule))]
    public class MyModule : AbpModule
    {
        public override void Initialize()
        {
            IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
          

            Configuration.BackgroundJobs.UseHangfire(
                configuration => { configuration.GlobalConfiguration.UseSqlServerStorage("Default"); });
        }

     
        [DisplayName("Provider Reminder for offers that are due {0} hours")]
        [AutomaticRetry(Attempts = 0, OnAttemptsExceeded = AttemptsExceededAction.Delete)]
        public void OfferReminderJobDefinition(int hours)
        {
            var reminderService = IocManager.Resolve<IReminderService>();
            reminderService.Start(hours);
        }


        public override void PostInitialize()
        {
            base.PostInitialize();

                   
            RecurringJob.AddOrUpdate("Provider Reminder offer 24 hours", () => OfferReminderJobDefinition(24), Cron.Hourly);
            RecurringJob.AddOrUpdate("Provider Reminder offer 36 hours", () => OfferReminderJobDefinition(36), Cron.Hourly);


        }
    }

The implementation of the IReminder Service looks like:

public class ReminderService : AppServiceBase, IReminderService
    {
        /// <summary>
        /// The _offer service
        /// </summary>
        private readonly IOfferService _offerService;
        /// <summary>
        /// The _offer executed action service
        /// </summary>
        private readonly IOfferExecutedActionService _offerExecutedActionService;

        /// <summary>
        /// The _qutation service
        /// </summary>
        private readonly IQutationService _qutationService;
        /// <summary>
        /// The _routing parameter service
        /// </summary>
        private readonly IRoutingParameterService _routingParameterService;

        private readonly IOfferEmailer _offerEmailer;



        /// <summary>
        /// The _tenant identifier
        /// </summary>
        private readonly int _tenantId = 1;


        /// <summary>
        /// Initializes a new instance of the <see cref="ReminderService"/> class.
        /// </summary>
        /// <param name="qutationService">The qutation service.</param>
        /// <param name="offerService">The offer service.</param>
        /// <param name="offerExecutedActionService">The offer executed action service.</param>
        /// <param name="offerEmailer"></param>
        public ReminderService(IQutationService qutationService, IOfferService offerService,
         IOfferExecutedActionService offerExecutedActionService, IOfferEmailer offerEmailer)
        {
            _qutationService = qutationService;
            _offerExecutedActionService = offerExecutedActionService;
            _offerService = offerService;
            _offerEmailer = offerEmailer;

        }


        /// <summary>
        /// Starts the specified hours.
        /// </summary>
        /// <param name="hours">The hours.</param>
        public async void Start(int hours)
        {
            await ProcessReminder(hours);
        }
        ...
    }

When I start the application the job is registered correct in hangfire. Also the first call/ job execution works without any problems. However, the next execution fails with following error:

Failed An exception occurred during processing of a background job.

Castle.MicroKernel.ComponentNotFoundException

No component for supporting the service MyModule was found Castle.MicroKernel.ComponentNotFoundException: No component for supporting the service MyModule was found at Castle.MicroKernel.DefaultKernel.Castle.MicroKernel.IKernelInternal.Resolve(Type service, IDictionary arguments, IReleasePolicy policy) at Castle.MicroKernel.DefaultKernel.Resolve(Type service, IDictionary arguments) at Castle.Windsor.WindsorContainer.Resolve(Type service) at Abp.Dependency.IocManager.Resolve(Type type) at Abp.Hangfire.HangfireIocJobActivator.ActivateJob(Type jobType) at Abp.Hangfire.HangfireIocJobActivator.HangfireIocJobActivatorScope.Resolve(Type type) at Hangfire.Server.CoreBackgroundJobPerformer.Perform(PerformContext context) at Hangfire.Server.BackgroundJobPerformer.<>c__DisplayClass8_0.<PerformJobWithFilters>b__0() at Hangfire.Server.BackgroundJobPerformer.InvokePerformFilter(IServerFilter filter, PerformingContext preContext, Func1 continuation) at Hangfire.Server.BackgroundJobPerformer.<>c__DisplayClass8_1.<PerformJobWithFilters>b__2() at Hangfire.Server.BackgroundJobPerformer.PerformJobWithFilters(PerformContext context, IEnumerable1 filters) at Hangfire.Server.BackgroundJobPerformer.Perform(PerformContext context) at Hangfire.Server.Worker.PerformJob(BackgroundProcessContext context, IStorageConnection connection, String jobId)

It looks like as if the Module forget the dependency. Do you know why that happens and how I can get rid of it?


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

    It's strange that your code trying to resolve MyModule. Why? Do you have a dependency to MyModule class, which is normally should not be? Also, is that a web application? What is delay between job executions?

  • User Avatar
    0
    soulmate created

    Hi,

    No, I have no dependency to MyModule. The project is a class library, that is deployed via the web application that comes with the template. MyModule implements AbpModule. The main goal of the module is to execute recurring jobs (some should execute every 2 minutes, some every hour). The jobs are registered in hangfire and access code in .Application project. It is strange because the jobs run fine for 30 minutes. After that it seems like castle "forget" the reference.

    I have done some refectoring to make the problem more clear. I seperate the job into an own class:

    public class JobDefinition : ITransientDependency
        {
            private readonly IIocResolver _iocResolver;
    
            public JobDefinition(IIocResolver iocResolver)
            {
                _iocResolver = iocResolver;
            }
    
            [DisplayName("Import qutations from url {0}")]
            [AutomaticRetry(Attempts = 0, OnAttemptsExceeded = AttemptsExceededAction.Delete)]
            public void QutationImportServiceJobDefinition(string tenant, string url)
            {
                var qutationImportService = _iocResolver.Resolve<IQutationImportService>();
                qutationImportService.Start(tenant, url);
            }
        }
    

    Here is the definition of the module:

    [DependsOn(typeof(AbpHangfireModule))]
        public class MyModule : AbpModule
        {
            public override void Initialize()
            {
                IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
           
    
                Configuration.BackgroundJobs.UseHangfire(
                    configuration => { configuration.GlobalConfiguration.UseSqlServerStorage("Default"); });
            }
    
    
            public override void PostInitialize()
            {
                base.PostInitialize();
    
                var jobDefinition = new JobDefinition(IocManager);
    
    
                    //Every 2 minutes
                    RecurringJob.AddOrUpdate($"Job for {tenant}",
                        () => jobDefinition.QutationImportServiceJobDefinition("---", "http://google.com"),
                        "*/2 * * * *");
             
            }
        }
    

    The exception is:

    JobDefinition jobDefinition = Activate<JobDefinition>(); jobDefinition.QutationImportServiceJobDefinition();

    Failed An exception occurred during processing of a background job.

    Castle.MicroKernel.ComponentNotFoundException

    No component for supporting the service JobDefinition was found Castle.MicroKernel.ComponentNotFoundException: No component for supporting the service JobDefinition was found at Castle.MicroKernel.DefaultKernel.Castle.MicroKernel.IKernelInternal.Resolve(Type service, IDictionary arguments, IReleasePolicy policy) at Castle.MicroKernel.DefaultKernel.Resolve(Type service, IDictionary arguments) at Castle.Windsor.WindsorContainer.Resolve(Type service) at Abp.Dependency.IocManager.Resolve(Type type) at Abp.Hangfire.HangfireIocJobActivator.ActivateJob(Type jobType) at Abp.Hangfire.HangfireIocJobActivator.HangfireIocJobActivatorScope.Resolve(Type type) at Hangfire.Server.CoreBackgroundJobPerformer.Perform(PerformContext context) at Hangfire.Server.BackgroundJobPerformer.<>c__DisplayClass8_0.<PerformJobWithFilters>b__0() at Hangfire.Server.BackgroundJobPerformer.InvokePerformFilter(IServerFilter filter, PerformingContext preContext, Func1 continuation) at Hangfire.Server.BackgroundJobPerformer.<>c__DisplayClass8_1.<PerformJobWithFilters>b__2() at Hangfire.Server.BackgroundJobPerformer.PerformJobWithFilters(PerformContext context, IEnumerable1 filters) at Hangfire.Server.BackgroundJobPerformer.Perform(PerformContext context) at Hangfire.Server.Worker.PerformJob(BackgroundProcessContext context, IStorageConnection connection, String jobId)

    The application runs on the latest version of ABP. The secneario is the same deployed to my local IIS/ to azure. The application is set to "run always".

    Do you have any idea why it "forgets" the reference? If you have any other idea how to register jobs in a seperate module that are executed with hangfire I can also follow this guidance.

  • User Avatar
    0
    hikalkan created
    Support Team

    The only probability I can think for now is your web app is being shutdown. To ensure that, override Shutdown method in MyModule and log something to see if it happens.

  • User Avatar
    0
    soulmate created

    Hi hikalkan,

    During the last month I traced the issue a lot. However, I cant find the root of the problem. Here is my scenario:

    1. I debug (on my local IIS) or deploy the application to azure
    2. Azure app service is configured to dont shut down
    3. When using hangfire and the job is executed and sometime I receive the mentioned error and sometime it works (50/50 chance)
    4. When the error appear I restart the iis. Sometimes it works and sometimes not.

    Do you have any idea how to get rid of it?

  • User Avatar
    0
    hikalkan created
    Support Team

    You should keep your application alive. Have you seen that: <a class="postlink" href="http://docs.hangfire.io/en/latest/deployment-to-production/making-aspnet-app-always-running.html">http://docs.hangfire.io/en/latest/deplo ... nning.html</a>

  • User Avatar
    0
    soulmate created

    The application is alive and azure is configured to dont shut down. The problem exist randomly if I start debugging or deploy a new version. I think for some reasons it randomly failed to register the dependencies