Skip to content

Commit

Permalink
Refactor to move things into nice small classes
Browse files Browse the repository at this point in the history
  • Loading branch information
nul800sebastiaan committed Jul 29, 2022
1 parent c13708e commit f956a00
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 90 deletions.
133 changes: 43 additions & 90 deletions Cultiv.Hangfire/HangfireComposer.cs
Original file line number Diff line number Diff line change
@@ -1,120 +1,73 @@
using System;
using System.Collections.Generic;
using Hangfire;
using Hangfire.Console;
using Hangfire.SqlServer;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Umbraco.Cms.Core.Composing;
using Umbraco.Cms.Core.DependencyInjection;
using Umbraco.Cms.Core.Manifest;
using Umbraco.Cms.Web.Common.ApplicationBuilder;
using Umbraco.Cms.Web.Common.Authorization;
using Umbraco.Extensions;

namespace Cultiv.Hangfire
namespace Cultiv.Hangfire;

public class HangfireComposer : IComposer
{
public class HangfireComposer : IComposer
public void Compose(IUmbracoBuilder builder)
{
public void Compose(IUmbracoBuilder builder)
{
builder.ManifestFilters().Append<CultivHangfireManifestFilter>();

var connectionString = GetConnectionString(builder);
if (string.IsNullOrEmpty(connectionString))
{
// This might happen when the package is installed before Umbraco is installed
// https://github.com/nul800sebastiaan/Cultiv.Hangfire/issues/11
return;
}

// Configure Hangfire to use our current database and add the option to write console messages
builder.Services.AddHangfire(configuration =>
{
configuration
.SetDataCompatibilityLevel(CompatibilityLevel.Version_170)
.UseSimpleAssemblyNameTypeSerializer()
.UseRecommendedSerializerSettings()
.UseConsole()
.UseSqlServerStorage(connectionString, new SqlServerStorageOptions
{
CommandBatchMaxTimeout = TimeSpan.FromMinutes(5),
SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5),
QueuePollInterval = TimeSpan.Zero,
UseRecommendedIsolationLevel = true,
DisableGlobalLocks = true,
});
});

// Run the required server so your queued jobs will get executed
builder.Services.AddHangfireServer();
builder.ManifestFilters().Append<ManifestFilter>();

AddAuthorizedUmbracoDashboard(builder);

// For some reason we need to give it the connection string again, else we get this error:
// https://discuss.hangfire.io/t/jobstorage-current-property-value-has-not-been-initialized/884
JobStorage.Current = new SqlServerStorage(connectionString);
var connectionString = builder.GetConnectionString();
if (string.IsNullOrEmpty(connectionString))
{
// This might happen when the package is installed before Umbraco is installed
// https://github.com/nul800sebastiaan/Cultiv.Hangfire/issues/11
return;
}

private static void AddAuthorizedUmbracoDashboard(IUmbracoBuilder builder)
// Configure Hangfire to use our current database and add the option to write console messages
builder.Services.AddHangfire(configuration =>
{
// Add the dashboard and make sure it's authorized with the named policy above
builder.Services.Configure<UmbracoPipelineOptions>(options =>
{
options.AddFilter(new UmbracoPipelineFilter(Constants.System.HangfireDashboard)
configuration
.SetDataCompatibilityLevel(CompatibilityLevel.Version_170)
.UseSimpleAssemblyNameTypeSerializer()
.UseRecommendedSerializerSettings()
.UseConsole()
.UseSqlServerStorage(connectionString, new SqlServerStorageOptions
{
Endpoints = app => app.UseEndpoints(endpoints =>
{
endpoints.MapHangfireDashboardWithAuthorizationPolicy(
pattern: Constants.System.Endpoint,
options: new DashboardOptions(),
authorizationPolicyName: AuthorizationPolicies.SectionAccessSettings);
})
CommandBatchMaxTimeout = TimeSpan.FromMinutes(5),
SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5),
QueuePollInterval = TimeSpan.Zero,
UseRecommendedIsolationLevel = true,
DisableGlobalLocks = true,
});
});
}
});

private static readonly List<string> AllowedSqlProviderNames =
new() { Umbraco.Cms.Persistence.SqlServer.Constants.ProviderName, "System.Data.SqlClient" };
// Run the required server so your queued jobs will get executed
builder.Services.AddHangfireServer();

private static string GetConnectionString(IUmbracoBuilder builder)
{
var connectionString =
builder.Config.GetUmbracoConnectionString(Constants.System.AlternativeConnectionStringName);
if (string.IsNullOrWhiteSpace(connectionString) == false)
{
return connectionString;
}
AddAuthorizedUmbracoDashboard(builder);

var providerName =
builder.Config.GetConnectionStringProviderName(Umbraco.Cms.Core.Constants.System.UmbracoConnectionName);
if (providerName != null && AllowedSqlProviderNames.InvariantContains(providerName) == false)
{
throw new NotSupportedException(
$"Cultiv.Hangfire only works on providers `{string.Join("`, `", AllowedSqlProviderNames)}`, your current provider ({providerName}) is not supported.");
}

return builder.Config.GetUmbracoConnectionString();
}
// For some reason we need to give it the connection string again, else we get this error:
// https://discuss.hangfire.io/t/jobstorage-current-property-value-has-not-been-initialized/884
JobStorage.Current = new SqlServerStorage(connectionString);
}

