Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WCF Duplex - Push different notifications to each client?

I am designing a 2 WCF services that all my clients will connect to. One of these services will be a notifications service.

I would like each client to connect to the service, subscribe to it and then receive notifications, using a duplex Callback interface (the service will fire the 'Notify' operation in the clients).

This is my Design Idea:

enter image description here

My question is: When each client connects to my service, I will validate it against the 'Users' table in my database (I will be using a UserNamePasswordValidator and implement the 'Validate' function).

Requirement: Each user needs to receive different notifications, based on rules defined in the database, but they all use the same contract.

For example:

John Smith's rules in the DB might be : Notify me on all new products that have a price of over 100 dollars.

Jane Doe's rules in the DB might be : Notify me on all new products that their names begin with 'JA'.

Jim Jabra's rules in the DB might be : Notify me on all new products that are of type 'Food'.

My service will have a worker thread that detects a change in the database (a new product was inserted to the database).

It should then loop over all the clients connected - and for each client send him a notification of the new product, only if it matches the client's notification requests.

Again - all clients receive the same type of update (new products), but each client should receive different products according to the rule in the database.

One approach I thought to implement this would be to use a Singleton service, that holds a list of :

  • Client Enpoint
  • User Object (from database)

This way - each time the worker thread detects a new product, it loops over this list and send notifications to whome ever needs it. The problem with this approach is that in order to have one global list of clients - I need to have the service as a Singlton, right ?

The second approach would be ... well ... I don't have another idea of how I can access a list of clients connected to the service from a worker thread ...

I guess the main problem I have is that each client might want different kinds of product notified to him. Meaning - the pub\sub method is not so good here, because my scenario requires the service to know about the clients.

Any suggestions on how I can solve this headaches ?

like image 374
John Miner Avatar asked Nov 05 '22 01:11

John Miner


1 Answers

In any way with duplex communication, you need to maintain TCP channel opened from server to client to be able to send notification.

Client is the one who initiate connection to server, and you need to keep this connection open, if this connection is lost you can't (shouldn't) initiate connection from server to client, because client can be behind NAT, have firewall, etc.

So in any way there must be some static (singleton) object on server side that keeps clients connections list, thought this is not necessarily WCF service. You can dependency inject this object into service constructor.

public class ProductRepository
{
    private EventAggregator eventAggregator;

    public void Add(Product product)
    {
        //...
        eventAggregator.Publish(new NewProductEvent(product))
    }
}
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)]
public class EventPublishingService
{
    private IClientCallback client;
    private EventAggregator eventAggregator;
    private Func<Product, bool> predicate;

    public EventPublishingService(...)
    {
        eventAggregator.Subscibe<NewProductEvent>(OnNewProduct);
    }
    private void OnNewProduct(NewProductEvent e)
    {
        if (predicate(e.Product)==true) client.Notify(e.Product);
    }

    public void Subscribe()
    {
        client = OperationContext.Current.GetCallbackChannel<IClientCallback>()
        var user = ServiceSecurityContext.PrimaryIdentity;
        predicate = GetFilterForUser(user);
    }
}
like image 125
Alex Burtsev Avatar answered Nov 15 '22 05:11

Alex Burtsev