Created
December 16, 2016 13:37
-
-
Save andreasohlund/ef4b3741231eaec21d71d459b5f7c572 to your computer and use it in GitHub Desktop.
Detects and throws an exception if the endpoint is exposed to the timeout handler issue
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
class TimeoutHandlerIssueDetector : Feature | |
{ | |
public TimeoutHandlerIssueDetector() | |
{ | |
EnableByDefault(); | |
} | |
protected override void Setup(FeatureConfigurationContext context) | |
{ | |
context.RegisterStartupTask(b => new DetectReusedMessages(b.Build<MessageHandlerRegistry>())); | |
} | |
internal class DetectReusedMessages : FeatureStartupTask | |
{ | |
public DetectReusedMessages(MessageHandlerRegistry messageHandlerRegistry) | |
{ | |
this.messageHandlerRegistry = messageHandlerRegistry; | |
} | |
protected override Task OnStart(IMessageSession session) | |
{ | |
var messageTypes = messageHandlerRegistry.GetMessageTypes(); | |
var problems = new List<string>(); | |
foreach (var messageType in messageTypes) | |
{ | |
var problematicSagas = messageHandlerRegistry.GetHandlersFor(messageType) | |
.Where(h => typeof(Saga).IsAssignableFrom(h.HandlerType) && | |
CanHandle(typeof(IHandleTimeouts<>), h.HandlerType, messageType) && | |
CanHandle(typeof(IHandleMessages<>), h.HandlerType, messageType)) | |
.Select(h => h.HandlerType) | |
.Distinct() | |
.Select(s => $"Saga '{s.FullName}' has both a regular and a timeout handler for message '{messageType.FullName}'") | |
.ToList(); | |
problems.AddRange(problematicSagas); | |
} | |
if (problems.Any()) | |
{ | |
var message = string.Join(Environment.NewLine, problems); | |
throw new Exception($"Endpoint is exposed to the timeout handler bug. {message}"); | |
} | |
Debug.WriteLine($"This endpoint is not affected by the timeout handler bug ({messageTypes.Count()} message(s) checked)"); | |
return Task.FromResult(0); | |
} | |
bool CanHandle(Type handlerInterfaceType, Type handlerType, Type messageType) | |
{ | |
var interfaceType = handlerInterfaceType.MakeGenericType(messageType); | |
if (!interfaceType.IsAssignableFrom(handlerType)) | |
{ | |
return false; | |
} | |
var methodInfo = handlerType.GetInterfaceMap(interfaceType).TargetMethods.FirstOrDefault(); | |
if (methodInfo == null) | |
{ | |
return false; | |
} | |
return true; | |
} | |
protected override Task OnStop(IMessageSession session) | |
{ | |
return Task.FromResult(0); | |
} | |
MessageHandlerRegistry messageHandlerRegistry; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment