Skip to content

Commit

Permalink
+ custom queued handler
Browse files Browse the repository at this point in the history
  • Loading branch information
dusterio committed Nov 27, 2022
1 parent 05c6578 commit 09573b1
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 0 deletions.
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,34 @@ Please make sure that two special routes are not mounted behind a CSRF middlewar
If your job fails, we will throw a ```FailedJobException```. If you want to customize error output – just customise your exception handler.
Note that your HTTP status code must be different from 200 in order for AWS to realize the job has failed.

## Job expiration (retention)

A new nice feature is being able to set a job expiration (retention in AWS terms) in seconds so
that low value jobs get skipped completely if there is temporary queue latency due to load.

Let's say we have a spike in queued jobs and some of them don't even make sense anymore
now that a few minutes passed – we don't want to spend computing resources processing them
later.

By setting a special property on a job or a listener class:
```php
class PurgeCache implements ShouldQueue
{
public static int $retention = 300; // If this job is delayed more than 300 seconds, skip it
}
```

We can make sure that we won't run this job later than 300 seconds since it's been queued.
This is similar to AWS SQS "message retention" setting which can only be set globally for
the whole queue.

To use this new feature, you have to use provided ```Jobs\CallQueuedHandler``` class that
extends Laravel's default ```CallQueuedHandler```. A special ```ExpiredJobException``` exception
will be thrown when expired jobs arrive and then it's up to you what to do with them.

If you just catch these exceptions and therefore stop Laravel from returning code 500
to AWS daemon, the job will be deleted by AWS automatically.

## ToDo

1. Add support for AWS dead letter queue (retry jobs from that queue?)
Expand Down
6 changes: 6 additions & 0 deletions src/Exceptions/ExpiredJobException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?php

namespace Dusterio\AwsWorker\Exceptions;

class ExpiredJobException extends \Exception {
}
42 changes: 42 additions & 0 deletions src/Jobs/CallQueuedHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

namespace Dusterio\AwsWorker\Jobs;

use Dusterio\AwsWorker\Exceptions\ExpiredJobException;
use Illuminate\Contracts\Queue\Job;
use Illuminate\Queue\CallQueuedHandler as LaravelHandler;

class CallQueuedHandler extends LaravelHandler {
/**
* Dispatch the given job / command through its specified middleware.
*
* @param \Illuminate\Contracts\Queue\Job $job
* @param mixed $command
* @return mixed
*/
protected function dispatchThroughMiddleware(Job $job, $command)
{
if ($this->hasExpired($command, $job->timestamp())) {
throw new ExpiredJobException("This job has already expired");
}

return parent::dispatchThroughMiddleware($job, $command);
}

/**
* @param $command
* @param $queuedAt
* @return bool
*/
protected function hasExpired($command, $queuedAt) {
if (! property_exists($command, 'class')) {
return false;
}

if (! property_exists($command->class, 'retention')) {
return false;
}

return time() > $queuedAt + $command->class::$retention;
}
}

0 comments on commit 09573b1

Please sign in to comment.