Skip to content

Instantly share code, notes, and snippets.

@BrianVallelunga
Last active March 17, 2016 14:03
Show Gist options
  • Select an option

  • Save BrianVallelunga/418e086d1758a4bd1441 to your computer and use it in GitHub Desktop.

Select an option

Save BrianVallelunga/418e086d1758a4bd1441 to your computer and use it in GitHub Desktop.
Azure WebJob MessageScope solution
namespace Demo
{
using System;
using System.Collections.Concurrent;
using System.Runtime.Remoting.Messaging;
using Microsoft.Practices.Unity;
using Microsoft.ServiceBus.Messaging;
public interface IMessageScopeManager
{
void BeginMessageScope(BrokeredMessage message);
void CompleteMessageScope();
IUnityContainer GetScopedContainer();
}
public class MessageScopeManager : IMessageScopeManager
{
private const string MessageIdKey = "MessageId";
private readonly IUnityContainer container;
private readonly ConcurrentDictionary<string, IUnityContainer> messageContainers;
public MessageScopeManager(IUnityContainer container)
{
this.container = container;
this.messageContainers = new ConcurrentDictionary<string, IUnityContainer>();
}
public void BeginMessageScope(BrokeredMessage message)
{
CallContext.LogicalSetData(MessageIdKey, message.MessageId);
var messageContainer = this.container.CreateChildContainer();
// NOTE: This is where you can set per-message child-container registrations
this.messageContainers.TryAdd(message.MessageId, messageContainer);
}
public void CompleteMessageScope()
{
string messageId = this.GetCurrentMessageId();
IUnityContainer messageContainer;
if (this.messageContainers.TryRemove(messageId, out messageContainer))
{
messageContainer.Dispose();
}
CallContext.FreeNamedDataSlot(MessageIdKey);
}
public IUnityContainer GetScopedContainer()
{
string messageId = this.GetCurrentMessageId();
IUnityContainer messageContainer;
if (this.messageContainers.TryGetValue(messageId, out messageContainer))
{
return messageContainer;
}
throw new InvalidOperationException("Container not found for message " + messageId);
}
private string GetCurrentMessageId()
{
return CallContext.LogicalGetData(MessageIdKey).ToString();
}
}
}
namespace Demo
{
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs.Host.Executors;
using Microsoft.Azure.WebJobs.ServiceBus;
using Microsoft.ServiceBus.Messaging;
public class MessageScopeMessageProcessor : MessageProcessor
{
private readonly IMessageScopeManager messageScopeManager;
public MessageScopeMessageProcessor(OnMessageOptions messageOptions, IMessageScopeManager messageScopeManager)
: base(messageOptions)
{
this.messageScopeManager = messageScopeManager;
}
public override Task<bool> BeginProcessingMessageAsync(BrokeredMessage message, CancellationToken cancellationToken)
{
this.messageScopeManager.BeginMessageScope(message);
return base.BeginProcessingMessageAsync(message, cancellationToken);
}
public override Task CompleteProcessingMessageAsync(BrokeredMessage message, FunctionResult result, CancellationToken cancellationToken)
{
this.messageScopeManager.CompleteMessageScope();
return base.CompleteProcessingMessageAsync(message, result, cancellationToken);
}
}
}
namespace Demo
{
using Microsoft.Azure.WebJobs.ServiceBus;
public class MessageScopeMessagingProvider : MessagingProvider
{
private readonly ServiceBusConfiguration config;
private readonly IMessageScopeManager messageScopeManager;
public MessageScopeMessagingProvider(ServiceBusConfiguration config, IMessageScopeManager messageScopeManager)
: base(config)
{
this.config = config;
this.messageScopeManager = messageScopeManager;
}
public override MessageProcessor CreateMessageProcessor(string entityPath)
{
return new MessageScopeMessageProcessor(this.config.MessageOptions, this.messageScopeManager);
}
}
}
namespace Demo
{
using Microsoft.Azure.WebJobs.Host;
using Microsoft.Practices.Unity;
public class MessageScopeUnityJobActivator : IJobActivator
{
private readonly IMessageScopeManager messageScopeManager;
public MessageScopeUnityJobActivator(IMessageScopeManager messageScopeManager)
{
this.messageScopeManager = messageScopeManager;
}
public T CreateInstance<T>()
{
var messageContainer = this.messageScopeManager.GetScopedContainer();
return messageContainer.Resolve<T>();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment