Search code examples
.netperformancepusher

Is there a better way to publish messages using Pusher Channels' batch event?


I'm trying to send messages to my users from my server using Pusher Channels. My api receives a list of users and the message needs to be sent to all the users in the list. I can't group these users into a single channel and an individual channel has to be used for each user. This makes my api slow as the list of users can have a size of anything between 1 and 10000 (possibly more in the future), and pusher batch events can only accept a Event list of size 10.

I'm using .net 6 for my api

I've tried using batch events to try and improve performance; my code looks something like this,

var events = new List<Event>();
// count can be anything between 1 and 10000
for (int i = 1; i <= count; i++)
{
    // creating a sample list of events
    events.Add(new Event
    {
        Channel = string.Format("batch-channel-{0}", i),
        EventName = "batch-event",
        Data = new
        {
            Channel = string.Format("batch-channel-{0}", i),
            Event = "batch-event",
            Message = string.Format("{0} - sample message", i)
        {
    });
}
var result = new List<HttpStatusCode>();
int chunkSize = 10;
int totalChunks = (int)Math.Ceiling((double)events.Length / chunkSize);
for (int i = 0; i < totalChunks; i++)
{
    var eventsChunk = events.Skip(i * chunkSize).Take(chunkSize).ToArray();
    // publishing event lists of size 10
    var chunkResult = await pusher.TriggerAsync(eventsChunk);
    result.Add(chunkResult.StatusCode);
}

I tested this code with a Event list of size 10000 and it takes around 6 minutes to complete execution. I want to know if there is anything I'm missing and if I can somehow improve performance.

Any help is appreciated. Thank you.


Solution

  • If you are sending the same event to multiple channels then you can use the standard trigger endpoint but specify a list of the channels that you are broadcasting to. For example:

    using PusherServer;
    
    var options = new PusherOptions();
    options.Cluster = "APP_CLUSTER";
    var pusher = new Pusher("APP_ID", "APP_KEY", "APP_SECRET", options);
    
    ITriggerResult result = await pusher.TriggerAsync(
      new string[]{"my-channel-1", "my-channel-2", "my-channel-3"},
      "my-event",
      new { message: "hello world" });
    

    This would trigger the event to the three specified channels. You can specify up to 100 channels in a single publish.

    If you are sending a different event to each channel then the batch event endpoint you have mentioned would be the way forward. In this case you might look at multi-threading to or similar to be able to handle multiple batch triggers at the same time, rather than sequentially.

    Source - https://pusher.com/docs/channels/server_api/http-api/#example-publish-an-event-on-multiple-channels