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

Subscriber is receiving 3 messages when publisher is only sending 1 #12

Closed
Roller007 opened this issue Jun 26, 2018 · 7 comments
Closed
Assignees
Labels

Comments

@Roller007
Copy link

What I'm doing is pretty basic, I have a singleton messagehub, subscriber and publisher. When the publisher publishes the message only one message is being published. For some reason however the subscriber is receiving 3 messages. I have confirmed that this is what is happening through debugging. Any ideas?

@NimaAra
Copy link
Owner

NimaAra commented Jun 26, 2018

I cannot help you without looking at your code. Please consider including a reproducible example which you can then zip up and attach to this issue for me to look at.

@NimaAra NimaAra closed this as completed Jun 26, 2018
@NimaAra NimaAra self-assigned this Jun 26, 2018
@jmdavid
Copy link

jmdavid commented May 13, 2020

I do have the same problem. I send only once and receive 2.

@NimaAra
Copy link
Owner

NimaAra commented May 13, 2020

Please provide a reproducible example for me to look at.

@jmdavid
Copy link

jmdavid commented May 13, 2020

Thanks for answering.

Dotnet Core 2.1.101

in Startup.cs:

services.AddSingleton<ISandboxService, SandboxService>();
services.AddSingleton<IActWorkflowService, ActWorkflowService>();
services.AddSingleton<IActTaskService, ActTaskService>();

services.AddSingleton<IMessageHub, MessageHub>();

I have a service locator to inject singletons from Startup based on that article: https://dotnetcoretutorials.com/2018/05/06/servicelocator-shim-for-net-core/

In each service, I have:

private readonly IMessageHub hub;
private readonly Guid subscriptionToken;

And in the constructors of each service, I have this (just the name of the service is different in Console.WriteLine:

hub = MyServiceLocator.Current.GetInstance<IMessageHub>();
subscriptionToken = hub.Subscribe<ActHubMessage>(p => Console.WriteLine($"ActTaskService({subscriptionToken}): {p.messageType}"));

In SandboxService, I publish an object with a messageType property:

var msg1 = new ActHubMessage()
{
    messageType = ActHubMessage.HubMessageType.WorkflowTransition,
    workflowId = 1
};
hub.Publish(msg1);

Here is the output:

ActWorkflowService(bc467ca9-64c0-47e4-868d-fd1692bcbe03): TaskCancel
SandboxService(1e4ce11d-281a-4208-bd1c-886f5cd95f5b): TaskCancel
ActWorkflowService(e8c259d3-be2c-4cdc-8eb9-11fae38c7d7b): TaskCancel
ActTaskService(67e5bbdf-f83f-4752-aba5-7faaadaed9d1): TaskCancel
ActTaskService(73c1999f-e7c2-4f6c-998d-c01d504a946d): TaskCancel

Notice that SandboxService have only 1 token (it is the service that publish, the only one that both publish AND subscribe); in the other services, I have 2 tokens.

@jmdavid
Copy link

jmdavid commented May 13, 2020

just in case:

namespace MyBackend
{
    //FROM THIS ARTICLE: https://dotnetcoretutorials.com/2018/05/06/servicelocator-shim-for-net-core/
    public class MyServiceLocator
    {
        private ServiceProvider _currentServiceProvider;
        private static ServiceProvider _serviceProvider;

        public MyServiceLocator(ServiceProvider currentServiceProvider)
        {
            _currentServiceProvider = currentServiceProvider;
        }

        public static MyServiceLocator Current
        {
            get
            {
                return new MyServiceLocator(_serviceProvider);
            }
        }

        public static void SetLocatorProvider(ServiceProvider serviceProvider)
        {
            _serviceProvider = serviceProvider;
        }

        public object GetInstance(Type serviceType)
        {
            return _currentServiceProvider.GetService(serviceType);
        }

        public TService GetInstance<TService>()
        {
            return _currentServiceProvider.GetService<TService>();
        }
    }
}

@NimaAra
Copy link
Owner

NimaAra commented May 14, 2020

Please put all of that into a project where I can clone or even zip it up.

@jmdavid
Copy link

jmdavid commented May 14, 2020

The problem seems to be the mix of DI.

In 2.1, it was not possible to inject in service like we do in controllers.

This works:

public SandboxController(ISandboxService _sandboxService, IActTaskService _actTaskService...

This NOT works:

public SandboxService(IActTaskService _taskService...

That's why I used the ServiceLocator to inject services in other services like this:

actTaskService = MyServiceLocator.Current.GetInstance<IActTaskService>();

However, I still use the first pattern in my controllers. And I realized that I inject ActTaskService and ActWorkflowService in 2 controllers, in correponding controller (ActTaskController, ActWorfklowController) AND in SandboxController (that I use as a scratchpad). As long as I removed the 2 services from SandboxController, the class is instantiated only once.

But I wonder why injection in controllers creates a new instance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants