Skip to content

Commit

Permalink
Merge pull request #28 from marcwittke/release/3.0.1
Browse files Browse the repository at this point in the history
Release/3.0.1
  • Loading branch information
marcwittke committed May 22, 2018
2 parents e7487f4 + a43dec1 commit 43f8c40
Show file tree
Hide file tree
Showing 41 changed files with 475 additions and 252 deletions.
Original file line number Diff line number Diff line change
@@ -1,26 +1,49 @@
namespace DemoBlog.Bootstrapping.Jobs
namespace DemoBlog.Application.Jobs
{
using System;
using Backend.Fx.Environment.Authentication;
using Backend.Fx.Environment.MultiTenancy;
using Backend.Fx.Patterns.DependencyInjection;
using Backend.Fx.Patterns.Jobs;
using JetBrains.Annotations;

/// <summary>
/// Wraps a pure Application Job (implementing <see cref="FluentScheduler.IJob"/>) in a
/// Fluent Scheduler Job (implementing <see cref="FluentScheduler.IJob"/>) to make it schedulable
/// </summary>
public class ApplicationRuntimeJobWrapper<TApplicationJob> : FluentScheduler.IJob where TApplicationJob : class, Backend.Fx.Patterns.Jobs.IJob
public class ApplicationRuntimeJobWrapper : FluentScheduler.IJob
{
private readonly IJobExecutor jobExecutor;
private readonly IScopeManager scopeManager;
private readonly ITenantManager tenantManager;
private readonly Type jobType;

[UsedImplicitly]
public ApplicationRuntimeJobWrapper(IJobExecutor jobExecutor)
public ApplicationRuntimeJobWrapper(IScopeManager scopeManager, ITenantManager tenantManager, Type jobType)
{
this.jobExecutor = jobExecutor;
this.scopeManager = scopeManager;
this.tenantManager = tenantManager;
this.jobType = jobType;
}

[UsedImplicitly]
public void Execute()
{
jobExecutor.ExecuteJobAsync<TApplicationJob>().RunSynchronously();
foreach (var tenantId in tenantManager.GetTenantIds())
{
using (var scope = scopeManager.BeginScope(new SystemIdentity(), tenantId))
{
var jobExecutorType = typeof(IJobExecutor<>).MakeGenericType(jobType);
IJobExecutor jobExecutor = (IJobExecutor) scope.GetInstance(jobExecutorType);
jobExecutor.ExecuteJob();
}
}
}
}

public class ApplicationRuntimeJobWrapper<TJob> : ApplicationRuntimeJobWrapper
{
public ApplicationRuntimeJobWrapper(IScopeManager scopeManager, ITenantManager tenantManager)
: base(scopeManager, tenantManager, typeof(TJob))
{ }
}
}
Original file line number Diff line number Diff line change
@@ -1,37 +1,40 @@
namespace DemoBlog.Bootstrapping.Jobs
namespace DemoBlog.Application.Jobs
{
using System;
using Backend.Fx.Environment.MultiTenancy;
using Backend.Fx.Logging;
using Backend.Fx.Patterns.Jobs;
using Backend.Fx.Patterns.DependencyInjection;
using FluentScheduler;
using IJob = FluentScheduler.IJob;

/// <summary>
/// Factory to enable FluentScheduler to use our application runtime
/// </summary>
public class ApplicationRuntimeJobFactory : IJobFactory
{
private static readonly ILogger Logger = LogManager.Create<ApplicationRuntimeJobFactory>();
private readonly IJobExecutor jobExecutor;

public ApplicationRuntimeJobFactory(IJobExecutor jobExecutor)
private readonly IScopeManager scopeManager;
private readonly ITenantManager tenantManager;

public ApplicationRuntimeJobFactory(IScopeManager scopeManager, ITenantManager tenantManager)
{
this.jobExecutor = jobExecutor;
this.scopeManager = scopeManager;
this.tenantManager = tenantManager;
}

public IJob GetJobInstance<T>() where T : IJob
{
object jobInstance;
try
{
jobInstance = Activator.CreateInstance(typeof(T), jobExecutor);
IJob job = (IJob) Activator.CreateInstance(typeof(T), scopeManager, tenantManager);
return job;
}
catch (Exception ex)
{
Logger.Error(ex, $"Unable to create an instance of {typeof(T).Name}. Are you sure it implements ApplicationRuntimeJobWrapper<T>?");
throw;
}
return (IJob)jobInstance;


}
}
}
18 changes: 14 additions & 4 deletions demo/DemoBlog.Application/Application/Jobs/JobSchedule.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
namespace DemoBlog.Bootstrapping.Jobs
namespace DemoBlog.Application.Jobs
{
using Backend.Fx.Logging;
using FluentScheduler;
using IJob = Backend.Fx.Patterns.Jobs.IJob;

public class JobSchedule : Registry
{
Expand All @@ -9,10 +11,18 @@ public JobSchedule()
NonReentrantAsDefault();

// NOTE: all application jobs must be wrapped in an ApplicationRuntimeJobWrapper for scheduling. Example:
// Schedule<ApplicationRuntimeJobWrapper<MyCoolJob>>().Every(60).Minutes();

Schedule<ApplicationRuntimeJobWrapper<MyCoolJob>>().ToRunNow().AndEvery(30).Seconds();

// add more jobs here
}
}

