HangfireIO / Hangfire

An easy way to perform background job processing in .NET and .NET Core applications. No Windows Service or separate process required
https://www.hangfire.io
Other
9.32k stars 1.69k forks source link

Console is already initialized #1200

Open kamran-pervaiz opened 6 years ago

kamran-pervaiz commented 6 years ago

I am setting up test project and when I am running my tests I get below error.

System.InvalidOperationException : Console is already initialized
   at Hangfire.Console.GlobalConfigurationExtensions.UseConsole(IGlobalConfiguration configuration, ConsoleOptions options)
   at Service.Content.Reverter.WindowsService.Infrastructure.Hangfire.HangfireConfiguration.ConfigureHangfireDashboardServer(IApplicationBuilder app)
   at Service.Content.Reverter.WindowsService.Startup.Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Microsoft.AspNetCore.Hosting.ConventionBasedStartup.Configure(IApplicationBuilder app)
   at Microsoft.AspNetCore.Hosting.Internal.AutoRequestServicesStartupFilter.<>c__DisplayClass0_0.<Configure>b__0(IApplicationBuilder builder)
   at Microsoft.AspNetCore.Hosting.Internal.WebHost.BuildApplication()
   at Microsoft.AspNetCore.Hosting.Internal.WebHost.<StartAsync>d__26.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.TestHost.TestServer..ctor(IWebHostBuilder builder, IFeatureCollection featureCollection)
   at Microsoft.AspNetCore.TestHost.TestServer..ctor(IWebHostBuilder builder)
   at Bbc.Ww.WindowsService.IntegrationTests.API.WebserverTestsBase.BeforeEachTestBaseSetup() in C:\Projects\service-content-reverter\src\WindowsService.IntegrationTests\API\ProcessStatusControllerTests.cs:line 80

Running test with root C:\Projects\service-content-reverter\src\WindowsService
Application startup exception: System.InvalidOperationException: Console is already initialized
   at Hangfire.Console.GlobalConfigurationExtensions.UseConsole(IGlobalConfiguration configuration, ConsoleOptions options)
   at Service.Content.Reverter.WindowsService.Infrastructure.Hangfire.HangfireConfiguration.ConfigureHangfireDashboardServer(IApplicationBuilder app)
   at Service.Content.Reverter.WindowsService.Startup.Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Microsoft.AspNetCore.Hosting.ConventionBasedStartup.Configure(IApplicationBuilder app)
   at Microsoft.AspNetCore.Hosting.Internal.AutoRequestServicesStartupFilter.<>c__DisplayClass0_0.<Configure>b__0(IApplicationBuilder builder)
   at Microsoft.AspNetCore.Hosting.Internal.WebHost.BuildApplication()
crit: Microsoft.AspNetCore.Hosting.Internal.WebHost[6]
      Application startup exception
System.InvalidOperationException: Console is already initialized
   at Hangfire.Console.GlobalConfigurationExtensions.UseConsole(IGlobalConfiguration configuration, ConsoleOptions options)
   at Service.Content.Reverter.WindowsService.Infrastructure.Hangfire.HangfireConfiguration.ConfigureHangfireDashboardServer(IApplicationBuilder app)
   at Service.Content.Reverter.WindowsService.Startup.Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Microsoft.AspNetCore.Hosting.ConventionBasedStartup.Configure(IApplicationBuilder app)
   at Microsoft.AspNetCore.Hosting.Internal.AutoRequestServicesStartupFilter.<>c__DisplayClass0_0.<Configure>b__0(IApplicationBuilder builder)
   at Microsoft.AspNetCore.Hosting.Internal.WebHost.BuildApplication()

I know the issue lies in below code:

GlobalConfiguration.Configuration.UseConsole();

This error message is added in 1.3.10

+            if (DashboardRoutes.Routes.Contains("/console/([0-9a-f]{11}.+)"))
+                throw new InvalidOperationException("Console is already initialized");

but not sure what is elegant way to stop calling UseConsole() more than once. This code is written as part of HangFireConfiguration class. can we clear HangFire GlobalConfiguration?

kamran-pervaiz commented 6 years ago

I have fixed it with below code but it would be great if we have the ability to clear GlobalConfiguration for HangFire.

if (AlreadyConfiguredHangFireConsole) return;
            GlobalConfiguration.Configuration
                .UseConsole();
            AlreadyConfiguredHangFireConsole = true;
mattkwiecien commented 6 years ago

I solved this problem by using the singleton pattern. My singleton is called HangfireGlobalConfiguration and I simply call HangfireGlobalConfiguration.GetInstance() in my OwinStartup method. Inside that class I setup sql server storage and console.

The benefits of using that pattern is you can make it thread safe and lazy, where your above code is not.

ffMathy commented 4 years ago

But why rely on statics in the first place? It makes it a pain to test.

mack0196 commented 3 years ago

Is there any progress on refactoring out the singleton state stores (e.g. GlobalConfiguration)?

TripleEmcoder commented 2 years ago

Hangfire and its extensions, as useful as they are, do rely too much on static state in GlobalConfiguration.Configuration, JobStorage.Current, JobActivator.Current, causing problems when multiple IServiceCollections are initialized. The actual issue is tracked in #821, I believe.