FileFailedJobProvider.php
TLDR
The FileFailedJobProvider.php
file is a part of the Illuminate\Queue\Failed namespace in the Laravel framework. This file provides an implementation of a failed job provider that stores failed jobs in a file. It includes methods for logging failed jobs, retrieving lists and details of failed jobs, deleting failed jobs, and pruning old failed jobs.
Methods
__construct($path, $limit = 100, ?Closure $lockProviderResolver = null)
This is the constructor method for the FileFailedJobProvider
class. It initializes the instance with the path where the failed job file should be stored, the maximum number of failed jobs to retain, and an optional closure for resolving the lock provider.
log($connection, $queue, $payload, $exception)
This method is used to log a failed job into storage. It takes the connection name, queue name, payload, and exception as parameters and returns the ID of the logged job.
ids($queue = null)
This method returns an array of IDs of all the failed jobs. Optionally, you can pass a queue name to filter the failed jobs based on the queue.
all()
This method returns an array of all the failed jobs.
find($id)
This method takes an ID as a parameter and returns a single failed job with the matching ID.
forget($id)
This method is used to delete a single failed job from storage. It takes an ID as a parameter and returns a boolean indicating whether the deletion was successful.
flush($hours = null)
This method is used to flush all of the failed jobs from storage. It takes an optional parameter $hours
to specify the number of hours before which the failed jobs should be retained.
prune(DateTimeInterface $before)
This method prunes all of the entries older than the given date from the failed jobs storage. It takes a DateTimeInterface
instance as a parameter and returns the number of pruned jobs.
count($connection = null, $queue = null)
This method returns the count of failed jobs. It takes optional parameters $connection
and $queue
to filter the count based on the connection and queue names.
Classes
None
<?php
namespace Illuminate\Queue\Failed;
use Closure;
use DateTimeInterface;
use Illuminate\Support\Facades\Date;
class FileFailedJobProvider implements CountableFailedJobProvider, FailedJobProviderInterface, PrunableFailedJobProvider
{
/**
* The file path where the failed job file should be stored.
*
* @var string
*/
protected $path;
/**
* The maximum number of failed jobs to retain.
*
* @var int
*/
protected $limit;
/**
* The lock provider resolver.
*
* @var \Closure
*/
protected $lockProviderResolver;
/**
* Create a new database failed job provider.
*
* @param string $path
* @param int $limit
* @param \Closure|null $lockProviderResolver
* @return void
*/
public function __construct($path, $limit = 100, ?Closure $lockProviderResolver = null)
{
$this->path = $path;
$this->limit = $limit;
$this->lockProviderResolver = $lockProviderResolver;
}
/**
* Log a failed job into storage.
*
* @param string $connection
* @param string $queue
* @param string $payload
* @param \Throwable $exception
* @return int|null
*/
public function log($connection, $queue, $payload, $exception)
{
return $this->lock(function () use ($connection, $queue, $payload, $exception) {
$id = json_decode($payload, true)['uuid'];
$jobs = $this->read();
$failedAt = Date::now();
array_unshift($jobs, [
'id' => $id,
'connection' => $connection,
'queue' => $queue,
'payload' => $payload,
'exception' => (string) mb_convert_encoding($exception, 'UTF-8'),
'failed_at' => $failedAt->format('Y-m-d H:i:s'),
'failed_at_timestamp' => $failedAt->getTimestamp(),
]);
$this->write(array_slice($jobs, 0, $this->limit));
return $id;
});
}
/**
* Get the IDs of all of the failed jobs.
*
* @param string|null $queue
* @return array
*/
public function ids($queue = null)
{
return collect($this->all())
->when(! is_null($queue), fn ($collect) => $collect->where('queue', $queue))
->pluck('id')
->all();
}
/**
* Get a list of all of the failed jobs.
*
* @return array
*/
public function all()
{
return $this->read();
}
/**
* Get a single failed job.
*
* @param mixed $id
* @return object|null
*/
public function find($id)
{
return collect($this->read())
->first(fn ($job) => $job->id === $id);
}
/**
* Delete a single failed job from storage.
*
* @param mixed $id
* @return bool
*/
public function forget($id)
{
return $this->lock(function () use ($id) {
$this->write($pruned = collect($jobs = $this->read())
->reject(fn ($job) => $job->id === $id)
->values()
->all());
return count($jobs) !== count($pruned);
});
}
/**
* Flush all of the failed jobs from storage.
*
* @param int|null $hours
* @return void
*/
public function flush($hours = null)
{
$this->prune(Date::now()->subHours($hours ?: 0));
}
/**
* Prune all of the entries older than the given date.
*
* @param \DateTimeInterface $before
* @return int
*/
public function prune(DateTimeInterface $before)
{
return $this->lock(function () use ($before) {
$jobs = $this->read();
$this->write($prunedJobs = collect($jobs)->reject(function ($job) use ($before) {
return $job->failed_at_timestamp <= $before->getTimestamp();
})->values()->all());
return count($jobs) - count($prunedJobs);
});
}
/**
* Execute the given callback while holding a lock.
*
* @param \Closure $callback
* @return mixed
*/
protected function lock(Closure $callback)
{
if (! $this->lockProviderResolver) {
return $callback();
}
return ($this->lockProviderResolver)()
->lock('laravel-failed-jobs', 5)
->block(10, function () use ($callback) {
return $callback();
});
}
/**
* Read the failed jobs file.
*
* @return array
*/
protected function read()
{
if (! file_exists($this->path)) {
return [];
}
$content = file_get_contents($this->path);
if (empty(trim($content))) {
return [];
}
$content = json_decode($content);
return is_array($content) ? $content : [];
}
/**
* Write the given array of jobs to the failed jobs file.
*
* @param array $jobs
* @return void
*/
protected function write(array $jobs)
{
file_put_contents(
$this->path,
json_encode($jobs, JSON_PRETTY_PRINT)
);
}
/**
* Count the failed jobs.
*
* @param string|null $connection
* @param string|null $queue
* @return int
*/
public function count($connection = null, $queue = null)
{
if (($connection ?? $queue) === null) {
return count($this->read());
}
return collect($this->read())
->filter(fn ($job) => $job->connection === ($connection ?? $job->connection) && $job->queue === ($queue ?? $job->queue))
->count();
}
}