Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel Event exceeds Pusher allowed limit

I have an event in my Laravel application that for specific records it exceeds the allowed maximum limit (10240 bytes) of Pusher. Is it correct that Laravel serializes every public attribute on the Event class? If so I suspect that the serialized model should not exceed the 10kb limit but it fails anyway. Are there any approaches to decrease the size of the data content?

class PostChanged implements ShouldBroadcast
{

 use Dispatchable, InteractsWithSockets, SerializesModels;

 public $post;

 /**
  * Create a new event instance.
  *
  * @return void
  */
  public function __construct(Post $post)
  {
    $this->post = $post;
  }

  /**
  * Get the channels the event should broadcast on.
  *
  * @return \Illuminate\Broadcasting\Channel|array
  */
  public function broadcastOn()
  {
    return new Channel('post-channel.'.$this->post->id);
  }

  public function broadcastWith()
  {
    $extra = [
      'data' => $this->post->data,
    ];

    return array_merge($this->post->toArray(), $extra);
  }
}

produces:

The data content of this event exceeds the allowed maximum (10240 bytes). 
See http://pusher.com/docs/server_api_guide/server_publishing_events for more info
like image 621
sarotnem Avatar asked Jul 03 '18 06:07

sarotnem


1 Answers

Approach 1: Resolve at client side

The most reliable approach would be what @ExohJosh described: Only send the event type along with an ID so the client (most likely JavaScript) can fetch the updated record through a separate REST (or whatever) API.

public function broadcastWith()
{
    return [
        'id' => $this->post->id,
    ];
}

Approach 2: Reduce Payload

An alternative (and simpler) approach would be to send only the data required by the client (the one you figured out yourself @sarotnem). However this approach is only safe, if you definitely know that the attributes you submit can not in any case exceed the 10KiB limit. This can be ensured through input validation, limitations on DB columns or other means.

When choosing this approach, be sure to also include the size of any relationships, that could possibly be loaded on the model, into your calculations.

A neat way to define an "external representation" of a model are Laravel's API Resources. They could make your code look like this:

public function broadcastWith()
{
    return [
        'post' => new \App\Http\Resources\PostResource($this->post),
    ];
}

where App\Http\Resources\PostResource could be:

class PostResource extends JsonResource
{
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'title' => $this->title,
            'body' => $this->body,
        ];
    }
}
like image 178
jsphpl Avatar answered Sep 20 '22 20:09

jsphpl