/// <summary>
        /// Adds the hangfire services to the application.
        /// </summary>
        public static IServiceCollection AddHangfire(this IServiceCollection services, string serverName, string connectionString = "", Action <JobStorageOptions> configJobStorage = null, Action <BackgroundJobServerOptions> configAction = null, IEnumerable <IBackgroundProcess> additionalProcesses = null)
        {
            services.AddHangfire(config =>
            {
                config
                .SetDataCompatibilityLevel(CompatibilityLevel.Version_170)
                .UseSimpleAssemblyNameTypeSerializer()
                .UseRecommendedSerializerSettings();

                config.UseFilter(new HangfireLoggerAttribute());
                config.UseFilter(new HangfirePreserveOriginalQueueAttribute());

                if (connectionString != null)
                {
                    //Initializes Hangfire Schema if PrepareSchemaIfNecessary = true
                    var storage = HangfireJobStorage.GetJobStorage(connectionString, configJobStorage).JobStorage;

                    config.UseStorage(storage);
                    //config.UseMemoryStorage();
                    //config.UseSqlServerStorage(connectionString);
                    //config.UseSQLiteStorage(connectionString);
                }
            });

            if (connectionString != null)
            {
                //Launches Server as IHostedService
                services.AddHangfireServer(serverName, configAction, additionalProcesses);
            }

            return(services);
        }
        public virtual void ConfigureServices(TenantBuilderContext context, IServiceCollection services)
        {
            var hangfireServicesAdded = context.RootServiceProvider.GetService <IGlobalConfiguration>() != null;

            //configuration
            var configuration = new HangfireConfiguration();

            context.Configuration.Bind("Hangfire", configuration);
            ConfigureHangfire(context, configuration);
            services.AddSingleton(configuration);

            //dashboard options
            var dashboardOptions = context.RootServiceProvider.GetService <DashboardOptions>()?.Clone() ?? new DashboardOptions();

            ConfigureHangfireDashboard(context, dashboardOptions);
            services.AddSingleton(dashboardOptions);

            //background processing server
            IBackgroundProcessingServer processingServer = null;

            //Storage
            if (configuration.Enabled)
            {
                var storageDetails = HangfireJobStorage.GetJobStorage(configuration.ConnectionString, options => {
                    options.PrepareSchemaIfNecessary = false;
                    options.EnableHeavyMigrations    = false;
                    options.EnableLongPolling        = configuration.EnableLongPolling;
                    options.SchemaName = configuration.SchemaName;
                });

                JobStorage storage = storageDetails.JobStorage;
                configuration.ExistingConnection = storageDetails.ExistingConnection;

                services.AddSingleton(storage);
                services.AddHangfireServerServices();

                Func <IServiceProvider, Action <IBackgroundProcessingServer> > processingServerSetter = ((sp) => (x) => { processingServer = x; });
                services.AddSingleton(processingServerSetter);
                Func <IServiceProvider, IBackgroundProcessingServer> processingServerAccessor = ((sp) => processingServer);
                services.AddSingleton(processingServerAccessor);

                var backgroundServerOptions = context.RootServiceProvider.GetService <BackgroundJobServerOptions>()?.Clone() ?? new BackgroundJobServerOptions();

                backgroundServerOptions.ServerName     = configuration.ServerName ?? backgroundServerOptions.ServerName;
                backgroundServerOptions.Activator      = new MultiTenantJobActivator(context.RootServiceProvider.GetRequiredService <MultitenantContainer>(), context.TenantId);
                backgroundServerOptions.FilterProvider = context.RootServiceProvider.GetService <IJobFilterProvider>() ?? new JobFilterCollection();

                ConfigureHangfireServer(context, backgroundServerOptions);

                services.AddSingleton(backgroundServerOptions);
            }
            else
            {
                if (hangfireServicesAdded)
                {
                    services.AddSingleton((JobStorage) new NoopJobStorage());
                    services.AddHangfireServerServices();
                }
            }

            //background processes
            ConfigureBackgroundProcesses(context, services);
        }
        public virtual async Task InitializeDbAsync(IServiceProvider serviceProvider, CancellationToken cancellationToken)
        {
            var jobStorage        = serviceProvider.GetService <JobStorage>();
            var newHangfireServer = jobStorage != null && jobStorage.GetType() != typeof(NoopJobStorage);

            if (newHangfireServer)
            {
                var configuration = serviceProvider.GetRequiredService <HangfireConfiguration>();

                //Initialize Hangfire Db
                if (!string.IsNullOrEmpty(configuration.ConnectionString))
                {
                    if (configuration.DbInitialiation == DbInitialiation.PrepareSchemaIfNecessary)
                    {
                        if (configuration.ExistingConnection == null)
                        {
                            HangfireJobStorage.GetJobStorage(configuration.ConnectionString, options => {
                                options.PrepareSchemaIfNecessary = true;
                                options.EnableHeavyMigrations    = false;
                                options.EnableLongPolling        = false;
                                options.SchemaName = configuration.SchemaName;
                            });
                        }
                        else
                        {
                            HangfireJobStorage.GetJobStorage(configuration.ExistingConnection, options => {
                                options.PrepareSchemaIfNecessary = true;
                                options.EnableHeavyMigrations    = false;
                                options.EnableLongPolling        = false;
                                options.SchemaName = configuration.SchemaName;
                            });
                        }
                    }
                    else if (configuration.DbInitialiation == DbInitialiation.PrepareSchemaIfNecessaryAndHeavyMigrations)
                    {
                        if (configuration.ExistingConnection == null)
                        {
                            HangfireJobStorage.GetJobStorage(configuration.ConnectionString, options =>
                            {
                                options.PrepareSchemaIfNecessary = true;
                                options.EnableHeavyMigrations    = true;
                                options.EnableLongPolling        = false;
                                options.SchemaName = configuration.SchemaName;
                            });
                        }
                        else
                        {
                            HangfireJobStorage.GetJobStorage(configuration.ExistingConnection, options =>
                            {
                                options.PrepareSchemaIfNecessary = true;
                                options.EnableHeavyMigrations    = true;
                                options.EnableLongPolling        = false;
                                options.SchemaName = configuration.SchemaName;
                            });
                        }
                    }
                    else if (configuration.DbInitialiation == DbInitialiation.EnsureTablesDeletedThenEnsureDbAndTablesCreated)
                    {
                        if (configuration.ExistingConnection == null)
                        {
                            await HangfireInitializer.EnsureTablesDeletedAsync(configuration.ConnectionString, configuration.SchemaName);

                            await HangfireInitializer.EnsureDbAndTablesCreatedAsync(configuration.ConnectionString, options =>
                            {
                                options.PrepareSchemaIfNecessary = true;
                                options.EnableHeavyMigrations    = true;
                                options.SchemaName = configuration.SchemaName;
                            });
                        }
                        else
                        {
                            await HangfireInitializer.EnsureTablesDeletedAsync(configuration.ExistingConnection, configuration.SchemaName);

                            await HangfireInitializer.EnsureDbAndTablesCreatedAsync(configuration.ExistingConnection, options =>
                            {
                                options.PrepareSchemaIfNecessary = true;
                                options.EnableHeavyMigrations    = true;
                                options.SchemaName = configuration.SchemaName;
                            });
                        }
                    }
                    else if (configuration.DbInitialiation == DbInitialiation.EnsureDbAndTablesCreated)
                    {
                        if (configuration.ExistingConnection == null)
                        {
                            await HangfireInitializer.EnsureDbAndTablesCreatedAsync(configuration.ConnectionString, options =>
                            {
                                options.PrepareSchemaIfNecessary = true;
                                options.EnableHeavyMigrations    = false;
                                options.SchemaName = configuration.SchemaName;
                            });
                        }
                        else
                        {
                            await HangfireInitializer.EnsureDbAndTablesCreatedAsync(configuration.ExistingConnection, options =>
                            {
                                options.PrepareSchemaIfNecessary = true;
                                options.EnableHeavyMigrations    = false;
                                options.SchemaName = configuration.SchemaName;
                            });
                        }
                    }
                    else if (configuration.DbInitialiation == DbInitialiation.EnsureDbAndTablesCreatedAndHeavyMigrations)
                    {
                        if (configuration.ExistingConnection == null)
                        {
                            await HangfireInitializer.EnsureDbAndTablesCreatedAsync(configuration.ConnectionString, options => {
                                options.PrepareSchemaIfNecessary = true;
                                options.EnableHeavyMigrations    = true;
                                options.SchemaName = configuration.SchemaName;
                            });
                        }
                        else
                        {
                            await HangfireInitializer.EnsureDbAndTablesCreatedAsync(configuration.ExistingConnection, options => {
                                options.PrepareSchemaIfNecessary = true;
                                options.EnableHeavyMigrations    = true;
                                options.SchemaName = configuration.SchemaName;
                            });
                        }
                    }
                }

                //Launch Server
                var applicationLifetime = serviceProvider.GetRequiredService <IApplicationLifetime>();
                var additionalProcesses = serviceProvider.GetServices <IBackgroundProcess>();
                var setter        = serviceProvider.GetRequiredService <Action <IBackgroundProcessingServer> >();
                var serverDetails = HangfireLauncher.StartHangfireServer(serviceProvider.GetRequiredService <BackgroundJobServerOptions>(), jobStorage, new HangfireLauncherOptions()
                {
                    ApplicationLifetime = applicationLifetime, AdditionalProcesses = additionalProcesses
                });
                setter(serverDetails.Server);
            }
        }