Search code examples
c#.netdesign-patternspublish-subscribe

.Net messaging pub/sub pattern


So I have an .Net application that is running on NancyFx (needs to be platform agnostic). I have a requirement that I need to send a notification when a certain event happens (subscription). The notification will implement this interface:

public interface INotification
{
    public void Notify();
}

There will be many different implementations for this e.g. Email, Pushbullet, Pushover etc.

What I am struggling with is how to actually implement this so that all implementations of INotification will execute Notify() when there is a subscription.

Can anyone point me in the right direction.

I don't really want to use any sort of external queues, since the application will be running on the users machines.

So the application is a self-hosted, the client and the server are located on the users machine and it does not talk to the outside world, it's all internal.


Solution

  • Excuse me for a second, I'll just want to make sure I got you right. You have not written what's the exact problem, so I assume you are stuck somewhere at some basics. I'll also ignore NancyFX, I don't know it, I assume that if it supported this case, you'd find it in docs.

    To let the client know that something has changed, you essentially have only 3 options:
    (a) there's a list of old events on the server, server updates it when events happen, clients periodically read them and invoke their 'Notify' that does Ping!
    (b) each client opens a connection to the server and keeps it open, server remembers the connections and when a new even happens, sends a message to all clients over already-opened connections, clients get the message and invoke their 'Notify' that does Ping!
    (c) clients send registration message to the server, it contains callback address/port/etc, server stores that. when event occurs, server reads the list and sends infos to these addresses, clients handle these requests and call their Notify according to the request

    Since you use words 'publish-subscribe', I assume you meant (C).

    For this option, regarding notifications, the roles of client/server are actually reversed. In a normal case, the server exposes API to client, client connects to it, sends a request, server handles it and returns some response. Here, both sides must do the same. The client app must also expose a callable API to the server, so that when "event" occurs, the server can connect to the client's API and send him a request with notification data.

    Now, how you'd structure the API - it's up to you. You can have one Notify(string xmlizedOrJsonizedData) method, you can have parameters Notify(string infotype, datetime, data), or many methods NotifyEmal(...) NotifyBullet(...) ... - after implementing the registration and subscription bookkeeping, you will just need the server to call into the client's api with correct request data, just like the client does the same all the time.

    Now that's a bit of work to write all of that and reinvent the wheel. There are lots of libraries that already can do it. I looked and I didn't find anything in NancyFx docs about that. Probably you could use it to create a client-side api, just like you create server-side api, but .. there's a catch.

    Client-side and server-side differ.

    When client talks to sever, there is only one server to send to and to listen to. You can do it in naive way, even blocking the UI if you like. When server sends notifications back, there can be 10000s of clients. You should not even start writing it in a naive way. Looping over that many clients and waiting till finished can freeze your server completely, and if not freeze, then cause slowdowns and timeouts. Furthermore, server is out there in public. Clients are not. Clients often are behind NATs, firewalls, and all other funny things that pass traffic from Client->to->Server but may block traffic in the other direction. Most basic example is blocking ports. :80 on the server is almost always passed through firewalls, but :80 on client will be probably unavailable and when client opens its api on :23122 it probably won't be configured on their firewalls/routers .. unless you handle that with upnp/etc.

    That's why it's good to pick a library that can do all of that for you.. Sorry, I can't recall any name now, check i.e. google for PublishSubscribe pattern, or client-notification or push-notification server-side library.

    That's why a thing called "WebSockets" was invented. That's essentially option (B) I talked about in the beginning. It's really worth investigating. The whole concept of subscribe-publish is also implementable as calls/responses to server/client apis/interfaces over websocket, but it saves you a lot of work and network problems.

    I've found an info that it's possible to use Nancy and SignalR so that may be a very good start.