Skip to content

Commit

Permalink
Hotfix/7.0.4 (#110)
Browse files Browse the repository at this point in the history
* db conn aclaration

* exception logging & builder

* docs

* wait for data generation

* currentHolder with initial ctor

* xmldocs

* wait for default tenant

* xmldocs

* formatting

* logging improved

* xmldocs

* xmldocs

* method detection standardized

* xmldocs

* method detections

* xmldocs

* description and min version

* fix logging of errors array

* cherrypick-errors fixed

* dependency fix

* test fix

* correlation holder is injected, must not contain more public ctors

* build triggers adapted

* master -> main
  • Loading branch information
marcwittke authored Jul 12, 2021
1 parent 3c7d4e5 commit 51e5a16
Show file tree
Hide file tree
Showing 39 changed files with 231 additions and 62 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Backend.Fx.AspNetCore.Mvc | 2.0 | [![NuGet](https://img.shields.io/nuget/v/Backe
Backend.Fx.NetCore | 1.3 | [![NuGet](https://img.shields.io/nuget/v/Backend.Fx.NetCore.svg)](https://www.nuget.org/packages/Backend.Fx.NetCore)

## What does "opinionated" mean?
You get vendor locked to a set of abstractions, like my DDD building blocks and some architecture [patterns](https://github.com/marcwittke/Backend.Fx/tree/master/src/abstractions/Backend.Fx/Patterns) defined as interfaces
You get vendor locked to a set of abstractions, like my DDD building blocks and some architecture [patterns](https://github.com/marcwittke/Backend.Fx/tree/main/src/abstractions/Backend.Fx/Patterns) defined as interfaces

## Less opinonated, but already provided as pluggable implementations of patterns

Expand Down
2 changes: 1 addition & 1 deletion build/Build.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ class Build : NukeBuild
.DependsOn(Pack)
.Executes(() =>
{
bool pushToNuget = GitRepository.Branch == "master";
bool pushToNuget = GitRepository.Branch == "main";
foreach (var nupkg in ArtifactsDirectory.GlobFiles("*.nupkg"))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ namespace Backend.Fx.Environment.Authentication
{
public class CurrentIdentityHolder : CurrentTHolder<IIdentity>
{
public CurrentIdentityHolder()
{ }

private CurrentIdentityHolder(IIdentity initial) : base(initial)
{ }

public override IIdentity ProvideInstance()
{
return new AnonymousIdentity();
Expand All @@ -28,9 +34,7 @@ public static ICurrentTHolder<IIdentity> CreateSystem()

public static ICurrentTHolder<IIdentity> Create(IIdentity identity)
{
var currentIdentityHolder = new CurrentIdentityHolder();
currentIdentityHolder.ReplaceCurrent(identity);
return currentIdentityHolder;
return new CurrentIdentityHolder(identity);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,21 @@ namespace Backend.Fx.Environment.MultiTenancy
{
public class CurrentTenantIdHolder : CurrentTHolder<TenantId>
{
public CurrentTenantIdHolder()
{ }

private CurrentTenantIdHolder(TenantId initial) : base(initial)
{ }

public static CurrentTenantIdHolder Create(int tenantId)
{
var instance = new CurrentTenantIdHolder();
instance.ReplaceCurrent(new TenantId(tenantId));
var instance = new CurrentTenantIdHolder((TenantId)tenantId);
return instance;
}

public static CurrentTenantIdHolder Create(TenantId tenantId)
{
var instance = new CurrentTenantIdHolder();
instance.ReplaceCurrent(tenantId);
var instance = new CurrentTenantIdHolder(tenantId);
return instance;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
namespace Backend.Fx.Environment.MultiTenancy
{
/// <summary>
/// By means of this instance, other services gain insight about all active tenants. This is useful, when for example a job
/// By means of this instance, the IBackendFxApplication gains insight about all active tenants. This is required, when for example a job
/// should be executed for all tenants or data should be generated for all tenants during startup.
/// The <see cref="ITenantService"/> can provide such implementation, but this can only be done in process. When the tenant service is
/// running in another process, the implementation must be done using a suitable remoting technology.
/// </summary>
public interface ITenantIdProvider
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public class SingleTenantApplication : TenantApplication, IBackendFxApplication
private readonly bool _isDemoTenant;
private readonly ITenantService _tenantService;
private readonly IBackendFxApplication _application;
private readonly ManualResetEventSlim _defaultTenantEnsured = new ManualResetEventSlim(false);

public SingleTenantApplication(bool isDemoTenant, ITenantService tenantService, IBackendFxApplication application) : base(application)
{
Expand All @@ -38,7 +39,7 @@ public void Dispose()

public bool WaitForBoot(int timeoutMilliSeconds = int.MaxValue, CancellationToken cancellationToken = default)
{
return _application.WaitForBoot(timeoutMilliSeconds, cancellationToken);
return _defaultTenantEnsured.Wait(timeoutMilliSeconds, cancellationToken);
}

public async Task Boot(CancellationToken cancellationToken = default)
Expand All @@ -50,6 +51,8 @@ public async Task Boot(CancellationToken cancellationToken = default)
Logger.Info($"Ensuring existence of single tenant");
TenantId = _tenantService.GetActiveTenants().SingleOrDefault()?.GetTenantId()
?? _tenantService.CreateTenant("Single Tenant", "This application runs in single tenant mode", _isDemoTenant);

_defaultTenantEnsured.Set();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ public void Complete()
public void Cancel()
{
Operation.Cancel();
Logger.Debug("Closing database connection");
DbConnection.Close();
_connectionLifetimeLogger?.Dispose();

// note: we do not dispose the DbConnection here, because we did not instantiate it. Disposing is always up to the creator of
// the instance, that is in this case the injection container.
}
}
}
18 changes: 18 additions & 0 deletions src/abstractions/Backend.Fx/Exceptions/ClientException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,19 @@ public ClientException()
{
}

/// <param name="message">When using one of the middlewares in Backend.Fx.AspNetCore.ErrorHandling, the message is not sent
/// to the client to not provide internal details to an attacker. Write the exception message with a developer in mind, since
/// the application log will contain the message. To provide the user with functional feedback to correct their input, use
/// the AddError(s) overloads.</param>
public ClientException(string message)
: base(message)
{
}

/// <param name="message">When using one of the middlewares in Backend.Fx.AspNetCore.ErrorHandling, the message is not sent
/// to the client to not provide internal details to an attacker. Write the exception message with a developer in mind, since
/// the application log will contain the message. To provide the user with functional feedback to correct their input, use
/// the AddError(s) overloads.</param>
public ClientException(string message, Exception innerException)
: base(message, innerException)
{
Expand Down Expand Up @@ -48,6 +56,16 @@ public override string ToString()
return string.Join(System.Environment.NewLine,
new[] {message, Errors.ToString(), innerException, StackTrace}.Where(s => s != null));
}

/// <summary>
/// Used to build an <see cref="ClientException"/> with multiple possible error messages. The builder will throw on disposal
/// when at least one error was added. Using the AddIf methods is quite comfortable when there are several criteria to be validated
/// before executing a business case.
/// </summary>
public static IExceptionBuilder UseBuilder()
{
return new ExceptionBuilder<ClientException>();
}
}

public static class ClientExceptionEx
Expand Down
7 changes: 2 additions & 5 deletions src/abstractions/Backend.Fx/Exceptions/ConflictedException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,16 @@ public ConflictedException()
{
}

/// <inheritdoc />
public ConflictedException(string message)
: base(message)
{
}

/// <inheritdoc />
public ConflictedException(string message, Exception innerException)
: base(message, innerException)
{
}

public static IExceptionBuilder UseBuilder()
{
return new ExceptionBuilder<ConflictedException>();
}
}
}
7 changes: 2 additions & 5 deletions src/abstractions/Backend.Fx/Exceptions/ForbiddenException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,16 @@ public ForbiddenException()
{
}

/// <inheritdoc />
public ForbiddenException(string message)
: base(message)
{
}

/// <inheritdoc />
public ForbiddenException(string message, Exception innerException)
: base(message, innerException)
{
}

public static IExceptionBuilder UseBuilder()
{
return new ExceptionBuilder<ForbiddenException>();
}
}
}
5 changes: 0 additions & 5 deletions src/abstractions/Backend.Fx/Exceptions/NotFoundException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,6 @@ public NotFoundException(string entityName, object id)
EntityName = entityName;
Id = id;
}

public static IExceptionBuilder UseBuilder()
{
return new ExceptionBuilder<NotFoundException>();
}
}

public class NotFoundException<TEntity> : NotFoundException
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ public TooManyRequestsException(int retryAfter)
RetryAfter = retryAfter;
}

/// <inheritdoc />
public TooManyRequestsException(int retryAfter, string message) : base(message)
{
RetryAfter = retryAfter;
}

/// <inheritdoc />
public TooManyRequestsException(int retryAfter, string message, Exception innerException) : base(message, innerException)
{
RetryAfter = retryAfter;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ public UnauthorizedException()
{
}

/// <inheritdoc />
public UnauthorizedException(string message)
: base(message)
{
}

/// <inheritdoc />
public UnauthorizedException(string message, Exception innerException)
: base(message, innerException)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,24 @@ public UnprocessableException()
{
}

/// <inheritdoc />
public UnprocessableException(string message)
: base(message)
{
}

/// <inheritdoc />
public UnprocessableException(string message, Exception innerException)
: base(message, innerException)
{
}

public static IExceptionBuilder UseBuilder()
/// <summary>
/// Used to build an <see cref="UnprocessableException"/> with multiple possible error messages. The builder will throw on disposal
/// when at least one error was added. Using the AddIf methods is quite comfortable when there are several criteria to be validated
/// before executing a business case.
/// </summary>
public new static IExceptionBuilder UseBuilder()
{
return new ExceptionBuilder<UnprocessableException>();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
namespace Backend.Fx.Patterns.Authorization
{
using System.Linq;
using System.Linq.Expressions;
using BuildingBlocks;
using System.Linq;
using System.Linq.Expressions;
using Backend.Fx.BuildingBlocks;

namespace Backend.Fx.Patterns.Authorization
{
/// <summary>
/// Implements permissions on aggregate level. The respective instance is applied when creating an <see cref="IRepository&lt;T&gt;"/>,
/// so that the repository never allows reading or writing of an aggregate without permissions.
/// </summary>
/// <typeparam name="TAggregateRoot"></typeparam>
public interface IAggregateAuthorization<TAggregateRoot> where TAggregateRoot : AggregateRoot
{
/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

namespace Backend.Fx.Patterns.DataGeneration
{
/// <summary>
/// Will appear on the message bus when the data generation process has been completed
/// </summary>
public class DataGenerated : IntegrationEvent
{
public DataGenerated(int tenantId) : base(tenantId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,16 @@

namespace Backend.Fx.Patterns.DataGeneration
{
/// <summary>
/// Enriches the <see cref="IBackendFxApplication"/> by calling all data generators for all tenants on application start.
/// </summary>
public class GenerateDataOnBoot : IBackendFxApplication
{
private static readonly ILogger Logger = LogManager.Create<GenerateDataOnBoot>();
private readonly ITenantIdProvider _tenantIdProvider;
private readonly IBackendFxApplication _application;
private readonly IModule _dataGenerationModule;
private readonly ManualResetEventSlim _dataGenerated = new ManualResetEventSlim(false);
public IDataGenerationContext DataGenerationContext { get; [UsedImplicitly] private set; }

public GenerateDataOnBoot(ITenantIdProvider tenantIdProvider, IModule dataGenerationModule, IBackendFxApplication application)
Expand All @@ -39,7 +43,7 @@ public void Dispose()

public bool WaitForBoot(int timeoutMilliSeconds = Int32.MaxValue, CancellationToken cancellationToken = default)
{
return _application.WaitForBoot(timeoutMilliSeconds, cancellationToken);
return _dataGenerated.Wait(timeoutMilliSeconds, cancellationToken);
}

public async Task Boot(CancellationToken cancellationToken = default)
Expand All @@ -48,9 +52,11 @@ public async Task Boot(CancellationToken cancellationToken = default)
await _application.Boot(cancellationToken);

SeedDataForAllActiveTenants();

_dataGenerated.Set();
}
public void SeedDataForAllActiveTenants()

private void SeedDataForAllActiveTenants()
{
using (Logger.InfoDuration("Seeding data"))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@

namespace Backend.Fx.Patterns.DependencyInjection
{
/// <summary>
/// A guid that is unique for an invocation. In case of an invocation as result of handling an integration event, the correlation
/// is stable, that is, the correlation can be used to track a logical action over different systems.
/// </summary>
public class Correlation
{
private static readonly ILogger Logger = LogManager.Create<Correlation>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ public abstract class CurrentTHolder<T> : ICurrentTHolder<T> where T : class
private static readonly ILogger Logger = LogManager.Create<CurrentTHolder<T>>();
private T _current;

protected CurrentTHolder()
{ }

protected CurrentTHolder(T initial)
{
_current = initial;
}

public T Current
{
get
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,15 @@ public interface ICompositionRoot : IDisposable, IDomainEventHandlerProvider
void RegisterModules(params IModule[] modules);

IInjectionScope BeginScope();

/// <summary>
/// Access to the container's resolution functionality
/// </summary>
IInstanceProvider InstanceProvider { get; }

/// <summary>
/// Access to the container's configuration functionality
/// </summary>
IInfrastructureModule InfrastructureModule { get; }
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
namespace Backend.Fx.Patterns.DependencyInjection
{
/// <summary>
/// A logically cohesive bunch of services
/// </summary>
public interface IModule
{
void Register(ICompositionRoot compositionRoot);
Expand Down
Loading

0 comments on commit 51e5a16

Please sign in to comment.