Skip to content

Commit

Permalink
Added memoization for the JsonTransformation inside Event Mapping.
Browse files Browse the repository at this point in the history
  • Loading branch information
oskardudycz committed Aug 29, 2022
1 parent 71bd00a commit e6469a4
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 40 deletions.
24 changes: 2 additions & 22 deletions src/Marten/Events/EventDocumentStorage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ public IEvent Resolve(DbDataReader reader)
mapping = eventMappingForDotNetTypeName(dotnetTypeName, eventTypeName);
}

var @event = deserializeEvent(mapping, reader);
var @event = mapping.ReadEventData(reader);

ApplyReaderDataToEvent(reader, @event);

Expand All @@ -246,7 +246,7 @@ public async Task<IEvent> ResolveAsync(DbDataReader reader, CancellationToken to
IEvent @event;
try
{
@event = await deserializeEventAsync(mapping, reader, token).ConfigureAwait(false);
@event = await mapping.ReadEventDataAsync(reader, token).ConfigureAwait(false);
}
catch (Exception e)
{
Expand Down Expand Up @@ -280,25 +280,5 @@ private EventMapping eventMappingForDotNetTypeName(string dotnetTypeName, string

return Events.EventMappingFor(type);
}

private IEvent deserializeEvent(EventMapping mapping, DbDataReader reader)
{
var data = mapping.Transformation != null?
mapping.Transformation.FromDbDataReader(_serializer, reader, 0)
: _serializer.FromJson(mapping.DocumentType, reader, 0);

return mapping.Wrap(data);
}

private async ValueTask<IEvent> deserializeEventAsync(EventMapping mapping, DbDataReader reader,
CancellationToken token)
{
// TODO -- eliminate the runtime logic here
var data = mapping.Transformation != null ?
await mapping.Transformation.FromDbDataReaderAsync(_serializer, reader, 0, token).ConfigureAwait(false)
: await _serializer.FromJsonAsync(mapping.DocumentType, reader, 0, token).ConfigureAwait(false);

return mapping.Wrap(data);
}
}
}
6 changes: 3 additions & 3 deletions src/Marten/Events/EventGraph.cs
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ public IEventStoreOptions Upcast(
{
var eventMapping = EventMappingFor(eventType);
eventMapping.EventTypeName = eventTypeName;
eventMapping.Transformation = jsonTransformation;
eventMapping.JsonTransformation(jsonTransformation);

return this;
}
Expand All @@ -169,7 +169,7 @@ Func<TOldEvent, TEvent> upcast
{
var eventMapping = EventMappingFor<TEvent>();
eventMapping.EventTypeName = eventTypeName;
eventMapping.Transformation = JsonTransformations.Upcast(upcast);
eventMapping.JsonTransformation(JsonTransformations.Upcast(upcast));

return this;
}
Expand All @@ -186,7 +186,7 @@ Func<TOldEvent, CancellationToken, Task<TEvent>> upcastAsync
{
var eventMapping = EventMappingFor<TEvent>();
eventMapping.EventTypeName = eventTypeName;
eventMapping.Transformation = JsonTransformations.Upcast(upcastAsync);
eventMapping.JsonTransformation(JsonTransformations.Upcast(upcastAsync));

return this;
}
Expand Down
69 changes: 54 additions & 15 deletions src/Marten/Events/EventMapping.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ public abstract class EventMapping: IDocumentMapping, IEventType
protected readonly EventGraph _parent;
protected readonly DocumentMapping _inner;
private ISqlFragment _defaultWhereFragment;
private readonly ISerializer _serializer;

protected EventMapping(EventGraph parent, Type eventType)
{
Expand All @@ -65,21 +66,19 @@ protected EventMapping(EventGraph parent, Type eventType)
filter = filter.CombineAnd(CurrentTenantFilter.Instance);
}

_serializer = parent.Options.Serializer();
_defaultWhereFragment = filter;

JsonTransformation(null);
}

Type IEventType.EventType => DocumentType;

public string DotNetTypeName { get; set; }

/// <summary>
/// <para>Defines the event JSON payload transformation. It transforms one event schema into another.
/// You can use it to handle the event schema versioning/migration.</para>
/// <para>By calling it, you tell that instead of the old CLR type, for the specific event type name,
/// you'd like to get the new CLR event type.
/// Provided functions take the deserialized object of the old event type and returns the new, mapped one.</para>
/// </summary>
public JsonTransformation? Transformation { get; set; }
public Func<DbDataReader, IEvent> ReadEventData { get; private set; }

public Func<DbDataReader, CancellationToken, Task<IEvent>> ReadEventDataAsync { get; private set; }

IDocumentMapping IDocumentMapping.Root => this;
public Type DocumentType { get; }
Expand Down Expand Up @@ -150,14 +149,57 @@ public ISqlFragment DefaultWhereFragment()
}

public abstract IEvent Wrap(object data);

/// <summary>
/// <para>Defines the event JSON payload transformation. It transforms one event schema into another.
/// You can use it to handle the event schema versioning/migration.</para>
/// <para>By calling it, you tell that instead of the old CLR type, for the specific event type name,
/// you'd like to get the new CLR event type.
/// Provided functions take the deserialized object of the old event type and returns the new, mapped one.</para>
/// </summary>
/// <param name="jsonTransformation">Json transfromation</param>
public void JsonTransformation(JsonTransformation? jsonTransformation)
{
ReadEventData =
jsonTransformation == null
? reader =>
{
var data = _serializer.FromJson(DocumentType, reader, 0);

return Wrap(data);
}
: reader =>
{
var data = jsonTransformation.FromDbDataReader(_serializer, reader, 0);

return Wrap(data);
}
;

ReadEventDataAsync = jsonTransformation == null
? async (reader, token) =>
{
var data = await _serializer.FromJsonAsync(DocumentType, reader, 0, token)
.ConfigureAwait(false);

return Wrap(data);
}
: async (reader, token) =>
{
var data = await jsonTransformation.FromDbDataReaderAsync(_serializer, reader, 0, token)
.ConfigureAwait(false);

return Wrap(data);
};
}
}

public class EventMapping<T>: EventMapping, IDocumentStorage<T> where T : class
{
private readonly string _tableName;
private Type _idType;

public EventMapping(EventGraph parent) : base(parent, typeof(T))
public EventMapping(EventGraph parent): base(parent, typeof(T))
{
var schemaName = parent.DatabaseSchemaName;
_tableName = schemaName == SchemaConstants.DefaultSchema ? "mt_events" : $"{schemaName}.mt_events";
Expand Down Expand Up @@ -195,7 +237,8 @@ ISelector ISelectClause.BuildSelector(IMartenSession session)
return new EventSelector<T>(session.Serializer);
}

IQueryHandler<TResult> ISelectClause.BuildHandler<TResult>(IMartenSession session, Statement topStatement, Statement currentStatement)
IQueryHandler<TResult> ISelectClause.BuildHandler<TResult>(IMartenSession session, Statement topStatement,
Statement currentStatement)
{
var selector = new EventSelector<T>(session.Serializer);

Expand Down Expand Up @@ -301,11 +344,7 @@ public IDeletion HardDeleteForDocument(T document, string tenantId)

public override IEvent Wrap(object data)
{
return new Event<T>((T) data)
{
EventTypeName = EventTypeName,
DotNetTypeName = DotNetTypeName
};
return new Event<T>((T)data) { EventTypeName = EventTypeName, DotNetTypeName = DotNetTypeName };
}
}

Expand Down

0 comments on commit e6469a4

Please sign in to comment.