Skip to content

Commit

Permalink
Merge pull request #216 from dolittle:execution-context
Browse files Browse the repository at this point in the history
execution-context
  • Loading branch information
einari authored May 10, 2021
2 parents 89d62b2 + f3c125c commit 885b0e3
Show file tree
Hide file tree
Showing 10 changed files with 85 additions and 17 deletions.
3 changes: 2 additions & 1 deletion Samples/Source/Aspnetcore/Backend/Things.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Dolittle.SDK.Events;
using Dolittle.SDK.Events.Handling;
using Dolittle.SDK.Events.Store;
using Dolittle.Vanir.Backend.Execution;
using Dolittle.Vanir.Backend.GraphQL;
using FluentValidation;
using Microsoft.Extensions.Logging;
Expand Down Expand Up @@ -116,7 +117,7 @@ public class Things : GraphController
readonly IEventStore _eventStore;
readonly IAggregateOf<Kitchen> _kitchen;

public Things(IMongoDatabase mongoDatabase, IEventStore eventStore, IAggregateOf<Kitchen> kitchen)
public Things(IMongoDatabase mongoDatabase, IEventStore eventStore, IAggregateOf<Kitchen> kitchen, IExecutionContextManager executionContextManager)
{
_mongoDatabase = mongoDatabase;
_eventStore = eventStore;
Expand Down
4 changes: 2 additions & 2 deletions Source/DotNET/Backend/Dolittle/DolittleContainer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ public class DolittleContainer : global::Dolittle.SDK.DependencyInversion.IConta

public object Get(Type service, ExecutionContext context)
{
ExecutionContextManager.Set(context);
ExecutionContextManager.SetCurrent(context);
return ServiceProvider.GetService(service);
}

public T Get<T>(ExecutionContext context) where T : class
{
ExecutionContextManager.Set(context);
ExecutionContextManager.SetCurrent(context);
return (T)ServiceProvider.GetService(typeof(T));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

using System;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Dolittle.SDK;
using Dolittle.SDK.Aggregates;
Expand Down Expand Up @@ -60,7 +59,7 @@ public static void AddDolittle(this IServiceCollection services, Config configur
services.AddTransient(_ =>
{
ThrowIfClientNotBuilt();
return DolittleClient.EventStore.ForTenant(ExecutionContextManager.Current.Tenant);
return DolittleClient.EventStore.ForTenant(ExecutionContextManager.GetCurrent().Tenant);
});
services.AddTransient(typeof(IAggregateOf<>), typeof(AggregateOf<>));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,23 @@

namespace Microsoft.AspNetCore.Builder
{
public static class ExecutionContextExtensions
public static class ExecutionContextAppBuilderExtensions
{
const string TENANT_ID = "Tenant-ID";
const string _tenantId = "Tenant-ID";

public static void UseExecutionContext(this IApplicationBuilder app)
{
app.Use(async (context, next) =>
{
var tenantId = TenantId.Development;
if (context.Request.Headers.ContainsKey(TENANT_ID))
if (context.Request.Headers.ContainsKey(_tenantId))
{
tenantId = context.Request.Headers[TENANT_ID].First();
tenantId = context.Request.Headers[_tenantId].First();
}
ExecutionContextManager.Establish(tenantId, Guid.NewGuid());
var executionContextManager = app.ApplicationServices.GetService(typeof(IExecutionContextManager)) as IExecutionContextManager;
executionContextManager.Establish(tenantId, Guid.NewGuid());
await next.Invoke().ConfigureAwait(false);
});
}
Expand Down
27 changes: 23 additions & 4 deletions Source/DotNET/Backend/Execution/ExecutionContextManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,30 @@

namespace Dolittle.Vanir.Backend.Execution
{
public static class ExecutionContextManager
/// <summary>
/// Represents an implementation of <see cref="IExecutionContextManager"/>.
/// </summary>
public class ExecutionContextManager : IExecutionContextManager
{
static readonly AsyncLocal<ExecutionContext> _currentExecutionContext = new();
public static ExecutionContext Current => _currentExecutionContext.Value;

public static ExecutionContext Establish(TenantId tenantId, CorrelationId correlationId)
/// <summary>
/// Get current <see cref="ExecutionContext"/>.
/// </summary>
/// <returns>Current <see cref="ExecutionContext"/>.</returns>
public static ExecutionContext GetCurrent() => _currentExecutionContext.Value;

/// <summary>
/// Set a <see cref="ExecutionContext"/> for current call path.
/// </summary>
/// <param name="context"><see cref="ExecutionContext"/> to set.</param>
public static void SetCurrent(ExecutionContext context) => _currentExecutionContext.Value = context;

/// <inheritdoc/>
public ExecutionContext Current => _currentExecutionContext.Value;

/// <inheritdoc/>
public ExecutionContext Establish(TenantId tenantId, CorrelationId correlationId)
{
_currentExecutionContext.Value = new ExecutionContext(
MicroserviceManager.Current.Id,
Expand All @@ -32,6 +50,7 @@ public static ExecutionContext Establish(TenantId tenantId, CorrelationId correl
return _currentExecutionContext.Value;
}

public static void Set(ExecutionContext context) => _currentExecutionContext.Value = context;
/// <inheritdoc/>
public void Set(ExecutionContext context) => _currentExecutionContext.Value = context;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright (c) Dolittle. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using Dolittle.Vanir.Backend.Execution;

namespace Microsoft.Extensions.DependencyInjection
{
public static class ExecutionContextServiceCollectionExtensions
{
public static void AddExecutionContext(this IServiceCollection services)
{
services.AddSingleton<IExecutionContextManager>(new ExecutionContextManager());
}
}
}
34 changes: 34 additions & 0 deletions Source/DotNET/Backend/Execution/IExecutionContextManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright (c) Dolittle. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using Dolittle.SDK.Execution;
using Dolittle.SDK.Tenancy;
using ExecutionContext = Dolittle.SDK.Execution.ExecutionContext;

namespace Dolittle.Vanir.Backend.Execution
{
/// <summary>
/// Defines a system for working with <see cref="ExecutionContext"/>
/// </summary>
public interface IExecutionContextManager
{
/// <summary>
/// Get the current <see cref="ExecutionContext"/> for the current call path.
/// </summary>
ExecutionContext Current { get; }

/// <summary>
/// Establish an <see cref="ExecutionContext"/> for current call path.
/// </summary>
/// <param name="tenantId"><see cref="TenantId"/> to establish for.</param>
/// <param name="correlationId"><see cref="CorrelationId"/> to establish for.</param>
/// <returns>Established <see cref="ExecutionContext"/>.</returns>
ExecutionContext Establish(TenantId tenantId, CorrelationId correlationId);

/// <summary>
/// Set a <see cref="ExecutionContext"/> for current call path.
/// </summary>
/// <param name="context"><see cref="ExecutionContext"/> to set.</param>
void Set(ExecutionContext context);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public static void AddResources(this IServiceCollection services, BackendArgumen
services.Add(new ServiceDescriptor(typeof(ResourceConfigurations), resourceConfigurations));
services.Add(new ServiceDescriptor(typeof(IMongoDatabase), (provider) =>
{
var tenant = ExecutionContextManager.Current.Tenant;
var tenant = ExecutionContextManager.GetCurrent().Tenant;
if (_mongoDatabaseByTenant.ContainsKey(tenant))
{
return _mongoDatabaseByTenant[tenant];
Expand Down
2 changes: 0 additions & 2 deletions Source/DotNET/Backend/VanirAppBuilderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@

namespace Microsoft.AspNetCore.Builder
{

public static class VanirAppBuilderExtensions
{
public static void UseVanir(this IApplicationBuilder app)
Expand Down Expand Up @@ -72,7 +71,6 @@ static void UseVanirCommon(this IApplicationBuilder app)
_.MapGraphQLPlayground(new PlaygroundOptions { GraphQLEndPoint = configuration.GraphQLRoute }, configuration.GraphQLPlaygroundRoute);
}
logger.LogInformation($"GraphQL endpoint is located at '{configuration.GraphQLRoute}'");
_.MapGraphQL(configuration.GraphQLRoute).WithOptions(new GraphQLServerOptions
{
Expand Down
1 change: 1 addition & 0 deletions Source/DotNET/Backend/VanirServiceCollectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public static Services AddVanir(this IServiceCollection services, BackendArgumen

var configuration = services.AddVanirConfiguration();
services.AddDolittle(configuration, arguments, types);
services.AddExecutionContext();
services.AddGraphQL(container, arguments, types);

services.Configure<KestrelServerOptions>(options => options.AllowSynchronousIO = true);
Expand Down

0 comments on commit 885b0e3

Please sign in to comment.