Hello,
I would like to know if there is a way how to resolve services inside ServerEventsFeature hooks, or move hooks attachment to another part of code, that is resolved later.
We are using ServerEvents to push notifications to user.
Currently I am registering ServerEvents like this:
public class ConfigureServerEvents : IHostingStartup
{
public void Configure(IWebHostBuilder builder) => builder
.ConfigureAppHost(appHost =>
{
appHost.Container.AddPlugin(new ServerEventsFeature()
{
LimitToAuthenticatedUsers = true,
NotifyChannelOfSubscriptions = false,
OnCreated = OnCreated,
OnSubscribeAsync = async subscription => await OnSubscribeAsync(subscription, appHost),
OnUnsubscribeAsync = async subscription => await OnUnsubscribeAsync(subscription, appHost),
OnError = OnError,
OnDispose = OnDispose,
OnConnect = OnConnect
});
appHost.Container.AddSingleton<INotificationsPublisher, NotificationsPublisher>();
});
}
I have a class NotificationsPublisher
, that basically implements my interface
public interface INotificationsPublisher
{
public Task PublishNotificationAsync(Notification notification);
}
Inside PublishNotificationAsync
, I have a call serverEvents.NotifyUserNameAsync
or serverEvents.NotifyChannelAsync
. So I am resolving IServerEvents
in constructor through DI.
I am doing some database actions and logging inside OnSubscribe
and OnUnsubscribe
methods. For example, I check if subscribed user has already received notification (through unique installation ID) and if not, we publish notification to user through INotificationsPublisher.PublishToSubscriptionAsync()
. Therefore, inside OnSubscribe
method, I call
dbConnectionFactory = appHost.Resolve<IWebDbConnectionFactory>();
notificationsPublisher = appHost.Resolve<INotificationsPublisher>();
Now I added some Jobs, because Notifications
can be scheduled into the future. I created
public class PublishNotificationsCommand(
IWebDbConnectionFactory webDbConnectionFactory,
INotificationsPublisher notificationsPublisher)
: AsyncCommand
which check for notifications to publish and publishes them to all subscribers in channel if needed.
I registered this command and job like it says in the docs:
public class ConfigureBackgroundJobs : IHostingStartup
{
public void Configure(IWebHostBuilder builder) => builder
.ConfigureServices(services =>
{
services.AddPlugin(new CommandsFeature());
services.AddPlugin(new BackgroundsJobFeature());
}).ConfigureAppHost(afterAppHostInit: appHost =>
{
var services = appHost.GetApplicationServices();
var jobs = services.GetRequiredService<IBackgroundJobs>();
jobs.RecurringCommand<PublishNotificationsCommand>(Schedule.Interval(TimeSpan.FromMinutes(5)));
});
}
Here comes the problem, the services.AddPlugin(new BackgroundsJobFeature());
is already registering the class PublishNotificationsCommand
, which needs INotificationsPublisher
, that is being registered in ConfigureAppHost
later in the game. I would move registration of INotificationsPublisher
into ConfigureServices
, however it has dependency on IServerEvents
, so I would need to move ServerEventsFeature
registration inside ConfigureServices
, but then I don’t know how to make the OnSubscribe
hook work with service resolving.
Is there some workaround or way, how to configure hooks later after registering, e.g. register plugin in ConfigureServices
but add hooks in ConfigureAppHost
?
I have also tried to use NotificationsPublisher(IServiceProvider serviceProvider)
and resolve IServerEvents
inside PublishNotificationAsync
, but for some reason, IServerEvents
is not found in IServiceProvider
.
Thanks for any ideas.