# Queue Overload - Load shedding
## Navigation
1. [Problem](https://hackmd.io/@jwdunne/HJXyhNY4h)
2. [Observability](https://hackmd.io/@jwdunne/S1pJ1CgHn)
3. [Testing](https://hackmd.io/@jwdunne/H1zKkAeSn)
4. [Throughput optimisation opportunities](https://hackmd.io/@jwdunne/H1h2k0xH3)
5. [Backpressure](https://hackmd.io/@jwdunne/B1WZeCeBh)
6. [Load shedding](https://hackmd.io/@jwdunne/BJB4MReH2)
7. [Autoscaling](https://hackmd.io/@jwdunne/Bkw_zAxHn)
## Solution
We can drop these messages outright in times of overload:
- `Leadflo\Integrations\Listeners\MonitorIntegrations`
- `Leadflo\Integrations\Listeners\MonitorSyncs`
- `Leadflo\Integrations\Listeners\Healthcheck`
- `Leadflo\Integrations\Events\IntegrationSyncStateChanged`
- `Leadflo\Integrations\Listeners\TimeoutSyncingIntegrations`
- `Leadflo\Email\Listeners\ProcessFeedbackQueue`
- `Leadflo\App\Listeners\ActionCountsBuilder`
This one is trickier as these listeners extend from the `BaseListener`, which already defines an abstract `execute` method. We would have to do something different. Perhaps `maybeExecute`, which signals that the listener may not be executed at all under times of high-load:
```php
/**
* @template T
* @require-extends BaseListener<T>
*/
trait Sheddable
{
private readonly QueueLoad $queueLoad;
/** @param T $event **/
abstract public function maybeExecute($event): void;
public function execute($event): void
{
if (!$this->shouldQueue($event)) {
return;
}
$this->maybeExecute($event);
}
/** @param T $event **/
public function shouldQueue($event)
{
// load shedding stuff here
}
}
```
The reason why we implement a guard clause that uses `shouldQueue` is because `shouldQueue` only prevents the message from being queued. If it's already on the queue, we want to ignore that too and get it off the worker ASAP.
## Implementation
- Implement `Sheddable` trait
- Make `MonitorSyncs` listener shed load
- Make `MonitorIntegrations` listener shed load
- Make `ActionCountsBuilder` listener shed load