internal class CultivHangfireManifestFilter : IManifestFilter
private static void AddAuthorizedUmbracoDashboard(IUmbracoBuilder builder)
{
public void Filter(List<PackageManifest> manifests)
// Add the dashboard and make sure it's authorized with the named policy above
builder.Services.Configure<UmbracoPipelineOptions>(options =>
{
manifests.Add(new PackageManifest
options.AddFilter(new UmbracoPipelineFilter(Constants.System.HangfireDashboard)
{
PackageName = "Cultiv.Hangfire",
Dashboards = new[]
Endpoints = app => app.UseEndpoints(endpoints =>
{
new ManifestDashboard
{
Alias = "cultiv.Hangfire",
Sections = new[] { Umbraco.Cms.Core.Constants.Applications.Settings },
View = "/App_Plugins/Cultiv.Hangfire/dashboard.html"
}
}
endpoints.MapHangfireDashboardWithAuthorizationPolicy(
pattern: Constants.System.Endpoint,
options: new DashboardOptions(),
authorizationPolicyName: AuthorizationPolicies.SectionAccessSettings);
})
});
}
});
}
}
}
24 changes: 24 additions & 0 deletions Cultiv.Hangfire/ManifestFilter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System.Collections.Generic;
using Umbraco.Cms.Core.Manifest;

namespace Cultiv.Hangfire;

internal class ManifestFilter : IManifestFilter
{
public void Filter(List<PackageManifest> manifests)
{
manifests.Add(new PackageManifest
{
PackageName = "Cultiv.Hangfire",
Dashboards = new[]
{
new ManifestDashboard
{
Alias = "cultiv.Hangfire",
Sections = new[] { Umbraco.Cms.Core.Constants.Applications.Settings },
View = "/App_Plugins/Cultiv.Hangfire/dashboard.html"
}
}
});
}
}
33 changes: 33 additions & 0 deletions Cultiv.Hangfire/UmbracoBuilderExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using Umbraco.Cms.Core.DependencyInjection;
using Umbraco.Extensions;

namespace Cultiv.Hangfire;

public static class UmbracoBuilderExtensions
{
public static string GetConnectionString(this IUmbracoBuilder builder)
{
var connectionString =
builder.Config.GetUmbracoConnectionString(Constants.System.AlternativeConnectionStringName);
if (string.IsNullOrWhiteSpace(connectionString) == false)
{
return connectionString;
}

var providerName =
builder.Config.GetConnectionStringProviderName(Umbraco.Cms.Core.Constants.System.UmbracoConnectionName);
if (providerName != null && AllowedSqlProviderNames.InvariantContains(providerName) == false)
{
throw new NotSupportedException(
$"Cultiv.Hangfire only works on providers `{string.Join("`, `", AllowedSqlProviderNames)}`, your current provider ({providerName}) is not supported.");
}

return builder.Config.GetUmbracoConnectionString();
}


private static readonly List<string> AllowedSqlProviderNames =
new() { Umbraco.Cms.Persistence.SqlServer.Constants.ProviderName, "System.Data.SqlClient" };
}

0 comments on commit f956a00

Please sign in to comment.