Team XSockets.NET

Target Clients Offline Based on State

In the previous section we used the queue extension and the IOfflineQueue module to automatically store messages for clients being offline and the sent the messages when they reconnect.

However, a big part of XSockets is state. State is what enables you to target client with lambda expressions in a very efficient way. Doing this for client that is currently offline is not so different from the previous sample.

Let's say that we have a integer property on our Foo controller. Now we want to target clients where the value of this property is lower that the value sent. Maybe this is some kind of sensor data with a conditional send.

Extending the helpers

In the previous section we added a helper class for both sending and queuing messages. Now we add and extra method that also handles targeting clients based on lambda expressions

/// <summary>
/// Queue extentions
/// </summary>
public static class QueueHelpers
{
    //Other method removed for readability

    public static async Task InvokeToAndQueue<T>(this T controller, Func<T, bool> exp, object o, string topic) where T : class, IXSocketController
    {
        var m = new Message(o, topic, controller.Alias);
        await controller.InvokeTo(exp,m);
        await controller.Queue(DeliveryType.Rpc, m, exp);
    }
}

The controller

The controller will look almost the same as in the previous section. The new things is a property with the PersistentProperty attribute and the lambda expression to target clients based on the new property

public class Foo : XSocketController
{
    [PersistentProperty]
    public int Limit { get; set; }

    public override async Task OnClosed()
    {
        //Store messgages with the topics bar,baz while I am offline
        await this.OfflineSubscribe(60000,"bar", "baz");
    }

    public override async Task OnReopened()
    {
        //Get all messages (with topics bar,baz) that was sent while I was offline
        await this.OnlinePublish();
    }

    public async Task Bar(int v)
    {
        //Send to all online clients and store for clients being offline
        //But we only send to client where the limit is lower than v
        await this.InvokeToAndQueue(x => x.Limit < v, v, "bar");
    }
}

Testing

Once again we can use Putty to test this. Just like in the previous section we will have 2 clients. The difference this time is that they will set the property Limit and based on that value the client might get data.

Connecting and setting the property

In the first picture both client connect and set the limit. The client on top sets the limit to 25, and the client at the bottom sets it to 50. So messages under 51 will only arrive at the client on the top.

We verified that it works by sending foo|bar|40 from the client at the bottom, and only the client on the top got the message. So it works for clients online!

offline with state 1

Send data with one client offline

We now closed the client on the top (the one with limit set to 25). Then the client at the bottom sent two values foo|bar|43 and foo|bar|45. Neither of these messages arrived back at the client since it has the Limit set to 50.

offline with state 2

Reconnect the upper client

In the picture below you can see that we closed the Foo controller by sending in foo|3|. Now we send in foo|1| to reopen the controller. The server then publish both foo|bar|43 and foo|bar|45 since the Limit was set to 25 for the upper client. The server knows about the limit being set to 25 since we had the PersistentProperty attribute set on the Limit property

offline with state 3

results matching ""

    No results matching ""