Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[10.x] Allow failed jobs to be counted by "connection" and "queue" #48216

Merged
merged 5 commits into from
Aug 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions src/Illuminate/Queue/Failed/CountableFailedJobProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

namespace Illuminate\Queue\Failed;

interface CountableFailedJobProvider
{
/**
* Count the failed jobs.
*
* @param string|null $connection
* @param string|null $queue
* @return int
*/
public function count($connection = null, $queue = null);
}
14 changes: 10 additions & 4 deletions src/Illuminate/Queue/Failed/DatabaseFailedJobProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@

namespace Illuminate\Queue\Failed;

use Countable;
use DateTimeInterface;
use Illuminate\Database\ConnectionResolverInterface;
use Illuminate\Support\Facades\Date;

class DatabaseFailedJobProvider implements Countable, FailedJobProviderInterface, PrunableFailedJobProvider
class DatabaseFailedJobProvider implements CountableFailedJobProvider, FailedJobProviderInterface, PrunableFailedJobProvider
{
/**
* The connection resolver implementation.
Expand Down Expand Up @@ -133,10 +132,17 @@ public function prune(DateTimeInterface $before)

/**
* Count the failed jobs.
*
* @param string|null $connection
* @param string|null $queue
* @return int
*/
public function count(): int
public function count($connection = null, $queue = null)
{
return $this->getTable()->count();
return $this->getTable()
->when($connection, fn ($builder) => $builder->whereConnection($connection))
->when($queue, fn ($builder) => $builder->whereQueue($queue))
->count();
}

/**
Expand Down
14 changes: 10 additions & 4 deletions src/Illuminate/Queue/Failed/DatabaseUuidFailedJobProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@

namespace Illuminate\Queue\Failed;

use Countable;
use DateTimeInterface;
use Illuminate\Database\ConnectionResolverInterface;
use Illuminate\Support\Facades\Date;

class DatabaseUuidFailedJobProvider implements Countable, FailedJobProviderInterface, PrunableFailedJobProvider
class DatabaseUuidFailedJobProvider implements CountableFailedJobProvider, FailedJobProviderInterface, PrunableFailedJobProvider
{
/**
* The connection resolver implementation.
Expand Down Expand Up @@ -146,10 +145,17 @@ public function prune(DateTimeInterface $before)

/**
* Count the failed jobs.
*
* @param string|null $connection
* @param string|null $queue
* @return int
*/
public function count(): int
public function count($connection = null, $queue = null)
{
return $this->getTable()->count();
return $this->getTable()
->when($connection, fn ($builder) => $builder->whereConnection($connection))
->when($queue, fn ($builder) => $builder->whereQueue($queue))
->count();
}

/**
Expand Down
17 changes: 13 additions & 4 deletions src/Illuminate/Queue/Failed/FileFailedJobProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@
namespace Illuminate\Queue\Failed;

use Closure;
use Countable;
use DateTimeInterface;
use Illuminate\Support\Facades\Date;

class FileFailedJobProvider implements Countable, FailedJobProviderInterface, PrunableFailedJobProvider
class FileFailedJobProvider implements CountableFailedJobProvider, FailedJobProviderInterface, PrunableFailedJobProvider
{
/**
* The file path where the failed job file should be stored.
Expand Down Expand Up @@ -206,9 +205,19 @@ protected function write(array $jobs)

/**
* Count the failed jobs.
*
* @param string|null $connection
* @param string|null $queue
* @return int
*/
public function count(): int
public function count($connection = null, $queue = null)
{
return count($this->read());
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();
}
}
10 changes: 6 additions & 4 deletions src/Illuminate/Queue/Failed/NullFailedJobProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@

namespace Illuminate\Queue\Failed;

use Countable;

