0

I want to make a service that notify the user in case there are some new messages sent to him. Thus I want to use some Comet framework that provide the server push ability. So I have looked into PokeIn.

Just wondering a thing. I have checked on the samples that they have on the website. None of them look into the database to retrieve new entries if there are some. But it is just a matter of modification to it I guess.

One of the sample implement this long polling by using a sleep on the server side. So if I use the same approach I can check the database, if there are any new entries, every 5 seconds. However this approach doesn't seem to be much different from when using polling on the client side with javascript.

This part is from a sample. As can be seen they put a sleep there for to update current time for everybody.

static void UpdateClients()
    {
        while (true)
        {
            //.. code to check database 
            if (CometWorker.ActiveClientCount > 0)
            {
                CometWorker.SendToAll(JSON.Method("UpdateTime", DateTime.Now));
            }
            Thread.Sleep(500);
        }
    }

So I wonder is this how I should implement the message notifier? It seems that the above approach is still going to push a huge load demand on the server side. The message notifier is intend to work same way as the one found Facebook.

Zuuum
  • 1,495
  • 11
  • 18
starcorn
  • 8,261
  • 23
  • 83
  • 124

2 Answers2

2

You shouldn't implement this way, that sample is only implemented like that because the keep PokeIn related part is clear. You should implement SQL part as mentioned http://www.codeproject.com/Articles/12335/Using-SqlDependency-for-data-change-events in order to track changes on database.

So, when you have something to send, call one of the PokeIn methods for the client side delivery. I don't know, how much your application is time critical because in addition to reverse ajax, PokeIn's internal websocket feature is very easy to activate and delivers messages to client quite fast.

Zuuum
  • 1,495
  • 11
  • 18
  • thanks for the information. Regarding to the data event changes, is there also an approach where detecting data changes in a azuretable is applied? – starcorn Jun 27 '12 at 09:47
  • no. maybe you should ask this on a separate question. (similar SQLDependency solution for Azuretable etc.) – Zuuum Jun 27 '12 at 13:30
0

You can do this with database as @Zuuum said, but I implemented it in a different way.

I'm using ASP.NET MVC with PokeIn and EF in a Windows Azure environment:

  • I have domain events similar to this approach: Strengthening your domain: Domain Events
  • When someone invokes an action, that's a Unit of Work
  • If that UOW succeeds then I raise a domain event (e.g. ChatMessageSent)
  • I have subscribers for these domain events so they can receive the event and forward the message to the PokeIn listeners

I use this pattern for all my real-time needs on my game site (making moves, actions etc in a game), I don't want to advertise it here, you can find it through me if you want.

I always use this pattern as a duplex communication solution so everybody gets their update via PokeIn, even the user who invoked the action so every client will behave the same. So when someone calls an action it won't return anything except the success signal.

The next examples are won't work because they are only snippets to demonstrate the flow

Here is an action snippet from my code:

[HttpPost]
[UnitOfWork]
[RestrictToAjax]
[ValidateAntiForgeryToken]
public JsonResult Post(SendMessageViewModel msg) 
{ 
    if (ModelState.IsValid)
    {
        var chatMessage = new ChatMessage
        {
            ContainerType = msg.ContainerType,
            ContainerID = msg.ContainerID,
            Message = _xssEncoder.Encode(msg.Message),
            User = _profileService.CurrentUser
        };

        _chatRepository.AddMessage(chatMessage);
        OnSuccessfulUoW = () => EventBroker.Current.Send(this, new ChatMessageSentPayload(chatMessage));
    }

    return Json(Constants.AjaxOk);
}

And the (simplified) EventBroker implementation:

public class UnityEventBroker : EventBroker
{
    private readonly IUnityContainer _container;

    public UnityEventBroker(IUnityContainer container)
    {
        _container = container;
    }

    public override void Send<TPayload>(object sender, TPayload payload)
    {
        var subscribers = _container.ResolveAll<IEventSubscriber<TPayload>>();
        if (subscribers == null) return;
        foreach (var subscriber in subscribers)
        {
            subscriber.Receive(sender, payload);
        }
    }
}

And the even more simplified subscriber:

public class ChatMessageSentSubscriber : IEventSubscriber<ChatMessageSentPayload>
{
    public void Receive(object sender, ChatMessageSentPayload payload)
    {
        var message = payload.Message;
        var content = SiteContent.Global;

        var clients = Client.GetClients(c => c.ContentID == message.ContainerID && c.Content == content)
                            .Select(c => c.ClientID)
                            .ToArray();

        var dto = ObjectMapper.Current.Map<ChatMessage, ChatMessageSentDto>(message);

        var json = PokeIn.JSON.Method("pokein", dto);
        CometWorker.SendToClients(clients, json);
    }
}
Peter Porfy
  • 8,921
  • 3
  • 31
  • 41