Hooking up custom IManageUnitsOfWork with NServiceBus? - nservicebus

I'm trying to do some performance logging with NServiceBus using a custom IManageUnitsOfWork implementation. Unfortunately, my custom IManageUnitsOfWork is never invoked and I'm not sure why. My current implementation looks like this:
public class UnitsOfWorkManager : IManageUnitsOfWork
{
private readonly Logger logger;
private readonly Stopwatch stopwatch;
public UnitsOfWorkManager()
{
this.logger = LogManager.GetCurrentClassLogger();
this.stopwatch = new Stopwatch();
}
public void Begin()
{
this.stopwatch.Start();
}
public void End(Exception ex = null)
{
this.stopwatch.Stop();
this.logger.Info("HANDLERS ELAPSED DURATION: " + this.stopwatch.ElapsedMilliseconds);
}
}
I have my Unity container registering the object as normal:
container.RegisterType<IManageUnitsOfWork, UnitsOfWorkManager>();
Is there something else I need to do to get this called? I'm using a Windows Service, not the NSB host. I'm currently using version 3.2.8.

Try adding an instance name to the registration:
container.RegisterType<IManageUnitsOfWork, UnitsOfWorkManager>("UnitsOfWorkManager");

Related

Hangfire per-job correlationId/state

I run Hangfire on ASP.NET Core.
For our other projects we have CorrelationIds that we pass when making API calls to be able to link the caller and callee.
We use the IHttpContextAccessor's TraceIdentifier for this in ASP.NET Core.
Unfortunately it looks like the trick used by ASP.NET Core to get a scoped CorrelationId in the Transient IHttpContextAccessor doesn't work for Hangfire job execution.
Using a Scoped state correlation object doesn't work because it must be Transient to be able to work with the rest of the system (logging etc.)
I used to be able to get away using the ServiceLocator anti-pattern and resolve a scoped state object in a transient service.
In the latest ASP.NET Core that is no longer supported and an exception is thrown making the system too slow because of the huge number of exceptions thrown.
Is there something that Hangfire provides already that would give me a unique ID per job execution?
Cheers.
Thanks to jbl's comment I looked at what I was doing again and managed to get it working through a kludge.
I've got the transient state holder
(basically it's the HttpContextAccessor class renamed):
public class StateHolder
{
private static AsyncLocal<ContextHolder> _contextCurrent = new AsyncLocal<ContextHolder>();
public string State {
get {
return _contextCurrent.Value?.Context;
}
set {
var holder = _contextCurrent.Value;
if (holder != null)
{
holder.Context = null;
}
if (value != null)
{
_contextCurrent.Value = new ContextHolder { Context = value };
}
}
}
private class ContextHolder
{
public string Context;
}
}
and then in Hangfire I hook it up to the activation with
public class LoggingActivator : JobActivator
{
private readonly IServiceScopeFactory _serviceScopeFactory;
private readonly ContextAccessor _contextAccessor;
public LoggingActivator([NotNull] IServiceScopeFactory serviceScopeFactory, ContextAccessor contextAccessor)
{
_serviceScopeFactory = serviceScopeFactory ?? throw new ArgumentNullException(nameof(serviceScopeFactory));
_contextAccessor = contextAccessor;
}
public override JobActivatorScope BeginScope(JobActivatorContext context)
{
return new LoggingActivatorScope(_serviceScopeFactory.CreateScope(), _contextAccessor);
}
}
and
public class LoggingActivatorScope : JobActivatorScope
{
private readonly IServiceScope _serviceScope;
private readonly ContextAccessor _contextAccessor;
public LoggingActivatorScope(
[NotNull] IServiceScope serviceScope,
ContextAccessor contextAccessor)
{
_serviceScope = serviceScope ?? throw new ArgumentNullException(nameof(serviceScope));
_contextAccessor = contextAccessor;
}
public override object Resolve(Type type)
{
_contextAccessor.Context = Guid.NewGuid().ToString();
return ActivatorUtilities.GetServiceOrCreateInstance(_serviceScope.ServiceProvider, type);
}
public override void DisposeScope()
{
_serviceScope.Dispose();
}
}
That seems to work fine.

How to send constantly updates using .Net Core SignalR?

I am new to SignalR and I would like to build such app -- every second a hub sends current time to all connected clients.
I found tutorial, but it is for .Net Framework (not Core): https://learn.microsoft.com/en-us/aspnet/signalr/overview/getting-started/tutorial-high-frequency-realtime-with-signalr So on one hand I don't know how to translate it to .Net Core SignalR, on the other hand I don't know how to write it from scratch (the limiting condition is the fact a hub is a volatile entity, so I cannot have state in it).
I need something static (I guess) with state -- let's say Broadcaster, when I create some cyclic action which in turn will send updates to clients. If such approach is OK, how to initialize this Broadcaster?
Currently I added such static class:
public static class CrazyBroadcaster
{
public static void Initialize(IServiceProvider serviceProvider)
{
var scope = serviceProvider.CreateScope();
var hub = scope.ServiceProvider.GetRequiredService<IHubContext<ChatHub>>();
var sub = Observable.Interval(TimeSpan.FromSeconds(1)).Subscribe(_ => hub.Clients.All.SendAsync("Bar", DateTimeOffset.UtcNow));
}
}
Yes, I know it is leaky. I call this method at the end of Startup.Configure, probably tons of violations here, but so far it is my best shot.
The missing piece was hosted service, i.e. the code that runs in the background -- https://learn.microsoft.com/en-US/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-2.2.
So my crazy class is now transformed into:
public sealed class HostedBroadcaster : IHostedService, IDisposable
{
private readonly IHubContext<ChatHub> hubContext;
private IDisposable subscription;
public HostedBroadcaster(IHubContext<ChatHub> hubContext)
{
this.hubContext = hubContext;
}
public void Dispose()
{
this.subscription?.Dispose();
}
public Task StartAsync(CancellationToken cancellationToken)
{
this.subscription = Observable.Interval(TimeSpan.FromSeconds(1)).Subscribe(_ => hubContext.Clients.All.SendAsync("Bar", DateTimeOffset.UtcNow));
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
this.subscription?.Dispose();
return Task.CompletedTask;
}
}

NinjectModule and IProvider not resolving types

Here is the set up that is not working
Using Ninject V3.0
public class LoggerModule : NinjectModule{
public override void Load()
{
Bind<ILogger>.ToProvider(MyLoggerProvider);
}
}
public class MyLoggerProvider: IProvider<ILogger>
{
public object Create(IContext context){
return new OneOfMyLoggers();
}
}
In my application wherever I inject instance of ILogger (using constructor or property injection, just does matter) I never get instance of ILogger resolved.
But If do not use module and/or povider, and bind when kernel is created, everything works like a charm. The following works
public class MyDiResolver()
{
public MyDiResolver()
{
MyKernel = new StandardKernel();
MyKernel.Bind<ILogger>().To<OneOfMyLoggers>();
}
}
The same arrangement of modules and providers works fine in Ninject2.x version. Is there something different about Ninject V3.0 that I am missing?
Thanks
Try passing the module into the StandardKernel so it knows to use it:
using (IKernel kernel = new StandardKernel(new LoggerModule()))
{
ILogger logger = kernel.Get<OneOfMyLoggers>();
}

SignalR Dependency Resolver not working from Javascript Hubs

I've recently upgraded to the new version of the excellent SignalR library, and moved all my Dependency Injection from StructureMap to Ninject, as Ninject seemed to be better supported.
I've got the dependency injection working fine for Server-side notifications using the "Broadcasting over a Hub from outside of a Hub" described here: https://github.com/SignalR/SignalR/wiki/Hubs.
The problem I'm getting is that all SignalR messages originating from the Javascript hub don't seem to be triggering the dependency injection.
I'm also using MVC4 WebAPI which also takes some shoe-horning to get dependency injection working.
Here's my Hub:
public class PresenceHub : Hub, IPresenceHub
{
private readonly IUserRepository _userRepository;
private readonly IFormsAuthenticationProvider _formsAuthenticationProvider;
public PresenceHub(IFormsAuthenticationProvider formsAuthenticationProvider, IUserRepository userRepository)
{
_userRepository = userRepository;
_formsAuthenticationProvider = formsAuthenticationProvider;
}
public void PresenceChange(string presence)
{
var user = _userRepository.FindById(_formsAuthenticationProvider.GetUserId());
var rosterEntry = Mapper.Map<User, RosterEntryDto>(user);
rosterEntry.Presence = presence;
Clients.updatePresence(rosterEntry);
}
}
Here's my Ninject Bootstrapper:
Namespace SLx.Web.App_Start
{
using System;
using System.Web;
using Microsoft.Web.Infrastructure.DynamicModuleHelper;
using Ninject;
using Ninject.Web.Common;
public static class NinjectWebCommon
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
}
public static void Stop()
{
bootstrapper.ShutDown();
}
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
// SignalR Ninject Resolver
GlobalHost.DependencyResolver = new SignalR.Ninject.NinjectDependencyResolver(kernel);
// WebApi Ninject Resolver
GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);
RegisterServices(kernel);
return kernel;
}
private static void RegisterServices(IKernel kernel)
{
}
}
I'm notifying clients on the serverside via a PresenceProxy defined as follows:
public class PresenceHubProxy : IPresenceHubProxy
{
private readonly IHubContext _hubContext;
public PresenceHubProxy()
{
_hubContext = GlobalHost.ConnectionManager.GetHubContext<PresenceHub>();
}
public void NotifyLogin(RosterEntryDto user)
{
_hubContext.Clients.updatePresence(user);
}
public void NotifyLogout(RosterEntryDto user)
{
_hubContext.Clients.updatePresence(user);
}
}
The Proxy works fine, injected into Controllers or their dependencies, and can send messages to the clients.
When the clients try to call SignalR via Javascript I get the following error:
No parameterless constructor defined for this object.
It looks like Ninject is not being invoked because the dependencies are not being injected into the constructor. What do I need to do to get Dependency Injection working for Javascript calls too?
Update --
Following advice from DFowler, I've replaced the Resolver in PostApplicationStart. Debugging I can see in the Immediate Window that SignalR.GlobalHost.Resolver is of type NinjectDependencyResolver but its still not working I get the same error - no paramaterless constructor.
I've then removed the NinjectDependencyResolver NuGet Library and added the source file to my solution and am using that for debugging purposes. Debugging on GetService and GetServices shows that neither method is ever called in NinjectDependencyResolver.
Any Ideas?
Problem was I hadn't called RouteTable.Routes.MapHubs:
GlobalHost.DependencyResolver = new SignalRNinjectResolver(NinjectWebCommon.Kernel);
RouteTable.Routes.MapHubs(new SignalRNinjectResolver(NinjectWebCommon.Kernel));
From the docs https://github.com/SignalR/SignalR/wiki/Extensibility:
NOTE: DO NOT override the global resolver in PreApplicationStart, it will not work, or it'll work only sometimes. Do it in PostApplicationStart (using WebActivator) or in Global.asax.

