Posts Tagged ‘Publish Subscribe Pattern’

I have been working in SAAS solutions for many years now and it is interesting to see how technologies are evolving & applications / web APIs are connecting to each other to get seamless & quick end to end integration between systems & organizations.

Webhook – A lightweight HTTP pattern providing a simple pub/sub model for wiring together Web APIs and SaaS services. It’s been an year that this new concept been introduced in my product (thanks to our great Architect) and I see lot of benefits with it.

  • Now our product can send notifications to the subscribed customers for the predefined events that happens in the product.
  • It’s also used to show the changes between two major statuses in our workflow system
  • We also thought about using it to build reporting data warehouse instead of building warehouse using the typical approach of ETL/batch jobs.

So there may be many such usecases that one can think about to see whether this can fit. The first use case i.e. sending notification with data on an event is a very natural usecase that many products can use this. More examples …

  • File has changed in Dropbox
  • Code change has been committed in GitHub
  • Payment has been initiated in PayPal
  • Card has been created in Trello
  • Post P1 bug to a slack group

References

Testing it

 

Advertisements

using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace DesignPatterns.PubSub
{
[TestClass]
public class TestSample
{
[TestMethod]
public void Main()
{
Publisher publisherService = new Publisher();
Subscriber1 sub1 = new Subscriber1(publisherService);
Subscriber2 sub2 = new Subscriber2(publisherService);

publisherService.Publish(“Published”);
}
}

public class Publisher
{
public delegate void PublishDelegate(object sender, InfoArgs args);
public event PublishDelegate PublishEvent;

public void OnPublishEvent(object sender, InfoArgs args)
{
if (PublishEvent != null)
PublishEvent(sender, args);
}

public void Publish(string info)
{
OnPublishEvent(this, new InfoArgs(info));
}
}

public class InfoArgs : EventArgs
{
private readonly string info;

public InfoArgs(string info)
{
this.info = info;
}

public string Info
{
get { return info; }
}
}

public class Subscriber1
{
private Publisher publisher;
public Subscriber1(Publisher pPublisher)
{
this.publisher = pPublisher;
pPublisher.PublishEvent += Action;
}

static void Action(object sender, InfoArgs args)
{
Console.WriteLine(“Subscriber1 Action: ” + args.Info);
}
}

public class Subscriber2
{
private Publisher publisher;
public Subscriber2(Publisher pPublisher)
{
this.publisher = pPublisher;
pPublisher.PublishEvent += Action;
}

static void Action(object sender, InfoArgs args)
{
Console.WriteLine(“Subscriber2 Action: ” + args.Info);
}
}
}

Reference –

http://www.akadia.com/services/dotnet_delegates_and_events.html

http://www.dotnetarchitecthouston.com/post/The-Publish-Subscribe-Pattern-in-C-and-some-gotchas.aspx

http://msdn.microsoft.com/en-us/library/ms752254.aspx – WCF

http://msdn.microsoft.com/en-us/library/ff649664.aspx – MS Patterens & Practices

1. Using bind, trigger functions we can implement simple Publish/Subscribe pattern in JQuery
2. Below example shows how to create Subscribers (generally the script on page sections or modules) by subscribing to a common custom event called buttonClick through JQuery bind method and it also shows how to publish the custom event on some action (manual or automatic – here on click of button which is manual action) which intern fires all subscriber’s Action methods through JQuery trigger method.
3. There is already a plug-in available in JQuery site for achieving this by simply calling $.subscribe, $.publish and with few other functions. Refer http://www.dotnetoutsource.com/Download/jQuery/Publish-subscribe.aspx for sample. Our custom functions can be extended on top of native JQuery code using Plug-ins to access them directly on $ operator, like $.subscirbe.

