Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Nik 1593 posts 7151 karma points MVP 6x c-trib
    Nov 27, 2019 @ 10:39
    Nik
    0

    Hangfire background task to create content - LightInject Activator

    Hi All,

    So I'm hitting a bit of a block and I'm wondering if anyone here can help.

    Scenario

    • Webhook end point is triggered when ever files are updated on an Azure blob storage
    • This action adds items into a db queue
    • Scheduled task (plan is to use hangfire) runs every hour to process this queue. The reason for this is updates need to be batched together and not processed as and when they come in.

    Current setup

    • Webhook is receiving requests and putting items in the queue
    • Hangfire is installed and the reoccurring job is set up - However it fails on execution

    This is my test job class:

    public class MyTestJobClass : IMyTestJobClass
    {
        private readonly IUmbracoContextFactory contextFactory;
        private readonly IProfilingLogger logger;
    
        public MyTestJobClass(IUmbracoContextFactory contextFactory, IProfilingLogger logger)
        {
            this.contextFactory = contextFactory ?? throw new ArgumentNullException(nameof(contextFactory));
            this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
        }
    
        public void ScheduleJob()
        {
            BackgroundJob.Enqueue(() => DoJob(null));
        }
    
        public void DoJob(PerformContext context)
        {
            try
            {
                using (var umbracoContext = contextFactory.EnsureUmbracoContext())
                {
                    foreach (var node in umbracoContext.UmbracoContext.Content.GetAtRoot())
                    {
                        System.Diagnostics.Debug.WriteLine("{0} - {1}", node.Id, node.Name);
                    }
                }
            }
            catch (Exception ex)
            {
                logger.Error(GetType(), ex);
            }
    
        }
    }
    

    Hangfire is configured using an approach based on this: https://github.com/guru-digital/umbraco-hangfire

    In addition to this setup, hangfire is set up to use the LightInjectJobActivator extension https://github.com/sbosell/Hangfire.LightInject by doing the following in a composer:

    [RuntimeLevel(MinLevel = RuntimeLevel.Boot)]
    public class HangfireStartup : IComposer
    {
    
        public void Compose(Composition composition)
        {
    
            UmbracoDefaultOwinStartup.MiddlewareConfigured += UmbracoDefaultOwinStartup_MiddlewareConfigured;
        }
    
        private void UmbracoDefaultOwinStartup_MiddlewareConfigured(object sender, OwinMiddlewareConfiguredEventArgs e)
        {
            StartHanfgire(e.AppBuilder);            
        }
    
        private  void StartHanfgire(IAppBuilder app)
        {
    
            //Configure Hangfire
            var options = new SqlServerStorageOptions { PrepareSchemaIfNecessary = true, QueuePollInterval = TimeSpan.FromSeconds(30) };
            const string defaultUmbracoConnectionName = Umbraco.Core.Constants.System.UmbracoConnectionName;
            var connectionString = System.Configuration.ConfigurationManager.ConnectionStrings[defaultUmbracoConnectionName].ConnectionString;
    
            GlobalConfiguration.Configuration.UseSqlServerStorage(connectionString, options)
                .UseLightInjectActivator(Current.Factory.Concrete as LightInject.ServiceContainer);
    
            //Give hangfire a URL and start the server
            app.UseHangfireDashboard("/umbraco/hangfire", new DashboardOptions { AppPath = null, Authorization = new[] { new UmbracoHangfireAuthorizationFilter() } });
            app.UseHangfireServer();
    
    
        }
    
    
    }
    

    However, when the job is trying to active a null reference is being thrown:

    System.NullReferenceException Object reference not set to an instance of an object.
    
    System.NullReferenceException: Object reference not set to an instance of an object.    
        at LightInject.Web.PerWebRequestScopeManager.GetOrAddScope() in
        C:\projects\lightinject-web\build\tmp\Net46\Binary\LightInject.Web\LightInject.Web.cs:line 148
        at LightInject.ScopeManager.BeginScope() in
        C:\projects\lightinject\src\LightInject\LightInject.cs:line 6325
        at Hangfire.LightInject.LightInjecterScope..ctor(ServiceContainer container)
        at Hangfire.LightInject.LightInjectJobActivator.BeginScope()
        at Hangfire.Server.CoreBackgroundJobPerformer.Perform(PerformContext context)
        at Hangfire.Server.BackgroundJobPerformer.<>c__DisplayClass9_0.<PerformJobWithFilters>b__0()
        at Hangfire.Server.BackgroundJobPerformer.InvokePerformFilter(IServerFilter filter, PerformingContext preContext, Func`1 continuation)
        at Hangfire.Server.BackgroundJobPerformer.PerformJobWithFilters(PerformContext context, IEnumerable`1 filters)
        at Hangfire.Server.BackgroundJobPerformer.Perform(PerformContext context) at Hangfire.Server.Worker.PerformJob(BackgroundProcessContext context, IStorageConnection connection, String jobId)
    

    My job class requires the LightInject DI to work because I want to (eventually) be injecting all the services I need for content creation. However, I believe that my current error is related to getting the LightInject DI to work.

    For reference I've been reading the following existing threads in an attempt to get my head around this as well: https://our.umbraco.com/forum/umbraco-8/95966-umbraco-8-and-hangfire https://cultiv.nl/blog/using-hangfire-for-scheduled-tasks-in-umbraco/ https://our.umbraco.com/forum/using-umbraco-and-getting-started/100156-umbracocontext-issues-in-hangfireservice-job-possible-dependency-injection

    I'm hoping I don't have to go down the route of creating my own LightInject service composer instance and re-registering all of the Umbraco services in order to achieve this, so any help/pointers from people would greatly help me.

    Thanks

    Nik

  • Nik 1593 posts 7151 karma points MVP 6x c-trib
    Nov 27, 2019 @ 11:09
    Nik
    0

    I feel that this might be something to do with it: https://github.com/seesharper/LightInject/issues/383

    And also that various components in Umbraco are dependent on a HTTP context.

  • Nik 1593 posts 7151 karma points MVP 6x c-trib
    Nov 27, 2019 @ 11:30
    Nik
    0

    Does anyone know what the risks/implications of doing the following are:

     var serviceContainer = new LightInject.ServiceContainer();
     foreach (var t in (Current.Factory.Concrete as LightInject.ServiceContainer).AvailableServices)
         serviceContainer.Register(t);
    
     serviceContainer.ScopeManagerProvider = new PerLogicalCallContextScopeManagerProvider();
    
     GlobalConfiguration.Configuration.UseSqlServerStorage(connectionString, options)
        .UseLightInjectActivator(serviceContainer);
    
  • Nik 1593 posts 7151 karma points MVP 6x c-trib
    Nov 27, 2019 @ 11:51
    Nik
    0

    Further follow on:

    Finally found a thread on here that seemed very similar to the issues I was having:

    https://our.umbraco.com/forum/umbraco-8/96445-hangfire-dependency-injection

Please Sign in or register to post replies

Write your reply to:

Draft