Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to run multiple processing strategies #83

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions Mail2Bug/Mail2Bug.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@
<HintPath>..\packages\Microsoft.Azure.KeyVault.1.0.0\lib\net45\Microsoft.Azure.KeyVault.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Azure.KeyVault.Core, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Azure.KeyVault.Core.2.0.4\lib\net45\Microsoft.Azure.KeyVault.Core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Exchange.WebServices, Version=14.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.Exchange.WebServices.1.2\lib\Microsoft.Exchange.WebServices.dll</HintPath>
Expand Down Expand Up @@ -320,6 +324,7 @@
<Compile Include="MessageProcessingStrategies\DateBasedValueResolver.cs" />
<Compile Include="MessageProcessingStrategies\IMessageProcessingStrategy.cs" />
<Compile Include="MessageProcessingStrategies\INameResolver.cs" />
<Compile Include="MessageProcessingStrategies\MultiStrategy.cs" />
<Compile Include="MessageProcessingStrategies\NameResolver.cs" />
<Compile Include="MessageProcessingStrategies\NameResolverMock.cs" />
<Compile Include="MessageProcessingStrategies\OverridesExtractor.cs" />
Expand Down Expand Up @@ -363,6 +368,10 @@
<Error Condition="!Exists('..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" Text="This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=317567." HelpKeyword="BCLBUILD2001" />
<Error Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" Text="The build restored NuGet packages. Build the project again to include these packages in the build. For more information, see http://go.microsoft.com/fwlink/?LinkID=317568." HelpKeyword="BCLBUILD2002" />
</Target>
<PropertyGroup>
<PostBuildEvent>
</PostBuildEvent>
</PropertyGroup>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
Expand Down
13 changes: 8 additions & 5 deletions Mail2Bug/Mail2BugEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@
using Mail2Bug.Helpers;
using Mail2Bug.MessageProcessingStrategies;
using Mail2Bug.WorkItemManagement;
using System.Collections.Generic;

