Skip to content

Commit

Permalink
Handlers
Browse files Browse the repository at this point in the history
  • Loading branch information
spetz committed Jun 2, 2017
1 parent 5ab43f7 commit 387c097
Show file tree
Hide file tree
Showing 10 changed files with 332 additions and 11 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -271,3 +271,4 @@ __pycache__/

appsettings.local.json
.vscode/
*.DS_Store
24 changes: 15 additions & 9 deletions Passenger.Infrastructure/Handlers/Accounts/LoginHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,30 @@ namespace Passenger.Infrastructure.Handlers.Accounts
{
public class LoginHandler : ICommandHandler<Login>
{
private readonly IHandler _handler;
private readonly IUserService _userService;
private readonly IJwtHandler _jwtHandler;
private readonly IMemoryCache _cache;
public LoginHandler(IUserService userService, IJwtHandler jwtHandler,
IMemoryCache cache)

public LoginHandler(IHandler handler, IUserService userService,
IJwtHandler jwtHandler, IMemoryCache cache)
{
_handler = handler;
_userService = userService;
_jwtHandler = jwtHandler;
_cache = cache;
}

public async Task HandleAsync(Login command)
{
await _userService.LoginAsync(command.Email, command.Password);
var user = await _userService.GetAsync(command.Email);
var jwt = _jwtHandler.CreateToken(user.Id, user.Role);
_cache.SetJwt(command.TokenId, jwt);
}
=> await _handler
.Run(async () => await _userService.LoginAsync(command.Email, command.Password))
.Next()
.Run(async () =>
{
var user = await _userService.GetAsync(command.Email);
var jwt = _jwtHandler.CreateToken(user.Id, user.Role);
_cache.SetJwt(command.TokenId, jwt);
})
.ExecuteAsync();
}
}
31 changes: 31 additions & 0 deletions Passenger.Infrastructure/Services/Handler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace Passenger.Infrastructure.Services
{
public class Handler : IHandler
{
private readonly ISet<IHandlerTask> _handlerTasks = new HashSet<IHandlerTask>();

public IHandlerTask Run(Func<Task> runAsync)
{
var handlerTask = new HandlerTask(this, runAsync);
_handlerTasks.Add(handlerTask);

return handlerTask;
}

public IHandlerTaskRunner Validate(Func<Task> validateAsync)
=> new HandlerTaskRunner(this, validateAsync, _handlerTasks);

public async Task ExecuteAllAsync()
{
foreach (var handlerTask in _handlerTasks)
{
await handlerTask.ExecuteAsync();
}
_handlerTasks.Clear();
}
}
}
163 changes: 163 additions & 0 deletions Passenger.Infrastructure/Services/HandlerTask.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
using System;
using System.Threading.Tasks;
using NLog;
using Passenger.Core.Domain;