public class MyCoolJob : IJob
{
private static readonly ILogger Logger = LogManager.Create<MyCoolJob>();

public void Run()
{
Logger.Info("Job run");
}
}
}
16 changes: 8 additions & 8 deletions demo/DemoBlog.Mvc/DemoBlog.Mvc.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,23 @@
<UserSecretsId>aspnet-DemoBlog.Mvc-5cbe09ad-9a77-44bb-8a63-757aec42ff7e</UserSecretsId>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.1.1" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.2.1" />
<PackageReference Include="Microsoft.AspNetCore" Version="2.0.3" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.Cookies" Version="2.0.4" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.Google" Version="2.0.4" />
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="2.0.3" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="2.0.3" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.4" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.0.1" PrivateAssets="All" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="2.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.0.1" PrivateAssets="All" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.0.3" PrivateAssets="All" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="2.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.0.3" PrivateAssets="All" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="2.0.2" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.0.2" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.0.1" PrivateAssets="All" />
<PackageReference Include="Microsoft.VisualStudio.Web.BrowserLink" Version="2.0.1" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.0.4" PrivateAssets="All" />
<PackageReference Include="Microsoft.VisualStudio.Web.BrowserLink" Version="2.0.3" />
<PackageReference Include="Polly" Version="6.0.1" />
<PackageReference Include="SimpleInjector.Integration.AspNetCore.Mvc" Version="4.0.12" />
<PackageReference Include="SimpleInjector.Integration.AspNetCore.Mvc" Version="4.3.0" />
</ItemGroup>
<ItemGroup>
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="2.0.0" />
Expand Down
2 changes: 1 addition & 1 deletion src/Backend.Fx.AspNetCore/Backend.Fx.AspNetCore.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore" Version="2.0.3" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.2" />
<PackageReference Include="SimpleInjector.Integration.AspNetCore.Mvc" Version="4.0.12" />
<PackageReference Include="SimpleInjector.Integration.AspNetCore.Mvc" Version="4.3.0" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace Backend.Fx.AspNetCore.Integration
namespace Backend.Fx.AspNetCore
{
using System;
using Logging;
Expand Down
20 changes: 6 additions & 14 deletions src/Backend.Fx.AspNetCore/ErrorHandling/ErrorLoggingMiddleware.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
namespace Backend.Fx.AspNetCore.ErrorHandling
{
using System;
using System.Linq;
using System.Threading.Tasks;
using Exceptions;
using JetBrains.Annotations;
using Logging;
using Microsoft.AspNetCore.Http;

public class ErrorLoggingMiddleware
{
private readonly RequestDelegate next;
private static readonly ILogger Logger = LogManager.Create<ErrorLoggingMiddleware>();
private readonly IExceptionLogger exceptionLogger = new ExceptionLogger(LogManager.Create<ErrorLoggingMiddleware>());

[UsedImplicitly]
public ErrorLoggingMiddleware(RequestDelegate next)
Expand All @@ -26,19 +24,13 @@ public async Task Invoke(HttpContext context)
{
await next.Invoke(context);
}
catch (ClientException cex)
{
string[] clientErrorStrings = cex.Errors
.SelectMany(err => err.Value.Select(er => $"{Environment.NewLine} {er.Code}:{er.Message}"))
.ToArray();

var clientErrorString = string.Join("", clientErrorStrings);
Logger.Warn(cex, cex.Message + clientErrorString);
throw;
}
catch (Exception uex)
{
Logger.Error(uex);
if (!context.Items.ContainsKey("ExceptionLogged"))
{
exceptionLogger.LogException(uex);
context.Items["ExceptionLogged"] = true;
}
throw;
}
}
Expand Down
22 changes: 22 additions & 0 deletions src/Backend.Fx.AspNetCore/ErrorHandling/ExceptionLoggingFilter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
namespace Backend.Fx.AspNetCore.ErrorHandling
{
using Logging;
using Microsoft.AspNetCore.Mvc.Filters;

public class ExceptionLoggingFilter : IActionFilter
{
public void OnActionExecuting(ActionExecutingContext context)
{ }

public void OnActionExecuted(ActionExecutedContext context)
{
if (context.Exception != null && !context.HttpContext.Items.ContainsKey("ExceptionLogged"))
{
ILogger logger = LogManager.Create(context.Controller.GetType().FullName);
IExceptionLogger exceptionLogger = new ExceptionLogger(logger);
exceptionLogger.LogException(context.Exception);
context.HttpContext.Items["ExceptionLogged"] = true;
}
}
}
}
2 changes: 1 addition & 1 deletion src/Backend.Fx.AspNetCore/Scoping/UnitOfWorkMiddleware.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public class UnitOfWorkMiddleware
private readonly IBackendFxApplication application;

[UsedImplicitly]
protected UnitOfWorkMiddleware(RequestDelegate next, IBackendFxApplication application)
public UnitOfWorkMiddleware(RequestDelegate next, IBackendFxApplication application)
{
this.next = next;
this.application = application;
Expand Down
4 changes: 2 additions & 2 deletions src/Backend.Fx.Bootstrapping/Backend.Fx.Bootstrapping.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.0.0" />
<PackageReference Include="SimpleInjector" Version="4.0.12" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="2.0.2" />
<PackageReference Include="SimpleInjector" Version="4.3.0" />
</ItemGroup>

<ItemGroup>
Expand Down
8 changes: 1 addition & 7 deletions src/Backend.Fx.Bootstrapping/BackendFxDbApplication.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
using Environment.Persistence;
using Logging;
using Patterns.DependencyInjection;
using Patterns.Jobs;


public abstract class BackendFxDbApplication : BackendFxApplication
{
Expand All @@ -21,15 +19,12 @@ public abstract class BackendFxDbApplication : BackendFxApplication
/// <param name="databaseManager">The database manager for the current application</param>
/// <param name="tenantManager">The tenant manager for the current application</param>
/// <param name="scopeManager">The scope manager for the current application</param>
/// <param name="jobExecutor">The job executor for the current application. If not provided, a default <see cref="Patterns.Jobs.JobExecutor"/> instance is generated.</param>
protected BackendFxDbApplication(
ICompositionRoot compositionRoot,
IDatabaseManager databaseManager,
ITenantManager tenantManager,
IScopeManager scopeManager,
IJobExecutor jobExecutor = null) : base(compositionRoot,scopeManager)
IScopeManager scopeManager) : base(compositionRoot,scopeManager)
{
JobExecutor = jobExecutor ?? new JobExecutor(tenantManager, scopeManager);
DatabaseManager = databaseManager;
TenantManager = tenantManager;
}
Expand All @@ -44,7 +39,6 @@ public abstract class BackendFxDbApplication : BackendFxApplication
/// </summary>
public ITenantManager TenantManager { get; }

public IJobExecutor JobExecutor { get; }

public override async Task Boot()
{
Expand Down
11 changes: 8 additions & 3 deletions src/Backend.Fx.Bootstrapping/Modules/DomainModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,22 +55,27 @@ protected override void Register(Container container, ScopedLifestyle scopedLife

// domain event subsystem
Logger.Debug($"Registering domain event handlers from {string.Join(",", assemblies.Select(ass => ass.GetName().Name))}");
container.RegisterCollection(typeof(IDomainEventHandler<>), assemblies);
container.Collection.Register(typeof(IDomainEventHandler<>), assemblies);
Logger.Debug("Registering singleton event aggregator instance");
container.RegisterSingleton(domainEventAggregator);
container.RegisterInstance(domainEventAggregator);

// initial data generation subsystem
Logger.Debug($"Registering initial data generators from {string.Join(",", assemblies.Select(ass => ass.GetName().Name))}");
container.RegisterCollection<InitialDataGenerator>(assemblies);
container.Collection.Register<InitialDataGenerator>(assemblies);

// all jobs are dynamically registered
foreach (var scheduledJobType in container.GetTypesToRegister(typeof(IJob), assemblies))
{
Logger.Debug($"Registering {scheduledJobType.Name}");
container.Register(scheduledJobType);
}

container.Register(typeof(IJobExecutor<>), typeof(JobExecutor<>));
container.RegisterDecorator(typeof(IJobExecutor<>), typeof(UnitOfWorkJobExecutor<>));
container.RegisterDecorator(typeof(IJobExecutor<>), typeof(ExceptionLoggingJobExecutor<>));
}


/// <summary>
/// Auto registering all aggregate authorization classes
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ protected EfCorePersistenceModule(DbContextOptions<TDbContext> dbContextOptions)

protected override void Register(Container container, ScopedLifestyle lifestyle)
{
container.RegisterSingleton(dbContextOptions);
container.RegisterInstance(dbContextOptions);
container.Register<DbContext,TDbContext>();

// EF Repositories
Expand Down
6 changes: 3 additions & 3 deletions src/Backend.Fx.Bootstrapping/SimpleInjectorContainerEx.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,13 @@ public static void RegisterDomainAndApplicationServices(this Container container

public static void Configure<TOptions>(this Container container, Action<TOptions> configure) where TOptions : class
{
container.RegisterSingleton<IConfigureOptions<TOptions>>(new ConfigureOptions<TOptions>(configure));
container.RegisterInstance<IConfigureOptions<TOptions>>(new ConfigureOptions<TOptions>(configure));
}

public static void Configure<TOptions>(this Container container, IConfiguration configuration) where TOptions : class
{
container.RegisterSingleton<IOptionsChangeTokenSource<TOptions>>(new ConfigurationChangeTokenSource<TOptions>(Options.DefaultName, configuration));
container.RegisterSingleton<IConfigureOptions<TOptions>>(new NamedConfigureFromConfigurationOptions<TOptions>(Options.DefaultName, configuration));
container.RegisterInstance<IOptionsChangeTokenSource<TOptions>>(new ConfigurationChangeTokenSource<TOptions>(Options.DefaultName, configuration));
container.RegisterInstance<IConfigureOptions<TOptions>>(new NamedConfigureFromConfigurationOptions<TOptions>(Options.DefaultName, configuration));
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="2.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="2.0.3" />
</ItemGroup>

<ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion src/Backend.Fx.EfCorePersistence/Mssql/MsSqlSequence.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public abstract class MsSqlSequence : ISequence

public void EnsureSequence(DbContext dbContext)
{
Logger.Info($"Ensuring existence of oracle sequence {SequenceName}");
Logger.Info($"Ensuring existence of mssql sequence {SequenceName}");
using (var dbConnection = dbContext.Database.GetDbConnection())
{
dbConnection.Open();
Expand Down
2 changes: 1 addition & 1 deletion src/Backend.Fx.NLogLogging/Backend.Fx.NLogLogging.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.0.2" />
<PackageReference Include="NLog" Version="5.0.0-beta11" />
<PackageReference Include="NLog" Version="4.5.4" />
</ItemGroup>

<ItemGroup>
Expand Down

0 comments on commit 43f8c40

Please sign in to comment.