namespace Mail2Bug
{
class Mail2BugEngine : IDisposable
{
{
private readonly IMailboxManager _mailboxManager;
private readonly Config.InstanceConfig _config;

Expand All @@ -25,7 +26,7 @@ class Mail2BugEngine : IDisposable

public Mail2BugEngine(Config.InstanceConfig configInstance, MailboxManagerFactory mailboxManagerFactory)
{
_config = configInstance;
_config = configInstance;

Logger.InfoFormat("Initalizing MailboxManager");
_mailboxManager = mailboxManagerFactory.CreateMailboxManager(_config.EmailSettings);
Expand Down Expand Up @@ -94,19 +95,21 @@ private void ProcessInboxInternal()
private IMessageProcessingStrategy InitProcessingStrategy()
{
IWorkItemManager workItemManager;
List<IMessageProcessingStrategy> strategies = new List<IMessageProcessingStrategy>();
if (_config.TfsServerConfig.SimulationMode)
{
Logger.InfoFormat("Working in simulation mode. Using WorkItemManagerMock");
workItemManager = new WorkItemManagerMock(_config.WorkItemSettings.ConversationIndexFieldName);
strategies.Add(new SimpleBugStrategy(_config, workItemManager));
}
else
{
Logger.InfoFormat("Working in standard mode, using TFSWorkItemManager");
workItemManager = new TFSWorkItemManager(_config);
strategies.Add(new SimpleBugStrategy(_config));
}

Logger.InfoFormat("Initializing MessageProcessingStrategy");
return new SimpleBugStrategy(_config, workItemManager);

return new MultiStrategy(strategies);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than creating a strategy to encapsulate others, can we update Mail2BugEngine's behavior to support a list of strategies instead of one. This will keep it simpler and will still support the same set of use cases. The default implementation can have only SimpleBugStrategy in the list.

}

private static readonly ILog Logger = LogManager.GetLogger(typeof(Mail2BugEngine));
Expand Down
32 changes: 32 additions & 0 deletions Mail2Bug/MessageProcessingStrategies/MultiStrategy.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using log4net;
using Mail2Bug.Email;
using Mail2Bug.Helpers;
using Mail2Bug.WorkItemManagement;

namespace Mail2Bug.MessageProcessingStrategies
{
/// <summary>
/// Allows Mail2Bug administrators to create their own processing strategies to be run in conjunction with (or without) the default
/// SimpleBugStrategy. This opens up the door for plugins to write messages to storage or auto response bots while maintaining
/// current functionality.
/// </summary>
public class MultiStrategy : IMessageProcessingStrategy
{
private List<IMessageProcessingStrategy> _strategies;
public MultiStrategy(List<IMessageProcessingStrategy> strategies) {
_strategies = strategies;
}
public void ProcessInboxMessage(IIncomingEmailMessage message)
{
foreach (IMessageProcessingStrategy strategy in _strategies) {
strategy.ProcessInboxMessage(message);
}
}
}
}
32 changes: 29 additions & 3 deletions Mail2Bug/MessageProcessingStrategies/SimpleBugStrategy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,28 @@ public class SimpleBugStrategy : IMessageProcessingStrategy, IDisposable
private readonly AckEmailHandler _ackEmailHandler;
private readonly MessageToWorkItemMapper _messageToWorkItemMapper;

public SimpleBugStrategy(Config.InstanceConfig config, IWorkItemManager workItemManager)
public SimpleBugStrategy(Config.InstanceConfig config)
{
_config = config;
_workItemManager = workItemManager;
_workItemManager = InitWorkItemManager();
_ackEmailHandler = new AckEmailHandler(config);
_messageToWorkItemMapper =
new MessageToWorkItemMapper(
_config.EmailSettings.AppendOnlyEmailTitleRegex,
_config.EmailSettings.AppendOnlyEmailBodyRegex,
_workItemManager.WorkItemsCache);
}

public SimpleBugStrategy(Config.InstanceConfig config, IWorkItemManager WitManager)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use the same variable name as the original - workItemManager

{
_config = config;
_workItemManager = WitManager;
_ackEmailHandler = new AckEmailHandler(config);
_messageToWorkItemMapper =
new MessageToWorkItemMapper(
_config.EmailSettings.AppendOnlyEmailTitleRegex,
_config.EmailSettings.AppendOnlyEmailBodyRegex,
_workItemManager.WorkItemsCache);
}
public void ProcessInboxMessage(IIncomingEmailMessage message)
{
var workItemId = _messageToWorkItemMapper.GetWorkItemId(message);
Expand Down Expand Up @@ -187,6 +197,22 @@ private static TempFileCollection SaveAttachments(IIncomingEmailMessage message)
return attachmentFiles;
}

private IWorkItemManager InitWorkItemManager() {
IWorkItemManager workItemManager;
if (_config.TfsServerConfig.SimulationMode)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any specific reason we need to duplicate this code here? We should rather keep this in Mail2BugEngine itself so that these classes are agnostic of which IWorkItemManager is being used.

{
Logger.InfoFormat("Working in simulation mode. Using WorkItemManagerMock");
workItemManager = new WorkItemManagerMock(_config.WorkItemSettings.ConversationIndexFieldName);
}
else
{
Logger.InfoFormat("Working in standard mode, using TFSWorkItemManager");
workItemManager = new TFSWorkItemManager(_config);
}

return workItemManager;
}

private static readonly ILog Logger = LogManager.GetLogger(typeof(SimpleBugStrategy));

public void Dispose()
Expand Down
1 change: 1 addition & 0 deletions Mail2Bug/packages.config
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<package id="Microsoft.Azure.Common" version="2.0.4" targetFramework="net45" />
<package id="Microsoft.Azure.Common.Dependencies" version="1.0.0" targetFramework="net45" />
<package id="Microsoft.Azure.KeyVault" version="1.0.0" targetFramework="net45" />
<package id="Microsoft.Azure.KeyVault.Core" version="2.0.4" targetFramework="net45" />
<package id="Microsoft.Bcl" version="1.1.9" targetFramework="net45" />
<package id="Microsoft.Bcl.Async" version="1.0.168" targetFramework="net45" />
<package id="Microsoft.Bcl.Build" version="1.0.14" targetFramework="net45" />
Expand Down
2 changes: 2 additions & 0 deletions Mail2BugUnitTests/Mail2BugUnitTests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@
<Compile Include="Mocks\Email\IncomingAttachmentMock.cs" />
<Compile Include="Mocks\Email\IncomingEmailMessageMock.cs" />
<Compile Include="Mocks\Email\MailManagerMock.cs" />
<Compile Include="Mocks\ProcessingStrategyMock.cs" />
<Compile Include="MultiStrategyUnitTest.cs" />
<Compile Include="OverridesExtractorUnitTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RecipientsMailboxManagerRouterUnitTest.cs" />
Expand Down
21 changes: 21 additions & 0 deletions Mail2BugUnitTests/Mocks/ProcessingStrategyMock.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Mail2Bug.MessageProcessingStrategies;
using Mail2Bug.Email;

namespace Mail2BugUnitTests.Mocks
{
public class ProcessingStrategyMock : IMessageProcessingStrategy
{
public bool status { get; set; }
public ProcessingStrategyMock() {
status = false;
}
public void ProcessInboxMessage(IIncomingEmailMessage message) {
status = true;
}
}
}
30 changes: 30 additions & 0 deletions Mail2BugUnitTests/MultiStrategyUnitTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Mail2Bug.MessageProcessingStrategies;
using Mail2BugUnitTests.Mocks;
using Mail2BugUnitTests.Mocks.Email;

namespace Mail2BugUnitTests
{
[TestClass]
public class MultiStrategyUnitTest
{
[TestMethod]
public void MultipleStrategiesCalled()
{
List<IMessageProcessingStrategy> mocks = new List<IMessageProcessingStrategy>();
IncomingEmailMessageMock messageMock = new IncomingEmailMessageMock();

mocks.Add(new ProcessingStrategyMock());
mocks.Add(new ProcessingStrategyMock());
MultiStrategy m = new MultiStrategy(mocks);

m.ProcessInboxMessage(messageMock);

foreach (ProcessingStrategyMock strategy in mocks) {
Assert.IsTrue(strategy.status, "Process message not successfully called on child strategies.");
}
}
}
}