namespace Passenger.Infrastructure.Services
{
public class HandlerTask : IHandlerTask
{
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
private readonly IHandler _handler;
private readonly Func<Task> _runAsync;
private Func<Task> _validateAsync;
private Func<Task> _alwaysAsync;
private Func<Task> _onSuccessAsync;
private Func<Exception, Task> _onErrorAsync;
private Func<Exception, Logger, Task> _onErrorWithLoggerAsync;
private Func<PassengerException, Task> _onCustomErrorAsync;
private Func<PassengerException, Logger, Task> _onCustomErrorWithLoggerAsync;
private bool _propagateException = true;
private bool _executeOnError = true;

public HandlerTask(IHandler handler, Func<Task> runAsync)
{
_handler = handler;
_runAsync = runAsync;
}

public HandlerTask(IHandler handler, Func<Task> runAsync,
Func<Task> validateAsync = null)
{
_handler = handler;
_runAsync = runAsync;
_validateAsync = validateAsync;
}

public IHandlerTask Always(Func<Task> always)
{
_alwaysAsync = always;

return this;
}

public IHandlerTask OnCustomError(Func<PassengerException, Task> onCustomError,
bool propagateException = false, bool executeOnError = false)
{
_onCustomErrorAsync = onCustomError;
_propagateException = propagateException;
_executeOnError = executeOnError;

return this;
}

public IHandlerTask OnCustomError(Func<PassengerException, Logger, Task> onCustomError,
bool propagateException = false, bool executeOnError = false)
{
_onCustomErrorWithLoggerAsync = onCustomError;
_propagateException = propagateException;
_executeOnError = executeOnError;

return this;
}

public IHandlerTask OnError(Func<Exception, Task> onError, bool propagateException = false)
{
_onErrorAsync = onError;
_propagateException = propagateException;

return this;
}

public IHandlerTask OnError(Func<Exception, Logger, Task> onError, bool propagateException = false)
{
_onErrorWithLoggerAsync = onError;
_propagateException = propagateException;

return this;
}

public IHandlerTask OnSuccess(Func<Task> onSuccess)
{
_onSuccessAsync = onSuccess;

return this;
}

public IHandlerTask PropagateException()
{
_propagateException = true;

return this;
}

public IHandlerTask DoNotPropagateException()
{
_propagateException = false;

return this;
}

public IHandler Next() => _handler;

public async Task ExecuteAsync()
{
try
{
if(_validateAsync != null)
{
await _validateAsync();
}
await _runAsync();
if(_onSuccessAsync != null)
{
await _onSuccessAsync();
}
}
catch (Exception exception)
{
await HandleExceptionAsync(exception);
if(_propagateException)
{
throw;
}
}
finally
{
if (_alwaysAsync != null)
{
await _alwaysAsync();
}
}
}

private async Task HandleExceptionAsync(Exception exception)
{
var customException = exception as PassengerException;
if (customException != null)
{
if (_onCustomErrorWithLoggerAsync != null)
{
await _onCustomErrorWithLoggerAsync(customException, Logger);
}
if (_onCustomErrorAsync != null)
{
await _onCustomErrorAsync(customException);
}
}

var executeOnError = _executeOnError || customException == null;
if (executeOnError)
{
if (_onErrorWithLoggerAsync != null)
{
await _onErrorWithLoggerAsync(exception, Logger);
}
if (_onErrorAsync != null)
{
await _onErrorAsync(exception);
}
}
}
}
}
30 changes: 30 additions & 0 deletions Passenger.Infrastructure/Services/HandlerTaskRunner.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace Passenger.Infrastructure.Services
{
public class HandlerTaskRunner : IHandlerTaskRunner
{
private readonly IHandler _handler;
private readonly Func<Task> _validateAsync;
private readonly ISet<IHandlerTask> _handlerTasks;

public HandlerTaskRunner(IHandler handler,
Func<Task> validateAsync, ISet<IHandlerTask> handlerTasks)
{
_handler = handler;
_validateAsync = validateAsync;
_handlerTasks = handlerTasks;
}

public IHandlerTask Run(Func<Task> runAsync)
{
var handlerTask = new HandlerTask(_handler, runAsync,
_validateAsync);
_handlerTasks.Add(handlerTask);

return handlerTask;
}
}
}
12 changes: 12 additions & 0 deletions Passenger.Infrastructure/Services/IHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System;
using System.Threading.Tasks;

namespace Passenger.Infrastructure.Services
{
public interface IHandler : IService
{
IHandlerTask Run(Func<Task> runAsync);
IHandlerTaskRunner Validate(Func<Task> validateAsync);
Task ExecuteAllAsync();
}
}
23 changes: 23 additions & 0 deletions Passenger.Infrastructure/Services/IHandlerTask.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using System;
using System.Threading.Tasks;
using NLog;
using Passenger.Core.Domain;

namespace Passenger.Infrastructure.Services
{
public interface IHandlerTask
{
IHandlerTask Always(Func<Task> always);
IHandlerTask OnCustomError(Func<PassengerException, Task> onCustomError,
bool propagateException = false, bool executeOnError = false);
IHandlerTask OnCustomError(Func<PassengerException, Logger, Task> onCustomError,
bool propagateException = false, bool executeOnError = false);
IHandlerTask OnError(Func<Exception, Task> onError, bool propagateException = false);
IHandlerTask OnError(Func<Exception, Logger, Task> onError, bool propagateException = false);
IHandlerTask OnSuccess(Func<Task> onSuccess);
IHandlerTask PropagateException();
IHandlerTask DoNotPropagateException();
IHandler Next();
Task ExecuteAsync();
}
}
10 changes: 10 additions & 0 deletions Passenger.Infrastructure/Services/IHandlerTaskRunner.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using System;
using System.Threading.Tasks;

