diff --git a/Directory.Build.props b/Directory.Build.props
index b6ef25a0e..13099aef2 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -11,7 +11,7 @@
1570;1571;1572;1573;1574;1587;1591;1701;1702;1711;1735;0618
true
enable
- 4.10.1
+ 4.11.0
$(PackageProjectUrl)
true
true
diff --git a/WolverineWebApiFSharp/Program.fs b/WolverineWebApiFSharp/Program.fs
new file mode 100644
index 000000000..84e53fa76
--- /dev/null
+++ b/WolverineWebApiFSharp/Program.fs
@@ -0,0 +1,20 @@
+
+open System
+open JasperFx
+open Marten
+open Microsoft.AspNetCore.Builder
+open Wolverine
+open Wolverine.Http
+
+// We'll come back to this later. Used it for now to manually test some changes
+// let args = Environment.GetCommandLineArgs()[1..]
+//
+// let builder = WebApplication.CreateBuilder(args)
+//
+// builder.Host.UseWolverine() |> ignore
+// builder.Services.AddWolverineHttp() |> ignore
+// builder.Services.AddMarten("Host=localhost;Port=12345;Username=postgres;Password=postgres;Database=postgres") |> ignore
+//
+// let app = builder.Build()
+// app.MapWolverineEndpoints();
+// app.RunJasperFxCommands(args).GetAwaiter().GetResult() |> ignore
\ No newline at end of file
diff --git a/WolverineWebApiFSharp/SideEffects.fs b/WolverineWebApiFSharp/SideEffects.fs
new file mode 100644
index 000000000..27f4927bb
--- /dev/null
+++ b/WolverineWebApiFSharp/SideEffects.fs
@@ -0,0 +1,43 @@
+module WolverineWebApiFSharp.SideEffects
+
+open System
+open Wolverine
+open Wolverine.Http
+open Wolverine.Marten
+
+type Command = { Name: string }
+
+(* I cannot define a custom side effect here because code generation does not recognize the Execute method
+Unhandled exception. Wolverine.InvalidSideEffectException: Invalid Wolverine side effect exception for Wolverine.ISideEffect, no public Execute/ExecuteAsync method found
+ at Wolverine.SideEffectPolicy.applySideEffectExecution(Variable effect, IChain chain) in /Users/marcpiechura/RiderProjects/wolverine/src/Wolverine/ISideEffect.cs:line 93
+ at Wolverine.SideEffectPolicy.lookForSingularSideEffects(GenerationRules rules, IServiceContainer container, IChain chain) in /Users/marcpiechura/RiderProjects/wolverine/src/Wolverine/ISideEffect.cs:line 62
+ at Wolverine.SideEffectPolicy.Apply(IReadOnlyList`1 chains, GenerationRules rules, IServiceContainer container) in /Users/marcpiechura/RiderProjects/wolverine/src/Wolverine/ISideEffect.cs:line 42
+ at Wolverine.Http.HttpGraph.DiscoverEndpoints(WolverineHttpOptions wolverineHttpOptions) in /Users/marcpiechura/RiderProjects/wolverine/src/Http/Wolverine.Http/HttpGraph.cs:line 107
+ at Wolverine.Http.WolverineHttpEndpointRouteBuilderExtensions.MapWolverineEndpoints(IEndpointRouteBuilder endpoints, Action`1 configure) in /Users/marcpiechura/RiderProjects/wolverine/src/Http/Wolverine.Http/WolverineHttpEndpointRouteBuilderExtensions.cs:line 202
+
+*)
+type SomeSideEffect() =
+ static member val WasExecuted = false with get, set
+
+ interface ISideEffect
+
+ member this.Execute() =
+ SomeSideEffect.WasExecuted <- true
+
+
+type Event = { Id: Guid; Name: string }
+type SomeType = { Id: Guid }
+
+// this one is a bit more tricky, generally using ISideEffect works,
+// but for MartenOps.StartStream one has to provide the generic type parameter, otherwise
+// codegen will not generate a handler at all.
+
+[]
+[]
+let post (command: Command) =
+ let event: Event = { Id = Guid.NewGuid(); Name = command.Name }
+ //this doesn't work
+ MartenOps.StartStream(event.Id, box event)
+
+ // but this does
+ //MartenOps.StartStream(event.Id, box event)
\ No newline at end of file
diff --git a/WolverineWebApiFSharp/TupleSupport.fs b/WolverineWebApiFSharp/TupleSupport.fs
new file mode 100644
index 000000000..33ceeb08e
--- /dev/null
+++ b/WolverineWebApiFSharp/TupleSupport.fs
@@ -0,0 +1,64 @@
+namespace WolverineWebApiFSharp.TupleSupport
+
+open System
+open Microsoft.AspNetCore.Mvc
+open Wolverine.Http
+
+type Command = { SomeProperty: string }
+
+// The root problem is, that F# uses System.Tuple by default, but C# uses System.ValueTuple when defining a tuple with (int, string) syntax.
+// A workaround for F# is to use struct(int, string) which compiles to ValueTuple.
+// That affects at least the ability to pass values from Before/Validate.. methods to the handler method,
+// as well as the ability to use cascading messages in the handler method.
+
+module ValidationSupport =
+ (* Codegen looks like this:
+ public override async System.Threading.Tasks.Task Handle(Microsoft.AspNetCore.Http.HttpContext httpContext)
+ {
+ // Reading the request body via JSON deserialization
+ var (command, jsonContinue) = await ReadJsonAsync(httpContext);
+ if (jsonContinue == Wolverine.HandlerContinuation.Stop) return;
+ var validationResult = httpContext.Request.Query["validationResult"];
+ var tuple = WolverineWebApiFSharp.TupleSupport.ValidationSupport.Validate(command);
+
+ // The actual HTTP request handler execution
+ var result_of_post = WolverineWebApiFSharp.TupleSupport.ValidationSupport.post(command, validationResult);
+
+ await WriteString(httpContext, result_of_post);
+ }
+ *)
+
+ let Validate (command: Command) =
+ if String.IsNullOrWhiteSpace(command.SomeProperty) then
+ ProblemDetails(Status = 400), ""
+ else
+ WolverineContinue.NoProblems, command.SomeProperty
+
+
+ []
+ let post (command: Command, validationResult: string) =
+ validationResult
+
+
+module CascadingMessages =
+ (* Codegen looks like this
+ public override async System.Threading.Tasks.Task Handle(Microsoft.AspNetCore.Http.HttpContext httpContext)
+ {
+ // Reading the request body via JSON deserialization
+ var (command, jsonContinue) = await ReadJsonAsync(httpContext);
+ if (jsonContinue == Wolverine.HandlerContinuation.Stop) return;
+
+ // The actual HTTP request handler execution
+ var tuple_response = WolverineWebApiFSharp.TupleSupport.AdditionalReturnValues.post(command);
+
+ // Writing the response body to JSON because this was the first 'return variable' in the method signature
+ await WriteJsonAsync(httpContext, tuple_response);
+ }
+ *)
+
+ type Event = { Id: Guid }
+
+ []
+ let post (command: Command) =
+ let event = { Id = Guid.NewGuid() }
+ event.Id, event
\ No newline at end of file
diff --git a/WolverineWebApiFSharp/UnitSupport.fs b/WolverineWebApiFSharp/UnitSupport.fs
new file mode 100644
index 000000000..4476fe2ef
--- /dev/null
+++ b/WolverineWebApiFSharp/UnitSupport.fs
@@ -0,0 +1,43 @@
+namespace WolverineWebApiFSharp.UnitSupport
+
+open System.Threading.Tasks
+open Wolverine.Http
+
+type Command = { SomeProperty: string }
+
+// In F# the type Unit defines the absence of a value, similar to void in C#.
+// In C# it is represented as a Task with no result, which is equivalent to Task.
+// But the codegen treats the Unit type as a regular type and generates a cascaded message call for it.
+// I've only encountered this in the context of Task handlers, but will add more examples if I find them.
+
+module TaskUnitSupport =
+ (* Codegen looks like this:
+ public override async System.Threading.Tasks.Task Handle(Microsoft.AspNetCore.Http.HttpContext httpContext)
+ {
+ var messageContext = new Wolverine.Runtime.MessageContext(_wolverineRuntime);
+ // Reading the request body via JSON deserialization
+ var (command, jsonContinue) = await ReadJsonAsync(httpContext);
+ if (jsonContinue == Wolverine.HandlerContinuation.Stop) return;
+
+ // The actual HTTP request handler execution
+ var unit = await WolverineWebApiFSharp.UnitSupport.TaskUnitSupport.post(command).ConfigureAwait(false);
+
+
+ // Outgoing, cascaded message
+ await messageContext.EnqueueCascadingAsync(unit).ConfigureAwait(false);
+
+ // Wolverine automatically sets the status code to 204 for empty responses
+ if (httpContext.Response is { HasStarted: false, StatusCode: 200 }) httpContext.Response.StatusCode = 204;
+
+ // Have to flush outgoing messages just in case Marten did nothing because of https://github.com/JasperFx/wolverine/issues/536
+ await messageContext.FlushOutgoingMessagesAsync().ConfigureAwait(false);
+
+ }
+ *)
+
+ []
+ []
+ let post (command: Command) = task {
+ do! Task.Delay 10
+ }
+
\ No newline at end of file
diff --git a/WolverineWebApiFSharp/WolverineWebApiFSharp.fsproj b/WolverineWebApiFSharp/WolverineWebApiFSharp.fsproj
index 48b4ccda3..58ba7eafc 100644
--- a/WolverineWebApiFSharp/WolverineWebApiFSharp.fsproj
+++ b/WolverineWebApiFSharp/WolverineWebApiFSharp.fsproj
@@ -4,14 +4,18 @@
net8.0
true
8.0
+ Exe
+
+
+
diff --git a/docs/guide/durability/efcore/operations.md b/docs/guide/durability/efcore/operations.md
index 92ff00253..c016a1f90 100644
--- a/docs/guide/durability/efcore/operations.md
+++ b/docs/guide/durability/efcore/operations.md
@@ -141,4 +141,7 @@ public static class TodoHandler
Wolverine also supports the usage of the `[Entity]` attribute to load entity data by its identity with EF Core. As you'd
expect, Wolverine can "find" the right EF Core `DbContext` type for the entity type through IoC service registrations.
+The loaded EF core entity does not included related entities.
+For more information on the usage of this attribute see
+[Automatically loading entities to method parameters](/guide/handlers/persistence#automatically-loading-entities-to-method-parameters).
diff --git a/src/Http/Wolverine.Http/HttpChain.EndpointBuilder.cs b/src/Http/Wolverine.Http/HttpChain.EndpointBuilder.cs
index 50de08368..f33d60f65 100644
--- a/src/Http/Wolverine.Http/HttpChain.EndpointBuilder.cs
+++ b/src/Http/Wolverine.Http/HttpChain.EndpointBuilder.cs
@@ -53,7 +53,7 @@ public RouteEndpoint BuildEndpoint(RouteWarmup warmup)
if (Endpoint != null) return Endpoint;
RequestDelegate? requestDelegate = null;
- if (_parent.Rules.TypeLoadMode == TypeLoadMode.Static)
+ if (_parent.Rules.TypeLoadMode == TypeLoadMode.Static && !DynamicCodeBuilder.WithinCodegenCommand)
{
this.InitializeSynchronously(_parent.Rules, _parent, _parent.Container.Services);
var handler = (HttpHandler)_parent.Container.QuickBuild(_handlerType);
diff --git a/src/Http/WolverineWebApi/WolverineWebApi.csproj b/src/Http/WolverineWebApi/WolverineWebApi.csproj
index a7ad3a7a1..87c4cc6cc 100644
--- a/src/Http/WolverineWebApi/WolverineWebApi.csproj
+++ b/src/Http/WolverineWebApi/WolverineWebApi.csproj
@@ -36,6 +36,164 @@
Servers.cs
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Persistence/EfCoreTests/end_to_end_efcore_persistence.cs b/src/Persistence/EfCoreTests/end_to_end_efcore_persistence.cs
index 26cc28ce4..99e066cd4 100644
--- a/src/Persistence/EfCoreTests/end_to_end_efcore_persistence.cs
+++ b/src/Persistence/EfCoreTests/end_to_end_efcore_persistence.cs
@@ -22,6 +22,7 @@
using Wolverine.SqlServer;
using Wolverine.Tracking;
using Wolverine.Transports;
+using IServiceContainer = Wolverine.Runtime.IServiceContainer;
namespace EfCoreTests;
diff --git a/src/Persistence/MartenTests/basic_marten_integration.cs b/src/Persistence/MartenTests/basic_marten_integration.cs
index 47e30ba8b..cd24a828e 100644
--- a/src/Persistence/MartenTests/basic_marten_integration.cs
+++ b/src/Persistence/MartenTests/basic_marten_integration.cs
@@ -15,6 +15,7 @@
using Wolverine.Persistence.Durability;
using Wolverine.Postgresql;
using Wolverine.Runtime;
+using IServiceContainer = Wolverine.Runtime.IServiceContainer;
namespace MartenTests;
diff --git a/src/Persistence/MartenTests/transactional_frame_end_to_end.cs b/src/Persistence/MartenTests/transactional_frame_end_to_end.cs
index dbc9bfdf0..6582dcd27 100644
--- a/src/Persistence/MartenTests/transactional_frame_end_to_end.cs
+++ b/src/Persistence/MartenTests/transactional_frame_end_to_end.cs
@@ -15,6 +15,7 @@
using Wolverine.Marten.Codegen;
using Wolverine.Runtime;
using Wolverine.Runtime.Handlers;
+using IServiceContainer = Wolverine.Runtime.IServiceContainer;
namespace MartenTests;
diff --git a/src/Persistence/Wolverine.Marten/Wolverine.Marten.csproj b/src/Persistence/Wolverine.Marten/Wolverine.Marten.csproj
index 9906f35ee..f2c23f81d 100644
--- a/src/Persistence/Wolverine.Marten/Wolverine.Marten.csproj
+++ b/src/Persistence/Wolverine.Marten/Wolverine.Marten.csproj
@@ -12,7 +12,7 @@
-
+
diff --git a/src/Persistence/Wolverine.RDBMS/MessageDatabase.DeadLetters.cs b/src/Persistence/Wolverine.RDBMS/MessageDatabase.DeadLetters.cs
index 7652baea1..89d3f4841 100644
--- a/src/Persistence/Wolverine.RDBMS/MessageDatabase.DeadLetters.cs
+++ b/src/Persistence/Wolverine.RDBMS/MessageDatabase.DeadLetters.cs
@@ -40,6 +40,11 @@ public async Task QueryDeadLetterEnvelopesAsync(DeadLe
query += $" and {DatabaseConstants.Id} >= @startId";
}
+ if (queryParameters.Limit > 0)
+ {
+ query += " limit @limit";
+ }
+
var command = CreateCommand(query);
if (!string.IsNullOrEmpty(queryParameters.ExceptionType))
@@ -72,15 +77,18 @@ public async Task QueryDeadLetterEnvelopesAsync(DeadLe
command = command.With("startId", queryParameters.StartId.Value);
}
- command.With("limit", queryParameters.Limit);
+ if (queryParameters.Limit > 0)
+ {
+ command = command.With("limit", queryParameters.Limit + 1);
+ }
var deadLetterEnvelopes = (List)await command.FetchListAsync(reader =>
DatabasePersistence.ReadDeadLetterAsync(reader, _cancellation), cancellation: _cancellation);
- if (deadLetterEnvelopes.Count > queryParameters.Limit)
+ if (queryParameters.Limit > 0 && deadLetterEnvelopes.Count > queryParameters.Limit)
{
- deadLetterEnvelopes.RemoveAt(deadLetterEnvelopes.Count - 1);
var nextId = deadLetterEnvelopes.LastOrDefault()?.Envelope.Id;
+ deadLetterEnvelopes.RemoveAt(deadLetterEnvelopes.Count - 1);
return new(deadLetterEnvelopes, nextId, tenantId);
}
diff --git a/src/Testing/CoreTests/Runtime/Handlers/HandlerGraphTests.cs b/src/Testing/CoreTests/Runtime/Handlers/HandlerGraphTests.cs
index a3de0368f..519d815f7 100644
--- a/src/Testing/CoreTests/Runtime/Handlers/HandlerGraphTests.cs
+++ b/src/Testing/CoreTests/Runtime/Handlers/HandlerGraphTests.cs
@@ -1,8 +1,12 @@
-using System.Diagnostics;
+using ImTools;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Module1;
+using System.Diagnostics;
+using System.Reflection;
+using JasperFx.Core.Reflection;
using Wolverine.Attributes;
+using Wolverine.Runtime;
using Wolverine.Runtime.Handlers;
using Wolverine.Util;
using Xunit;
@@ -65,6 +69,25 @@ await Should.ThrowAsync(async () =>
}).StartAsync();
});
}
+
+ [Fact]
+ public async Task Concurrent_Registration_No_Race_Condition()
+ {
+ // just make sure the list consists of at least a couple of messages
+ var typesToRegister = typeof(DummyMessage).Assembly.GetTypes().Where(x => x.Name.EndsWith("Message")).ToArray();
+
+ using var host = await Host.CreateDefaultBuilder()
+ .UseWolverine()
+ .StartAsync();
+
+ var graph = host.Services.GetRequiredService();
+ var runtime = host.Services.GetRequiredService();
+ Parallel.ForEach(typesToRegister, t => runtime.RegisterMessageType(t));
+
+ var missingTypes = typesToRegister.Select(t => t.ToMessageTypeName())
+ .Where(t => graph.TryFindMessageType(t, out var _) is false).ToArray();
+ missingTypes.ShouldBeEmpty();
+ }
}
public class DummyMessage { }
diff --git a/src/Transports/AWS/Wolverine.AmazonSqs.Tests/Internal/AmazonSqsQueueTests.cs b/src/Transports/AWS/Wolverine.AmazonSqs.Tests/Internal/AmazonSqsQueueTests.cs
index 84e2ecad6..0198daa9e 100644
--- a/src/Transports/AWS/Wolverine.AmazonSqs.Tests/Internal/AmazonSqsQueueTests.cs
+++ b/src/Transports/AWS/Wolverine.AmazonSqs.Tests/Internal/AmazonSqsQueueTests.cs
@@ -66,7 +66,8 @@ public void configure_request()
{
MaxNumberOfMessages = 8,
VisibilityTimeout = 3,
- WaitTimeSeconds = 11
+ WaitTimeSeconds = 11,
+ MessageAttributeNames = ["All"],
};
var request = new ReceiveMessageRequest();
@@ -76,6 +77,39 @@ public void configure_request()
request.VisibilityTimeout.ShouldBe(endpoint.VisibilityTimeout);
request.MaxNumberOfMessages.ShouldBe(endpoint.MaxNumberOfMessages);
request.WaitTimeSeconds.ShouldBe(endpoint.WaitTimeSeconds);
+ request.MessageAttributeNames.ShouldBe(endpoint.MessageAttributeNames);
+ }
+
+ [Fact]
+ public void default_message_attribute_names_is_null_on_endpoint()
+ {
+ new AmazonSqsQueue("foo", new AmazonSqsTransport())
+ .MessageAttributeNames.ShouldBeNull();
+ }
+
+ [Fact]
+ public void configure_request_does_not_set_message_attribute_names_when_null()
+ {
+ var endpoint = new AmazonSqsQueue("foo", new AmazonSqsTransport());
+ var request = new ReceiveMessageRequest();
+
+ endpoint.ConfigureRequest(request);
+
+ request.MessageAttributeNames.ShouldBeNull();
+ }
+
+ [Fact]
+ public void configure_request_does_not_set_when_empty_list()
+ {
+ var endpoint = new AmazonSqsQueue("foo", new AmazonSqsTransport())
+ {
+ MessageAttributeNames = []
+ };
+ var request = new ReceiveMessageRequest();
+
+ endpoint.ConfigureRequest(request);
+
+ request.MessageAttributeNames.ShouldBeNull();
}
}
diff --git a/src/Transports/AWS/Wolverine.AmazonSqs/Internal/AmazonSqsQueue.cs b/src/Transports/AWS/Wolverine.AmazonSqs/Internal/AmazonSqsQueue.cs
index 648d249f1..3a051b5d4 100644
--- a/src/Transports/AWS/Wolverine.AmazonSqs/Internal/AmazonSqsQueue.cs
+++ b/src/Transports/AWS/Wolverine.AmazonSqs/Internal/AmazonSqsQueue.cs
@@ -90,6 +90,13 @@ public int VisibilityTimeout
///
public string? DeadLetterQueueName { get; set; } = AmazonSqsTransport.DeadLetterQueueName;
+ ///
+ /// Optional list of message attribute names to request in ReceiveMessage.
+ /// Use "All" to retrieve all message attributes. If null or empty, nothing is requested.
+ /// (Attention: this is different from .)
+ ///
+ public List? MessageAttributeNames { get; set; }
+
public async ValueTask CheckAsync()
{
var response = await _parent.Client!.GetQueueUrlAsync(QueueName);
@@ -299,6 +306,11 @@ internal void ConfigureRequest(ReceiveMessageRequest request)
request.WaitTimeSeconds = WaitTimeSeconds;
request.MaxNumberOfMessages = MaxNumberOfMessages;
request.VisibilityTimeout = VisibilityTimeout;
+
+ if (MessageAttributeNames is { Count: > 0 })
+ {
+ request.MessageAttributeNames = MessageAttributeNames;
+ }
}
public async Task TeardownAsync(IAmazonSQS client, CancellationToken token)
diff --git a/src/Wolverine/HostBuilderExtensions.cs b/src/Wolverine/HostBuilderExtensions.cs
index c6ddf8589..72ead04a6 100644
--- a/src/Wolverine/HostBuilderExtensions.cs
+++ b/src/Wolverine/HostBuilderExtensions.cs
@@ -20,6 +20,8 @@
using Wolverine.Persistence.Sagas;
using Wolverine.Runtime;
using Wolverine.Runtime.Handlers;
+using IServiceContainer = Wolverine.Runtime.IServiceContainer;
+using ServiceContainer = Wolverine.Runtime.ServiceContainer;
namespace Wolverine;
diff --git a/src/Wolverine/Runtime/Agents/AgentCommandHandler.cs b/src/Wolverine/Runtime/Agents/AgentCommandHandler.cs
index 4fa42e8ed..ceeba537f 100644
--- a/src/Wolverine/Runtime/Agents/AgentCommandHandler.cs
+++ b/src/Wolverine/Runtime/Agents/AgentCommandHandler.cs
@@ -18,7 +18,10 @@ public AgentCommandHandler(WolverineRuntime runtime)
.RetryWithCooldown(50.Milliseconds(), 100.Milliseconds(), 250.Milliseconds())
.Then.Discard();
- Chain.ExecutionLogLevel = LogLevel.Debug;
+ // Reducing log noise
+ Chain.ExecutionLogLevel = LogLevel.None;
+ Chain.ProcessingLogLevel = LogLevel.None;
+ Chain.SuccessLogLevel = LogLevel.None;
Chain.TelemetryEnabled = false;
}
diff --git a/src/Wolverine/Runtime/Handlers/HandlerGraph.cs b/src/Wolverine/Runtime/Handlers/HandlerGraph.cs
index 0b7c25cfe..bf3e3ec84 100644
--- a/src/Wolverine/Runtime/Handlers/HandlerGraph.cs
+++ b/src/Wolverine/Runtime/Handlers/HandlerGraph.cs
@@ -42,6 +42,8 @@ public partial class HandlerGraph : ICodeFileCollectionWithServices, IWithFailur
private bool _hasGrouped;
+ private object _messageTypesLock = new();
+
private ImHashMap _messageTypes = ImHashMap.Empty;
private ImmutableList _replyTypes = ImmutableList.Empty;
@@ -326,24 +328,28 @@ private void tryApplyLocalQueueConfiguration(WolverineOptions options)
private void registerMessageTypes()
{
- _messageTypes =
- _messageTypes.AddOrUpdate(typeof(Acknowledgement).ToMessageTypeName(), typeof(Acknowledgement));
-
- foreach (var chain in Chains)
+ lock (_messageTypesLock)
{
- _messageTypes = _messageTypes.AddOrUpdate(chain.MessageType.ToMessageTypeName(), chain.MessageType);
+ _messageTypes =
+ _messageTypes.AddOrUpdate(typeof(Acknowledgement).ToMessageTypeName(), typeof(Acknowledgement));
- if (chain.MessageType.TryGetAttribute(out var att))
+ foreach (var chain in Chains)
{
- _messageTypes = _messageTypes.AddOrUpdate(att.InteropType.ToMessageTypeName(), chain.MessageType);
- }
- else
- {
- foreach (var @interface in chain.MessageType.GetInterfaces())
+ _messageTypes = _messageTypes.AddOrUpdate(chain.MessageType.ToMessageTypeName(), chain.MessageType);
+
+ if (chain.MessageType.TryGetAttribute(out var att))
{
- if (InteropAssemblies.Contains(@interface.Assembly))
+ _messageTypes = _messageTypes.AddOrUpdate(att.InteropType.ToMessageTypeName(), chain.MessageType);
+ }
+ else
+ {
+ foreach (var @interface in chain.MessageType.GetInterfaces())
{
- _messageTypes = _messageTypes.AddOrUpdate(@interface.ToMessageTypeName(), chain.MessageType);
+ if (InteropAssemblies.Contains(@interface.Assembly))
+ {
+ _messageTypes =
+ _messageTypes.AddOrUpdate(@interface.ToMessageTypeName(), chain.MessageType);
+ }
}
}
}
@@ -457,8 +463,11 @@ public void RegisterMessageType(Type messageType)
return;
}
- _messageTypes = _messageTypes.AddOrUpdate(messageType.ToMessageTypeName(), messageType);
- _replyTypes = _replyTypes.Add(messageType);
+ lock (_messageTypesLock)
+ {
+ _messageTypes = _messageTypes.AddOrUpdate(messageType.ToMessageTypeName(), messageType);
+ _replyTypes = _replyTypes.Add(messageType);
+ }
}
public void RegisterMessageType(Type messageType, string messageAlias)
@@ -473,8 +482,11 @@ public void RegisterMessageType(Type messageType, string messageAlias)
return;
}
- _messageTypes = _messageTypes.AddOrUpdate(messageAlias, messageType);
- _replyTypes = _replyTypes.Add(messageType);
+ lock (_messageTypesLock)
+ {
+ _messageTypes = _messageTypes.AddOrUpdate(messageAlias, messageType);
+ _replyTypes = _replyTypes.Add(messageType);
+ }
}
public IEnumerable AllChains()
diff --git a/src/Wolverine/Wolverine.csproj b/src/Wolverine/Wolverine.csproj
index ea05bb39c..062f29b2b 100644
--- a/src/Wolverine/Wolverine.csproj
+++ b/src/Wolverine/Wolverine.csproj
@@ -4,7 +4,7 @@
WolverineFx
-
+