Callback Contract to Implement an Eventing Mechanism

 08-Apr-2017   nityaprakash     WCF  DuplexBinding    Comments  0

In last article, I have describe how to implement publisher/subscribe pattern with duplex binding. Here, I am going to explain how to implement eventing mechanism with same. We want other clients to notify, if there is change in state of any process is done by other client or the system. All clients will subscribe to event if they want to be notified.

Subscribing And Unsubscribing Event

We can use callbacks to implement an eventing mechanism; the service can advertise events and provide operations to enable client applications to Subscribe to these events and unsubscribe from them. The Service can provide a callback contract to send a message to each subscribing client when an event occurs. To do this, service must have reference to each client application instance.

Kanban Service

For demo purpose, We are going to create new Kanban Service which will return all tasks of the a specific project, SaveTaskDetail, SubscribeTaskChangeEvent, UnSubscribeTaskChangeEvent. The client which has subscribed to TaskChangeEvent will receive notification when any client update the Any Task.


    [ServiceContract( CallbackContract = typeof(IKanbanServiceCallback))]
    public interface IKanbanService
    {
        [OperationContract]
        ProjectDetail GetProject(int Id);

        [OperationContract]
        TaskDetail[] GetTasks(int projectId);

        [OperationContract(IsOneWay = true)]
        void SaveTaskDetail(TaskDetail task);

        [OperationContract]
        void SubscribeTaskChangeEvent();

        [OperationContract]
        void UnSubscribeTaskChangeEvent();
    }
   

KanbanServiceCallback

Here we want client to notify when any TaskDetail is modified. So we have created a callback contact IKanbanServiceCallback as below:


    [ServiceContract]
    public interface IKanbanServiceCallback
    {
        [OperationContract]
        void OnTaskDetailChanged(TaskDetail task);
    }
   

Now multiple client can subscribe to the TaskDetailChanged event. In this case multiple clients has opened the KanbanBoard for specific project and all tasks pertaining to the project are loaded on their board. If someone update the task, for example mark the task completed, all the board loaded with this project should reflect the change immediately. So they will come to know that this task has completed. When client subscribe the event, Service will add the reference of context in static list. Whenever, request come for updating task, it will update the task and call OnTaskDetailChanged event for each callback. Before running the event we will check, if connection is still alive. See the code snippet below:


       public void SaveTaskDetail(TaskDetail task)
        {
            TaskDetail existingTask = null;
            lock (Tasks)
            {
                existingTask = Tasks.SingleOrDefault(t => t.TaskId == task.TaskId);

                existingTask.IsComplete = task.IsComplete;

                if (existingTask.IsComplete)
                    existingTask.CompletedDate = DateTime.Now;
            }

            Parallel.ForEach(subscription, ( callback) =>
           {
               if (((ICommunicationObject)callback).State == CommunicationState.Opened)
               {
                   callback.OnTaskDetailChanged(existingTask);
               }
               else
               {
                   subscription.Remove(callback);
               }
           });
        }
   

In this example, I have locked(synchronization) the Tasks list because, client is reloading list of task when OnTaskDetailChanged event trigger at their side. In this case it hasn't completed with SaveTaskDetail method and making connection again to the client. ConcurrencyMode.Reentrant will allow client to make connection to the server again but cause Deadlock situation. **To handle Deadlock situation we have to implement proper synchronization techniques. Here is client side call:


       private void SaveTask()
        {
            TaskDetail modifiedTask = tasks.FirstOrDefault(t => t.IsComplete && t.CompletedDate == DateTime.MinValue);
            kanbanProxy.SaveTaskDetail(modifiedTask);
        }

        public void OnTaskDetailChanged(TaskDetail task)
        {

            GetTasks();
                OnPropertyChanged("PendingTasks");
                OnPropertyChanged("CompletedTasks");
        }
   

##Delivery Models for Publishing and Subscribing If we are implementing such systems in a large enterprise, or across the internet, we would need to consider security and scalability, and how they impact the operation of the WCF Service calling back into a client application. There are at least three models that publication and subscription systems frequently implemented. They have their own advantages and disadvantages.

The Push Model

In this example we have used Push Model where client. If we are implementing for large enterprise then, service must have sufficient resources to be able to invoke operations in a potentially large number of subscribers simultaneously. Service can spawn a new thread for each client as we did in our example and return data. The primary disadvantage of this approach is security. The callback operations invoked by the service could be blocked by a firewall protecting client applications.

The Pull Model

In this model, service will update to a third service with latest data. Client will periodically call the third service for the updated information. This model less prone to firewall blocking issues, but it requires more complexity on the part of subscribers. There could also be scalability issues with the third service if large number of subscribers query too frequently. Other issue can be if subscriber does not query the third service frequently enough, it might miss an event.

The Broker Model

This model is hybrid of above two models. Third service will expose events which will be subscribe by clients. This third service will subscribe the event from original service. As any update happen on Service side, it will update to third service about data and it will immediately notify clients.


Nitya Prakash Sharma has over 10 years of experience in .NET technology. He is currently working as Senior Consultant in industry. He is always keen to learn new things in Technology and eager to apply wherever is possible. He is also has interest in Photography, sketching and painting.

My Blog
Post Comment

COMMENTS