class NullFailedJobProvider implements Countable, FailedJobProviderInterface
class NullFailedJobProvider implements CountableFailedJobProvider, FailedJobProviderInterface
{
/**
* Log a failed job into storage.
Expand Down Expand Up @@ -65,8 +63,12 @@ public function flush($hours = null)

/**
* Count the failed jobs.
*
* @param string|null $connection
* @param string|null $queue
* @return int
*/
public function count(): int
public function count($connection = null, $queue = null)
{
return 0;
}
Expand Down
91 changes: 87 additions & 4 deletions tests/Queue/DatabaseFailedJobProviderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,13 +90,96 @@ public function testJobsCanBeCounted()
});
$provider = new DatabaseFailedJobProvider($db->getDatabaseManager(), 'default', 'failed_jobs');

$this->assertCount(0, $provider);
$this->assertSame(0, $provider->count());

$provider->log('database', 'default', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
$this->assertCount(1, $provider);
$this->assertSame(1, $provider->count());

$provider->log('database', 'default', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
$provider->log('database', 'default', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
$this->assertCount(3, $provider);
$provider->log('another-connection', 'another-queue', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
$this->assertSame(3, $provider->count());
}

public function testJobsCanBeCountedByConnection()
{
$db = new DB;
$db->addConnection([
'driver' => 'sqlite',
'database' => ':memory:',
]);
$db->getConnection()->getSchemaBuilder()->create('failed_jobs', function (Blueprint $table) {
$table->id();
$table->text('connection');
$table->text('queue');
$table->longText('payload');
$table->longText('exception');
$table->timestamp('failed_at')->useCurrent();
});
$provider = new DatabaseFailedJobProvider($db->getDatabaseManager(), 'default', 'failed_jobs');

$provider->log('connection-1', 'default', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
$provider->log('connection-2', 'default', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
$this->assertSame(1, $provider->count('connection-1'));
$this->assertSame(1, $provider->count('connection-2'));

$provider->log('connection-1', 'default', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
$this->assertSame(2, $provider->count('connection-1'));
$this->assertSame(1, $provider->count('connection-2'));
}

public function testJobsCanBeCountedByQueue()
{
$db = new DB;
$db->addConnection([
'driver' => 'sqlite',
'database' => ':memory:',
]);
$db->getConnection()->getSchemaBuilder()->create('failed_jobs', function (Blueprint $table) {
$table->id();
$table->text('connection');
$table->text('queue');
$table->longText('payload');
$table->longText('exception');
$table->timestamp('failed_at')->useCurrent();
});
$provider = new DatabaseFailedJobProvider($db->getDatabaseManager(), 'default', 'failed_jobs');

$provider->log('database', 'queue-1', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
$provider->log('database', 'queue-2', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
$this->assertSame(1, $provider->count(queue: 'queue-1'));
$this->assertSame(1, $provider->count(queue: 'queue-2'));

$provider->log('database', 'queue-1', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
$this->assertSame(2, $provider->count(queue: 'queue-1'));
$this->assertSame(1, $provider->count(queue: 'queue-2'));
}

public function testJobsCanBeCountedByQueueAndConnection()
{
$db = new DB;
$db->addConnection([
'driver' => 'sqlite',
'database' => ':memory:',
]);
$db->getConnection()->getSchemaBuilder()->create('failed_jobs', function (Blueprint $table) {
$table->id();
$table->text('connection');
$table->text('queue');
$table->longText('payload');
$table->longText('exception');
$table->timestamp('failed_at')->useCurrent();
});
$provider = new DatabaseFailedJobProvider($db->getDatabaseManager(), 'default', 'failed_jobs');

$provider->log('connection-1', 'queue-99', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
$provider->log('connection-1', 'queue-99', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
$provider->log('connection-2', 'queue-99', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
$provider->log('connection-1', 'queue-1', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
$provider->log('connection-2', 'queue-1', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
$provider->log('connection-2', 'queue-1', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
$this->assertSame(2, $provider->count('connection-1', 'queue-99'));
$this->assertSame(1, $provider->count('connection-2', 'queue-99'));
$this->assertSame(1, $provider->count('connection-1', 'queue-1'));
$this->assertSame(2, $provider->count('connection-2', 'queue-1'));
}
}
95 changes: 89 additions & 6 deletions tests/Queue/DatabaseUuidFailedJobProviderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,96 @@ public function testJobsCanBeCounted()
});
$provider = new DatabaseUuidFailedJobProvider($db->getDatabaseManager(), 'default', 'failed_jobs');

$this->assertCount(0, $provider);
$this->assertSame(0, $provider->count());

$provider->log('database', 'default', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
$this->assertCount(1, $provider);
$provider->log('connection-1', 'queue-1', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
$this->assertSame(1, $provider->count());

$provider->log('database', 'default', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
$provider->log('database', 'default', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
$this->assertCount(3, $provider);
$provider->log('connection-1', 'queue-1', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
$provider->log('connection-2', 'queue-2', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
$this->assertSame(3, $provider->count());
}

public function testJobsCanBeCountedByConnection()
{
$db = new DB;
$db->addConnection([
'driver' => 'sqlite',
'database' => ':memory:',
]);
$db->getConnection()->getSchemaBuilder()->create('failed_jobs', function (Blueprint $table) {
$table->uuid();
$table->text('connection');
$table->text('queue');
$table->longText('payload');
$table->longText('exception');
$table->timestamp('failed_at')->useCurrent();
});
$provider = new DatabaseUuidFailedJobProvider($db->getDatabaseManager(), 'default', 'failed_jobs');

$provider->log('connection-1', 'default', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
$provider->log('connection-2', 'default', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
$this->assertSame(1, $provider->count('connection-1'));
$this->assertSame(1, $provider->count('connection-2'));

$provider->log('connection-1', 'default', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
$this->assertSame(2, $provider->count('connection-1'));
$this->assertSame(1, $provider->count('connection-2'));
}

public function testJobsCanBeCountedByQueue()
{
$db = new DB;
$db->addConnection([
'driver' => 'sqlite',
'database' => ':memory:',
]);
$db->getConnection()->getSchemaBuilder()->create('failed_jobs', function (Blueprint $table) {
$table->uuid();
$table->text('connection');
$table->text('queue');
$table->longText('payload');
$table->longText('exception');
$table->timestamp('failed_at')->useCurrent();
});
$provider = new DatabaseUuidFailedJobProvider($db->getDatabaseManager(), 'default', 'failed_jobs');

$provider->log('database', 'queue-1', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
$provider->log('database', 'queue-2', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
$this->assertSame(1, $provider->count(queue: 'queue-1'));
$this->assertSame(1, $provider->count(queue: 'queue-2'));

$provider->log('database', 'queue-1', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
$this->assertSame(2, $provider->count(queue: 'queue-1'));
$this->assertSame(1, $provider->count(queue: 'queue-2'));
}

public function testJobsCanBeCountedByQueueAndConnection()
{
$db = new DB;
$db->addConnection([
'driver' => 'sqlite',
'database' => ':memory:',
]);
$db->getConnection()->getSchemaBuilder()->create('failed_jobs', function (Blueprint $table) {
$table->uuid();
$table->text('connection');
$table->text('queue');
$table->longText('payload');
$table->longText('exception');
$table->timestamp('failed_at')->useCurrent();
});
$provider = new DatabaseUuidFailedJobProvider($db->getDatabaseManager(), 'default', 'failed_jobs');

$provider->log('connection-1', 'queue-99', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
$provider->log('connection-1', 'queue-99', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
$provider->log('connection-2', 'queue-99', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
$provider->log('connection-1', 'queue-1', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
$provider->log('connection-2', 'queue-1', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
$provider->log('connection-2', 'queue-1', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
$this->assertSame(2, $provider->count('connection-1', 'queue-99'));
$this->assertSame(1, $provider->count('connection-2', 'queue-99'));
$this->assertSame(1, $provider->count('connection-1', 'queue-1'));
$this->assertSame(2, $provider->count('connection-2', 'queue-1'));
}
}
Loading