Hi
I’m new to NServiceBus and am currently working on a POC to migrate one of our sync services to test things out. Our system is multi-tenant and my idea was to have a base type that every command passes containing the tenant context.
public class MessageBase
{
public TenantContext TenantContext { get; set; }
}
Our cloud solution exists in what we call “pods”, and a pod will have a database containing all the tenant details, settings and connection strings to their individual databases. So we retrieve the tenant details when the sync item is first added to the queue to be processed and then this TenantContext can be used to resolve the TenantContextFactory which most services, including the ITeanantDbConnection will rely on.
My current POC contains 7 endpoints, which would all need to resolve the unity container with a TenantContext.
As we retrieve the TenantContext when we handle a message, how would I be best to go about resolving the TenantContext for the TenantContextFactory?
We do something similar for the API, but that is using the HttpContext:
public static void Register(IUnityContainer container)
{
container.RegisterType<TenantContextFactory>(new ContainerControlledLifetimeManager(), new InjectionFactory(u =>
{
return new TenantContextFactory(() => u.Resolve<TenantContext>());
}));
container.RegisterType<TenantContext>(new InjectionFactory(GetContext));
}
private static TenantContext GetContext(IUnityContainer container)
{
if (HttpContext.Current != null)
{
var tenantGuid = HttpContext.Current.Request.Headers["X-Tenant"];
return string.IsNullOrEmpty(tenantGuid) ?
null :
GetContextFromCache(tenantGuid, container);
}
return null;
}
private static TenantContext GetContextFromCache(string guid, IUnityContainer container)
{
var cache = MemoryCache.Default;
var key = $"tenantcontext_{guid}";
var cachedContext = cache.Get(key) as TenantContext;
if (cachedContext != null)
return cachedContext;
var repo = container.Resolve<ITenantAdminRepository>();
var tenant = repo.GetTenant(Guid.Parse(guid));
if (tenant == null)
return null;
var context = new TenantContext
{
ConnectionString = tenant.ConnectionString,
TenantGuid = tenant.TenantGuid,
TenantName = tenant.Name,
Logging_LogErrors = true,
Logging_LogInfo = false,
Logging_LogDebug = false
};
var policy = new CacheItemPolicy
{
AbsoluteExpiration = DateTime.UtcNow.AddHours(10),
Priority = CacheItemPriority.Default
};
cache.Add(key, context, policy);
return context;
}
I wonder if there is some way we can hook in to the endpoint pipeline and retrieve either the TenantContext for the command and resolve the dependencies ahead of the request ending up in the handler. Open to better ways around this I am completely new to NSeviceBus so there may be some functionality that helps with this?
Thanks in advance
Andy