Skip to content

Commit

Permalink
Add non-reflection way of dispatching events
Browse files Browse the repository at this point in the history
  • Loading branch information
smatsson committed Oct 12, 2021
1 parent 6bab00a commit 00b692b
Show file tree
Hide file tree
Showing 5 changed files with 202 additions and 6 deletions.
83 changes: 83 additions & 0 deletions Source/tusdotnet.benchmark/Benchmarks/EventHelperBenchmark.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
using BenchmarkDotNet.Attributes;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using tusdotnet.Adapters;
using tusdotnet.Helpers;
using tusdotnet.Helpers.Internal;
using tusdotnet.Models;
using tusdotnet.Models.Configuration;

namespace tusdotnet.benchmark.Benchmarks
{
[MemoryDiagnoser]
public class EventHelperBenchmark
{
private static ContextAdapter _context = new ContextAdapter
{
Request = new RequestAdapter("/files")
{
RequestUri = new Uri("http://localhost/files/file1")
},
Configuration = new DefaultTusConfiguration
{
Events = new Events
{
OnAuthorizeAsync = ctx =>
{
return Task.CompletedTask;
},

OnBeforeCreateAsync = ctx =>
{
return Task.CompletedTask;
},
OnCreateCompleteAsync = ctx =>
{
return Task.CompletedTask;
},
OnBeforeDeleteAsync = ctx =>
{
return Task.CompletedTask;
},
OnDeleteCompleteAsync = ctx =>
{
return Task.CompletedTask;
},
OnFileCompleteAsync = ctx =>
{
return Task.CompletedTask;
}
},
},
CancellationToken = System.Threading.CancellationToken.None
};

[Benchmark(Baseline = true)]
public async Task EventHelperReflectionBased()
{
await EventHelper.Validate<AuthorizeContext>(_context);
await EventHelper.Validate<BeforeCreateContext>(_context);
await EventHelper.Validate<BeforeDeleteContext>(_context);

await EventHelper.Notify<CreateCompleteContext>(_context);
await EventHelper.Notify<DeleteCompleteContext>(_context);

await EventHelper.NotifyFileComplete(_context);
}

[Benchmark]
public async Task EventHelperPatternMatchingBased()
{
await EventHelperPatternMatching.Validate<AuthorizeContext>(_context);
await EventHelperPatternMatching.Validate<BeforeCreateContext>(_context);
await EventHelperPatternMatching.Validate<BeforeDeleteContext>(_context);

await EventHelperPatternMatching.Notify<CreateCompleteContext>(_context);
await EventHelperPatternMatching.Notify<DeleteCompleteContext>(_context);

await EventHelperPatternMatching.NotifyFileComplete(_context);
}
}
}
4 changes: 3 additions & 1 deletion Source/tusdotnet.benchmark/Program.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System;
using System.Threading.Tasks;
using BenchmarkDotNet.Running;
//using tusdotnet.benchmark.Benchmarks;
using tusdotnet.benchmark.Benchmarks;

namespace tusdotnet.benchmark
{
Expand All @@ -13,6 +13,8 @@ public static void Main()
//var summary = BenchmarkRunner.Run<NoTusResumableHeader>();
//var summary = BenchmarkRunner.Run<RequestIsNotForTusEndpoint>();

var summary = BenchmarkRunner.Run<EventHelperBenchmark>();

//new MetadataParser().TestNewWithTextRead();
//Test().GetAwaiter().GetResult();
}
Expand Down
4 changes: 0 additions & 4 deletions Source/tusdotnet.benchmark/tusdotnet.benchmark.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,4 @@
<ProjectReference Include="..\tusdotnet\tusdotnet.csproj" />
</ItemGroup>

<ItemGroup>
<Folder Include="Benchmarks\" />
</ItemGroup>

</Project>
115 changes: 115 additions & 0 deletions Source/tusdotnet/Helpers/Internal/EventHelperPatternMatching.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
using System;
using System.Threading.Tasks;
using tusdotnet.Adapters;
using tusdotnet.Extensions;
using tusdotnet.Models;
using tusdotnet.Models.Configuration;