<input type=”button” value=”Click Button & Publish Button Click Event” id=”myfield2″/>
<script type=”text/javascript” src=”http://ajax.microsoft.com/ajax/jQuery/jquery-1.4.4.js“></script>
<script language=”javascript”>
    // Publisher script can be at page level. Actual publish action will be invoked through either user actions or through callback functions in case of ajax calls
    var Publisher = {
        Publish: function (eventName, args) {
            $(document).trigger(eventName, args);
        }
    };

    // Subscriber1/Subscriber2 can be part of page sections i.e. user controls (in case of asp.net page)
    var Subscriber1 = {
        subscribe: function () {          
            $(document).bind(‘buttonClick’, Subscriber1.Action);           
        },

        Action: function (event, a, b, c) {
            alert(“Subscriber1 Action – arg1: ” + a + “, arg2: ” + b + “, arg3: ” + c);
        }
    }
    Subscriber1.subscribe();

    var Subscriber2 = {
        subscribe: function () {           
            $(document).bind(‘buttonClick’, Subscriber2.Action);           
        },

        Action: function (event, a, b, c) {
            alert(“Subscriber2 Action – arg1: ” + a + “, arg2: ” + b + “, arg3: ” + c);
        }
    }
    Subscriber2.subscribe();

    $(document).ready(function () {
        // Binding publish method for button click event
        $(‘#myfield2’).unbind(‘click’).bind(‘click’, function () { Publisher.Publish(‘buttonClick’, [‘1’, ‘2’, ‘3’]); });       
    });
</script>

Following code is a simple example of publish subscriber modal using Javascript. Subscriber1, Subscriber2 are 2 subscribers for an event “PublishOnClick”. User is the publisher who publishes the event by clicking “Click Button & Publish Button Click Event” button. Publisher javascript code provides framework for adding/executing subscribers by different other modules in the same page. For example Subscriber1 can be in one module and Subscriber2 can be in another module and both can subscribe to single button action on the main page.

<input type=”button” value=”Click Button & Publish Button Click Event” id=”myfield2″/>
<script language=”javascript”>
    var Publisher = {
        subscribers: {},       
        Subscribe: function (event, callback) {
            if (Publisher[event] && typeof callback === “function”) {
                if (Publisher.subscribers[event]) {
                    Publisher.subscribers[event].callbacks.push(callback);
                }
                else {
                    Publisher.subscribers[event] = { callbacks: [callback] };
                }
            }
        },
        Publish: function (event, callback) {
            if (Publisher.subscribers[event].callbacks) {
                for (var callback in Publisher.subscribers[event].callbacks) {
                    Publisher.subscribers[event].callbacks[callback].apply(null, arguments);
                }
            }
        },
        // PublishOnClick – name should be same as subscribing event name. Similar to this method we can have different method for each new publishing event
        PublishOnClick: function (event, arguments) {
            Publisher.Publish(event, arguments);
        }
    };

    var Subscriber1 = {
        initialize: function () {
            if (Publisher.Subscribe) {
                Publisher.Subscribe(“PublishOnClick”, Subscriber1.Action);
            }
        },
        Action: function (a, b, c) {
            alert(“Subscriber1 Action – arg1: ” + a + “, arg2: ” + b + “, arg3: ” + c);
        }
    };
    Subscriber1.initialize();

    var Subscriber2 = {
        initialize: function () {
            if (Publisher.Subscribe) {
                Publisher.Subscribe(“PublishOnClick”, Subscriber2.Action);
            }
        },
        Action: function (a, b, c) {
            alert(“Subscriber2 Action – arg1: ” + a + “, arg2: ” + b + “, arg3: ” + c);
        }
    };
    Subscriber2.initialize();

    var fld2 = document.getElementById(“myfield2”); 
    if (fld2.addEventListener) {
        fld2.addEventListener(“click”, function () { Publisher.PublishOnClick(“PublishOnClick”, [‘1’, ‘2’, ‘3’]); }, false); // publish thru button click event
    }
    else if (fld2.attachEvent) {
        fld2.attachEvent(“onclick”, function () { Publisher.PublishOnClick(“PublishOnClick”, [‘1’, ‘2’, ‘3’]); }); // publish thru button click
    }
</script>