Skip to content

Commit

Permalink
Redesigned registration of SNS handlers
Browse files Browse the repository at this point in the history
  • Loading branch information
Kralizek committed Oct 28, 2022
1 parent 49f9641 commit b27ad44
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 13 deletions.
4 changes: 1 addition & 3 deletions samples/SnsEventFunctionWithParallelism/Function.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,7 @@ protected override void ConfigureLogging(ILoggingBuilder logging, IExecutionEnvi

protected override void ConfigureServices(IServiceCollection services, IExecutionEnvironment executionEnvironment)
{
services.ConfigureSnsParallelExecution(4);

services.UseNotificationHandler<CustomNotification, CustomNotificationHandler>(enableParallelExecution: true);
services.UseNotificationHandler<CustomNotification, CustomNotificationHandler>().WithParallelExecution(maxDegreeOfParallelism: 4);
}
}

Expand Down
74 changes: 65 additions & 9 deletions src/Kralizek.Lambda.Template.Sns/ServiceCollectionExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,38 +1,94 @@
using System;
using Amazon.Lambda.SNSEvents;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;

namespace Kralizek.Lambda
{
public static class ServiceCollectionExtensions
{
[Obsolete("Use `services.UseNotificationHandler<TNotification,THandler>().UseParallelExecution(maxDegreeOfParallelism);` instead.")]
public static IServiceCollection ConfigureSnsParallelExecution(this IServiceCollection services, int maxDegreeOfParallelism)
{
services.Configure<ParallelSnsExecutionOptions>(option => option.MaxDegreeOfParallelism = maxDegreeOfParallelism);

return services;
}

public static IServiceCollection UseNotificationHandler<TNotification, THandler>(this IServiceCollection services, bool enableParallelExecution = false)
public static INotificationHandlerConfigurator<TNotification> WithParallelExecution<TNotification>(this INotificationHandlerConfigurator<TNotification> configurator, int? maxDegreeOfParallelism = null)
where TNotification : class
where THandler : class, INotificationHandler<TNotification>
{
services.AddOptions();
ArgumentNullException.ThrowIfNull(configurator);

services.AddSingleton<INotificationSerializer, DefaultJsonNotificationSerializer>();
if (maxDegreeOfParallelism <= 1) throw new ArgumentOutOfRangeException(nameof(maxDegreeOfParallelism), $"{nameof(maxDegreeOfParallelism)} must be greater than 1");

if (enableParallelExecution)
configurator.Services.AddTransient<IEventHandler<SNSEvent>, ParallelSnsEventHandler<TNotification>>();

if (maxDegreeOfParallelism.HasValue)
{
services.AddTransient<IEventHandler<SNSEvent>, ParallelSnsEventHandler<TNotification>>();
configurator.Services.Configure<ParallelSnsExecutionOptions>(options => options.MaxDegreeOfParallelism = maxDegreeOfParallelism.Value);
}
else

return configurator;
}

public static IServiceCollection UseCustomNotificationSerializer<TSerializer>(this IServiceCollection services, ServiceLifetime lifetime = ServiceLifetime.Singleton)
where TSerializer : INotificationSerializer
{
ArgumentNullException.ThrowIfNull(services);

services.Add(ServiceDescriptor.Describe(typeof(INotificationSerializer), typeof(TSerializer), lifetime));

return services;
}

[Obsolete("Use `services.UseNotificationHandler<TNotification,THandler>().UseParallelExecution();` instead.")]
public static IServiceCollection UseNotificationHandler<TNotification, THandler>(this IServiceCollection services, bool enableParallelExecution)
where TNotification : class
where THandler : class, INotificationHandler<TNotification>
{
var configurator = UseNotificationHandler<TNotification, THandler>(services);

if (enableParallelExecution)
{
services.AddTransient<IEventHandler<SNSEvent>, SnsEventHandler<TNotification>>();
configurator.WithParallelExecution();
}

return services;
}

public static INotificationHandlerConfigurator<TNotification> UseNotificationHandler<TNotification, THandler>(this IServiceCollection services)
where TNotification : class
where THandler : class, INotificationHandler<TNotification>
{
services.AddOptions();

services.AddTransient<IEventHandler<SNSEvent>, SnsEventHandler<TNotification>>();

services.TryAddSingleton<INotificationSerializer, DefaultJsonNotificationSerializer>();

services.AddTransient<INotificationHandler<TNotification>, THandler>();

return services;
var configurator = new NotificationHandlerConfigurator<TNotification>(services);

return configurator;
}
}

public interface INotificationHandlerConfigurator<TNotification>
where TNotification : class
{
IServiceCollection Services { get; }
}

internal sealed class NotificationHandlerConfigurator<TNotification> : INotificationHandlerConfigurator<TNotification>
where TNotification : class
{
public NotificationHandlerConfigurator(IServiceCollection services)
{
Services = services ?? throw new ArgumentNullException(nameof(services));
}

public IServiceCollection Services { get; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,31 @@ public void UseNotificationHandler_registers_default_SnsEventHandler()
}

[Test]
public void UseNotificationHandler_registers_ParallelSnsEventHandler_when_parallel_execution_is_enabled()
public void UseNotificationHandler_registers_ParallelSnsEventHandler_when_parallel_execution_is_enabled_obsolete()
{
var services = new ServiceCollection();

services.AddLogging();

#pragma warning disable CS0618
services.UseNotificationHandler<TestNotification, TestNotificationHandler>(enableParallelExecution: true);
#pragma warning restore CS0618

var serviceProvider = services.BuildServiceProvider();

var handler = serviceProvider.GetRequiredService<IEventHandler<SNSEvent>>();

Assert.That(handler, Is.InstanceOf<ParallelSnsEventHandler<TestNotification>>());
}

[Test]
public void UseNotificationHandler_registers_ParallelSnsEventHandler_when_parallel_execution_is_enabled()
{
var services = new ServiceCollection();

services.AddLogging();

services.UseNotificationHandler<TestNotification, TestNotificationHandler>().WithParallelExecution();

var serviceProvider = services.BuildServiceProvider();

Expand Down Expand Up @@ -67,5 +85,28 @@ public void UseNotificationHandler_registers_INotificationSerializer()

serviceProvider.GetRequiredService<INotificationSerializer>();
}

[Test]
public void UseCustomNotificationSerializer_registers_custom_serializer()
{
var services = new ServiceCollection();

services.AddLogging();

services.UseNotificationHandler<TestNotification, TestNotificationHandler>();

services.UseCustomNotificationSerializer<TestSerializer>();

var serviceProvider = services.BuildServiceProvider();

var serializer = serviceProvider.GetRequiredService<INotificationSerializer>();

Assert.That(serializer, Is.InstanceOf<TestSerializer>());
}

private class TestSerializer : INotificationSerializer
{
public TMessage Deserialize<TMessage>(string input) => default;
}
}
}

0 comments on commit b27ad44

Please sign in to comment.