namespace Passenger.Infrastructure.Services
{
public interface IHandlerTaskRunner
{
IHandlerTask Run(Func<Task> runAsync);
}
}
3 changes: 1 addition & 2 deletions Passenger.Tests/Services/UserServiceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
using Passenger.Core.Domain;
using System;

namespace Passenger.Tests.ServicesmapperMock
namespace Passenger.Tests.Services
{
public class UserServiceTests
{
Expand Down Expand Up @@ -62,6 +62,5 @@ public async Task when_calling_get_async_and_user_does_not_exist_it_should_invok

userRepositoryMock.Verify(x => x.GetAsync(It.IsAny<string>()), Times.Once());
}

}
}
46 changes: 46 additions & 0 deletions Passenger.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Passenger.Api", "Passenger.Api\Passenger.Api.csproj", "{DB49DC22-9B51-47D2-B217-3771CDAB3D4E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Passenger.Core", "Passenger.Core\Passenger.Core.csproj", "{57D81DC5-24E1-47BA-8459-9C4EF6EDECED}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Passenger.Infrastructure", "Passenger.Infrastructure\Passenger.Infrastructure.csproj", "{842B19F0-1CB4-4658-8C4C-B1DC534A4AF6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Passenger.Tests", "Passenger.Tests\Passenger.Tests.csproj", "{1EE7568F-E700-4C2D-B638-F172F707C14D}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8A0C5918-B860-44C9-9013-CB2A2BEF1729}"
ProjectSection(SolutionItems) = preProject
Passenger.sln = Passenger.sln
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Passenger.Tests.EndToEnd", "Passenger.Tests.EndToEnd\Passenger.Tests.EndToEnd.csproj", "{42B88B97-254A-4DE2-B505-AEAFCF317E6B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{DB49DC22-9B51-47D2-B217-3771CDAB3D4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DB49DC22-9B51-47D2-B217-3771CDAB3D4E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DB49DC22-9B51-47D2-B217-3771CDAB3D4E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DB49DC22-9B51-47D2-B217-3771CDAB3D4E}.Release|Any CPU.Build.0 = Release|Any CPU
{57D81DC5-24E1-47BA-8459-9C4EF6EDECED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{57D81DC5-24E1-47BA-8459-9C4EF6EDECED}.Debug|Any CPU.Build.0 = Debug|Any CPU
{57D81DC5-24E1-47BA-8459-9C4EF6EDECED}.Release|Any CPU.ActiveCfg = Release|Any CPU
{57D81DC5-24E1-47BA-8459-9C4EF6EDECED}.Release|Any CPU.Build.0 = Release|Any CPU
{842B19F0-1CB4-4658-8C4C-B1DC534A4AF6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{842B19F0-1CB4-4658-8C4C-B1DC534A4AF6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{842B19F0-1CB4-4658-8C4C-B1DC534A4AF6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{842B19F0-1CB4-4658-8C4C-B1DC534A4AF6}.Release|Any CPU.Build.0 = Release|Any CPU
{1EE7568F-E700-4C2D-B638-F172F707C14D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1EE7568F-E700-4C2D-B638-F172F707C14D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1EE7568F-E700-4C2D-B638-F172F707C14D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1EE7568F-E700-4C2D-B638-F172F707C14D}.Release|Any CPU.Build.0 = Release|Any CPU
{42B88B97-254A-4DE2-B505-AEAFCF317E6B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{42B88B97-254A-4DE2-B505-AEAFCF317E6B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{42B88B97-254A-4DE2-B505-AEAFCF317E6B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{42B88B97-254A-4DE2-B505-AEAFCF317E6B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

0 comments on commit 387c097

Please sign in to comment.