-
Notifications
You must be signed in to change notification settings - Fork 259
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add base mapper feat: updated messagemapper to use native json serializer
- Loading branch information
1 parent
3950599
commit 8856ee8
Showing
8 changed files
with
341 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
using System; | ||
using BenchmarkDotNet.Attributes; | ||
|
||
namespace Paramore.Brighter.Perf | ||
{ | ||
public class Benchmark | ||
{ | ||
private readonly JsonMessageMapper<TestCommand> _jsonMessageMapper; | ||
private readonly JsonMessageMapper2<TestCommand> _mapper2; | ||
private readonly Message _message; | ||
private readonly TestCommand _testCommand; | ||
|
||
public Benchmark() | ||
{ | ||
RequestContext requestContext = new RequestContext(); | ||
_jsonMessageMapper = new JsonMessageMapper<TestCommand>(requestContext); | ||
_mapper2 = new JsonMessageMapper2<TestCommand>(requestContext); | ||
|
||
DateTime dateTime = DateTime.UtcNow; | ||
_testCommand = new TestCommand | ||
{ | ||
Message = "This is a message", | ||
Number = 999, | ||
DateNow = dateTime | ||
}; | ||
|
||
string body = | ||
"{\"message\":\"This is a message\",\"number\":999,\"dateNow\":\"2019-04-09T15:06:56.7623017Z\",\"id\":\"7d9120b9-a18e-43ac-a63e-8201a43ea623\"}"; | ||
Guid correlationId = Guid.NewGuid(); | ||
_message = new Message( | ||
new MessageHeader(new Guid("7d9120b9-a18e-43ac-a63e-8201a43ea623"), "Blah", MessageType.MT_COMMAND, | ||
correlationId), new MessageBody(body)); | ||
} | ||
|
||
[Benchmark] | ||
public void MapToMessageJsonByte() | ||
{ | ||
_jsonMessageMapper.MapToMessage(_testCommand); | ||
} | ||
|
||
[Benchmark] | ||
public void MapFromMessageJsonByte() | ||
{ | ||
_jsonMessageMapper.MapToRequest(_message); | ||
} | ||
|
||
[Benchmark] | ||
public void MapToMessageJsonString() | ||
{ | ||
_mapper2.MapToMessage(_testCommand); | ||
} | ||
|
||
[Benchmark] | ||
public void MapFromMessageJsonString() | ||
{ | ||
_mapper2.MapToRequest(_message); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<OutputType>Exe</OutputType> | ||
<TargetFramework>netcoreapp2.2</TargetFramework> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="BenchmarkDotNet" Version="0.11.5" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\src\Paramore.Brighter\Paramore.Brighter.csproj" /> | ||
</ItemGroup> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
using System; | ||
using BenchmarkDotNet.Running; | ||
|
||
namespace Paramore.Brighter.Perf | ||
{ | ||
class Program | ||
{ | ||
static void Main(string[] args) | ||
{ | ||
var summary = BenchmarkRunner.Run<Benchmark>(); | ||
Console.WriteLine(summary); | ||
} | ||
} | ||
|
||
|
||
public class TestCommand : Command | ||
{ | ||
public TestCommand() : base(Guid.NewGuid()) | ||
{ | ||
} | ||
|
||
public string Message { get; set; } | ||
public int Number { get; set; } | ||
public DateTime DateNow { get; set; } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
using System; | ||
|
||
namespace Paramore.Brighter | ||
{ | ||
public abstract class BaseMessageMapper<T> : IAmAMessageMapper<T> where T : class, IRequest | ||
{ | ||
private readonly IRequestContext _requestContext; | ||
private readonly Func<T, string> _routingAction; | ||
private readonly RoutingKey _routingKey; | ||
|
||
protected BaseMessageMapper(IRequestContext requestContext, RoutingKey routingKey = null, Func<T, string> routingKeyFunc = null) | ||
{ | ||
_requestContext = requestContext; | ||
_routingKey = routingKey; | ||
_routingAction = routingKeyFunc; | ||
} | ||
|
||
public Message MapToMessage(T request) | ||
{ | ||
MessageType messageType = request switch | ||
{ | ||
Command _ => MessageType.MT_COMMAND, | ||
Event _ => MessageType.MT_EVENT, | ||
_ => throw new ArgumentException("This message mapper can only map Commands and Events", nameof(request)) | ||
}; | ||
|
||
var topic = _routingAction?.Invoke(request) ?? _routingKey ?? request.GetType().Name; | ||
|
||
var messageHeader = new MessageHeader(request.Id, topic, messageType, _requestContext.Header.CorrelationId, contentType: "application/json"); | ||
|
||
return new Message(messageHeader, CreateMessageBody(request)); | ||
} | ||
|
||
protected abstract MessageBody CreateMessageBody(T request); | ||
|
||
public T MapToRequest(Message message) | ||
{ | ||
_requestContext.Header.CorrelationId = message.Header.CorrelationId; | ||
|
||
return CreateType(message); | ||
} | ||
|
||
protected abstract T CreateType(Message message); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
using System; | ||
using System.Text.Json; | ||
|
||
namespace Paramore.Brighter | ||
{ | ||
public class JsonMessageMapper<T> : BaseMessageMapper<T> where T : class, IRequest | ||
{ | ||
public JsonMessageMapper(IRequestContext requestContext, RoutingKey routingKey = null, | ||
Func<T, string> routingKeyFunc = null) : base(requestContext, routingKey, routingKeyFunc) | ||
{ | ||
} | ||
|
||
protected override MessageBody CreateMessageBody(T request) | ||
{ | ||
return new MessageBody(JsonSerializer.SerializeToUtf8Bytes(request, JsonSerialisationOptions.Options), "JSON"); | ||
} | ||
|
||
protected override T CreateType(Message message) | ||
{ | ||
return JsonSerializer.Deserialize<T>(message.Body.Bytes, JsonSerialisationOptions.Options); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
162 changes: 162 additions & 0 deletions
162
tests/Paramore.Brighter.Core.Tests/MessageMapper/JsonMessageMapperTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
using System; | ||
using Xunit; | ||
|
||
namespace Paramore.Brighter.Core.Tests.MessageMapper | ||
{ | ||
public class JsonMessageMapperTests | ||
{ | ||
[Fact] | ||
public void When_mapping_an_event_to_a_message_as_json() | ||
{ | ||
var requestContext = new RequestContext(); | ||
|
||
var mapper = new JsonMessageMapper<TestedEvent>(requestContext); | ||
|
||
DateTime dateTime = DateTime.UtcNow; | ||
TestedEvent testedEvent = new TestedEvent | ||
{ | ||
Message = "This is a message", | ||
Number = 999, | ||
DateNow = dateTime | ||
}; | ||
|
||
requestContext.Header.CorrelationId = Guid.NewGuid(); | ||
|
||
var message = mapper.MapToMessage(testedEvent); | ||
|
||
// Message checks | ||
Assert.Equal(testedEvent.Id, message.Id); | ||
|
||
// Header checks | ||
Assert.Equal("application/json", message.Header.ContentType); | ||
Assert.Equal("TestedEvent", message.Header.Topic); | ||
Assert.Equal(MessageType.MT_EVENT , message.Header.MessageType); | ||
Assert.Equal( requestContext.Header.CorrelationId , message.Header.CorrelationId); | ||
|
||
// Body checks | ||
Assert.Equal("JSON", message.Body.BodyType); | ||
Assert.Equal($"{{\"message\":\"{testedEvent.Message}\",\"number\":{testedEvent.Number},\"dateNow\":\"{dateTime:yyyy-MM-ddTHH:mm:ss.FFFFFFFK}\",\"id\":\"{testedEvent.Id}\"}}", message.Body.Value); | ||
// Why not just datetime:O well the JsonSerializer does 7 decimal places with no trailing zeros, format "O" does 7 decimal places with trailing zeros | ||
} | ||
|
||
|
||
[Fact] | ||
public void When_mapping_a_command_to_a_message_as_json() | ||
{ | ||
var requestContext = new RequestContext(); | ||
|
||
var mapper = new JsonMessageMapper<TestCommand>(requestContext); | ||
|
||
DateTime dateTime = DateTime.UtcNow; | ||
TestCommand testCommand = new TestCommand | ||
{ | ||
Message = "This is a message", | ||
Number = 999, | ||
DateNow = dateTime | ||
}; | ||
|
||
requestContext.Header.CorrelationId = Guid.NewGuid(); | ||
|
||
var message = mapper.MapToMessage(testCommand); | ||
|
||
// Message checks | ||
Assert.Equal(testCommand.Id, message.Id); | ||
|
||
// Header checks | ||
Assert.Equal("application/json", message.Header.ContentType); | ||
Assert.Equal("TestCommand", message.Header.Topic); | ||
Assert.Equal(MessageType.MT_COMMAND , message.Header.MessageType); | ||
Assert.Equal( requestContext.Header.CorrelationId , message.Header.CorrelationId); | ||
|
||
// Body checks | ||
Assert.Equal("JSON", message.Body.BodyType); | ||
Assert.Equal($"{{\"message\":\"{testCommand.Message}\",\"number\":{testCommand.Number},\"dateNow\":\"{dateTime:yyyy-MM-ddTHH:mm:ss.FFFFFFFK}\",\"id\":\"{testCommand.Id}\"}}", message.Body.Value); | ||
} | ||
|
||
[Fact] | ||
public void when_mapping_to_a_command_from_json() | ||
{ | ||
var requestContext = new RequestContext(); | ||
var mapper = new JsonMessageMapper<TestCommand>(requestContext); | ||
|
||
|
||
var body = "{\"message\":\"This is a message\",\"number\":999,\"dateNow\":\"2019-04-09T15:06:56.7623017Z\",\"id\":\"7d9120b9-a18e-43ac-a63e-8201a43ea623\"}"; | ||
var correlationId = Guid.NewGuid(); | ||
var message = new Message(new MessageHeader(new Guid("7d9120b9-a18e-43ac-a63e-8201a43ea623"),"Blah", MessageType.MT_COMMAND, correlationId: correlationId), new MessageBody(body)); | ||
|
||
var testCommand = mapper.MapToRequest(message); | ||
|
||
|
||
Assert.Equal("7d9120b9-a18e-43ac-a63e-8201a43ea623", testCommand.Id.ToString()); | ||
Assert.Equal("This is a message", testCommand.Message); | ||
Assert.Equal(999, testCommand.Number); | ||
Assert.Equal(DateTime.Parse("2019-04-09T15:06:56.7623017Z").ToUniversalTime(), testCommand.DateNow); | ||
|
||
Assert.Equal(correlationId, requestContext.Header.CorrelationId); | ||
} | ||
|
||
[Fact] | ||
public void When_mapping_with_custom_routing_key_to_a_message() | ||
{ | ||
var mapper = new JsonMessageMapper<TestCommand>(new RequestContext(), new RoutingKey("MyTestRoute")); | ||
|
||
var testCommand = new TestCommand(); | ||
|
||
var message = mapper.MapToMessage(testCommand); | ||
|
||
Assert.Equal("MyTestRoute", message.Header.Topic); | ||
} | ||
|
||
[Fact] | ||
public void When_mapping_with_custom_routing_key_to_a_message2() | ||
{ | ||
var mapper = new JsonMessageMapper<TestCommand>(new RequestContext(), routingKeyFunc: request => | ||
{ | ||
string topic = "TestPreAmble."; | ||
|
||
string name = request.GetType().Name; | ||
|
||
if (name.EndsWith("Command", StringComparison.InvariantCultureIgnoreCase)) | ||
topic = topic + name.Replace("Command", "", StringComparison.InvariantCultureIgnoreCase); | ||
else if (name.EndsWith("Event", StringComparison.InvariantCultureIgnoreCase)) | ||
topic = topic + name.Replace("Event", "", StringComparison.InvariantCultureIgnoreCase); | ||
else | ||
{ | ||
topic = topic + name; | ||
} | ||
|
||
return topic; | ||
} ); | ||
|
||
var testCommand = new TestCommand(); | ||
|
||
var message = mapper.MapToMessage(testCommand); | ||
|
||
Assert.Equal("TestPreAmble.Test", message.Header.Topic); | ||
} | ||
|
||
|
||
} | ||
|
||
public class TestCommand : Command | ||
{ | ||
public TestCommand() : base(Guid.NewGuid()) | ||
{ | ||
} | ||
|
||
public string Message { get; set; } | ||
public int Number { get; set; } | ||
public DateTime DateNow { get; set; } | ||
} | ||
|
||
public class TestedEvent : Event | ||
{ | ||
public TestedEvent() : base(Guid.NewGuid()) | ||
{ | ||
} | ||
|
||
public string Message { get; set; } | ||
public int Number { get; set; } | ||
public DateTime DateNow { get; set; } | ||
} | ||
} |