ChannelFactory: creating and disposing

I have written an Sdk that is used by a WPF client, and takes care of calling WCF services and caching. These WCF services are called using the ChannelFactory, so I don't have service references. To do that, I created a factory that handles opening and closing ChannelFactory and ClientChannel as follows:
public class ProjectStudioServiceFactory : IDisposable
{
private IProjectStudioService _projectStudioService;
private static ChannelFactory<IProjectStudioService> _channelFactory;
public IProjectStudioService Instance
{
get
{
if (_channelFactory==null) _channelFactory = new ChannelFactory<IProjectStudioService>("ProjectStudioServiceEndPoint");
_projectStudioService = _channelFactory.CreateChannel();
((IClientChannel)_projectStudioService).Open();
return _projectStudioService;
}
}
public void Dispose()
{
((IClientChannel)_projectStudioService).Close();
_channelFactory.Close();
}
}
And each request I call like:
using (var projectStudioService = new ProjectStudioServiceFactory())
{
return projectStudioService.Instance.FindAllCities(new FindAllCitiesRequest()).Cities;
}
Although this works, it's slow because for every request the client channel and factory is opened and closed. If I keep it open, it's very fast. But I was wondering what the best practise would be? Should I keep it open? Or not? How to handle this in a correct way?
Thanks Daniel, didn't see that post. So I guess that the following may be a good approach:
public class ProjectStudioServiceFactory : IDisposable
{
private static IProjectStudioService _projectStudioService;
private static ChannelFactory<IProjectStudioService> _channelFactory;
public IProjectStudioService Instance
{
get
{
if (_projectStudioService == null)
{
_channelFactory = new ChannelFactory<IProjectStudioService>("ProjectStudioServiceEndPoint");
_projectStudioService = _channelFactory.CreateChannel();
((IClientChannel)_projectStudioService).Open();
}
return _projectStudioService;
}
}
public void Dispose()
{
//((IClientChannel)_projectStudioService).Close();
//_channelFactory.Close();
}
}