namespace tusdotnet.Helpers.Internal
{
internal class EventHelperPatternMatching
{
internal static async Task<ResultType> Validate<T>(ContextAdapter context, Action<T> configure = null) where T : ValidationContext<T>, new()
{
var handler = GetRegisteredHandler<T>(context);

if (handler == null)
return ResultType.ContinueExecution;

var eventContext = EventContext<T>.Create(context, configure);

await handler(eventContext);

if (eventContext.HasFailed)
{
var includeTusResumableHeaderInResponse = true;
// Do not leak information on the tus endpoint during authorization.
if (eventContext is EventContext<AuthorizeContext>)
{
includeTusResumableHeaderInResponse = false;
}
await context.Response.Error(eventContext.StatusCode, eventContext.ErrorMessage, includeTusResumableHeaderInResponse);
return ResultType.StopExecution;
}

return ResultType.ContinueExecution;
}

internal static async Task Notify<T>(ContextAdapter context, Action<T> configure = null) where T : EventContext<T>, new()
{
var handler = GetRegisteredHandler<T>(context);

if (handler == null)
{
return;
}

var eventContext = EventContext<T>.Create(context, configure);

await handler(eventContext);
}

private static Func<T, Task> GetRegisteredHandler<T>(ContextAdapter context) where T : EventContext<T>, new()
{
var events = context.Configuration.Events;

if (events == null)
{
return null;
}

var t = typeof(T);

if (t == typeof(AuthorizeContext))
return (Func<T, Task>)events.OnAuthorizeAsync;

if (t == typeof(BeforeCreateContext))
return (Func<T, Task>)events.OnBeforeCreateAsync;

if (t == typeof(CreateCompleteContext))
return (Func<T, Task>)events.OnCreateCompleteAsync;

if (t == typeof(BeforeDeleteContext))
return (Func<T, Task>)events.OnBeforeDeleteAsync;

if (t == typeof(DeleteCompleteContext))
return (Func<T, Task>)events.OnDeleteCompleteAsync;

return null;


// return true switch
//{
// var _ when t == typeof(AuthorizeContext) => (Func<T, Task>)events.OnAuthorizeAsync,
// var _ when t == typeof(BeforeCreateContext) => (Func<T, Task>)events.OnBeforeCreateAsync,
// var _ when t == typeof(CreateCompleteContext) => (Func<T, Task>)events.OnCreateCompleteAsync,
// var _ when t == typeof(BeforeDeleteContext) => (Func<T, Task>)events.OnBeforeDeleteAsync,
// var _ when t == typeof(DeleteCompleteContext) => (Func<T, Task>)events.OnDeleteCompleteAsync,
// _ => null,
//};

}

internal static async Task NotifyFileComplete(ContextAdapter context, Action<FileCompleteContext> configure = null)
{
#pragma warning disable CS0618 // Type or member is obsolete
if (context.Configuration.OnUploadCompleteAsync == null && context.Configuration.Events?.OnFileCompleteAsync == null)
{
return;
}

var eventContext = FileCompleteContext.Create(context, configure);

if (context.Configuration.OnUploadCompleteAsync != null)
{
await context.Configuration.OnUploadCompleteAsync(eventContext.FileId, eventContext.Store, eventContext.CancellationToken);
}
#pragma warning restore CS0618 // Type or member is obsolete

if (context.Configuration.Events?.OnFileCompleteAsync != null)
{
await context.Configuration.Events.OnFileCompleteAsync(eventContext);
}
}
}
}
2 changes: 1 addition & 1 deletion Source/tusdotnet/tusdotnet.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<Copyright>Copyright Stefan Matsson 2016</Copyright>
<AssemblyTitle>tusdotnet</AssemblyTitle>
<Authors>Stefan Matsson</Authors>
<TargetFrameworks>net452;netstandard1.3;netstandard2.0;netcoreapp3.1</TargetFrameworks>
<TargetFrameworks><!--net452;--><!--netstandard1.3;netstandard2.0;-->netcoreapp3.1</TargetFrameworks>
<AssemblyName>tusdotnet</AssemblyName>
<PackageId>tusdotnet</PackageId>
<PackageTags>Tus;Tus-Resumable;ResumableFileUploads;FileUpload</PackageTags>
Expand Down

0 comments on commit 00b692b

Please sign in to comment.