Skip to content

Commit d8a7bd9

Browse files
authored
[10.x] Allow failed jobs to be counted by "connection" and "queue" (#48216)
* Allow failed jobs to be counted by "connection" and "queue" * Fix and improve tests * additional tests * lint * standardise
1 parent 0ccc2d9 commit d8a7bd9

8 files changed

+276
-34
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
namespace Illuminate\Queue\Failed;
4+
5+
interface CountableFailedJobProvider
6+
{
7+
/**
8+
* Count the failed jobs.
9+
*
10+
* @param string|null $connection
11+
* @param string|null $queue
12+
* @return int
13+
*/
14+
public function count($connection = null, $queue = null);
15+
}

src/Illuminate/Queue/Failed/DatabaseFailedJobProvider.php

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,11 @@
22

33
namespace Illuminate\Queue\Failed;
44

5-
use Countable;
65
use DateTimeInterface;
76
use Illuminate\Database\ConnectionResolverInterface;
87
use Illuminate\Support\Facades\Date;
98

10-
class DatabaseFailedJobProvider implements Countable, FailedJobProviderInterface, PrunableFailedJobProvider
9+
class DatabaseFailedJobProvider implements CountableFailedJobProvider, FailedJobProviderInterface, PrunableFailedJobProvider
1110
{
1211
/**
1312
* The connection resolver implementation.
@@ -133,10 +132,17 @@ public function prune(DateTimeInterface $before)
133132

134133
/**
135134
* Count the failed jobs.
135+
*
136+
* @param string|null $connection
137+
* @param string|null $queue
138+
* @return int
136139
*/
137-
public function count(): int
140+
public function count($connection = null, $queue = null)
138141
{
139-
return $this->getTable()->count();
142+
return $this->getTable()
143+
->when($connection, fn ($builder) => $builder->whereConnection($connection))
144+
->when($queue, fn ($builder) => $builder->whereQueue($queue))
145+
->count();
140146
}
141147

142148
/**

src/Illuminate/Queue/Failed/DatabaseUuidFailedJobProvider.php

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,11 @@
22

33
namespace Illuminate\Queue\Failed;
44

5-
use Countable;
65
use DateTimeInterface;
76
use Illuminate\Database\ConnectionResolverInterface;
87
use Illuminate\Support\Facades\Date;
98

10-
class DatabaseUuidFailedJobProvider implements Countable, FailedJobProviderInterface, PrunableFailedJobProvider
9+
class DatabaseUuidFailedJobProvider implements CountableFailedJobProvider, FailedJobProviderInterface, PrunableFailedJobProvider
1110
{
1211
/**
1312
* The connection resolver implementation.
@@ -146,10 +145,17 @@ public function prune(DateTimeInterface $before)
146145

147146
/**
148147
* Count the failed jobs.
148+
*
149+
* @param string|null $connection
150+
* @param string|null $queue
151+
* @return int
149152
*/
150-
public function count(): int
153+
public function count($connection = null, $queue = null)
151154
{
152-
return $this->getTable()->count();
155+
return $this->getTable()
156+
->when($connection, fn ($builder) => $builder->whereConnection($connection))
157+
->when($queue, fn ($builder) => $builder->whereQueue($queue))
158+
->count();
153159
}
154160

155161
/**

src/Illuminate/Queue/Failed/FileFailedJobProvider.php

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,10 @@
33
namespace Illuminate\Queue\Failed;
44

55
use Closure;
6-
use Countable;
76
use DateTimeInterface;
87
use Illuminate\Support\Facades\Date;
98

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

207206
/**
208207
* Count the failed jobs.
208+
*
209+
* @param string|null $connection
210+
* @param string|null $queue
211+
* @return int
209212
*/
210-
public function count(): int
213+
public function count($connection = null, $queue = null)
211214
{
212-
return count($this->read());
215+
if (($connection ?? $queue) === null) {
216+
return count($this->read());
217+
}
218+
219+
return collect($this->read())
220+
->filter(fn ($job) => $job->connection === ($connection ?? $job->connection) && $job->queue === ($queue ?? $job->queue))
221+
->count();
213222
}
214223
}

src/Illuminate/Queue/Failed/NullFailedJobProvider.php

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@
22

33
namespace Illuminate\Queue\Failed;
44

5-
use Countable;
6-
7-
class NullFailedJobProvider implements Countable, FailedJobProviderInterface
5+
class NullFailedJobProvider implements CountableFailedJobProvider, FailedJobProviderInterface
86
{
97
/**
108
* Log a failed job into storage.
@@ -65,8 +63,12 @@ public function flush($hours = null)
6563

6664
/**
6765
* Count the failed jobs.
66+
*
67+
* @param string|null $connection
68+
* @param string|null $queue
69+
* @return int
6870
*/
69-
public function count(): int
71+
public function count($connection = null, $queue = null)
7072
{
7173
return 0;
7274
}

tests/Queue/DatabaseFailedJobProviderTest.php

Lines changed: 87 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,13 +90,96 @@ public function testJobsCanBeCounted()
9090
});
9191
$provider = new DatabaseFailedJobProvider($db->getDatabaseManager(), 'default', 'failed_jobs');
9292

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

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

9898
$provider->log('database', 'default', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
99-
$provider->log('database', 'default', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
100-
$this->assertCount(3, $provider);
99+
$provider->log('another-connection', 'another-queue', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
100+
$this->assertSame(3, $provider->count());
101+
}
102+
103+
public function testJobsCanBeCountedByConnection()
104+
{
105+
$db = new DB;
106+
$db->addConnection([
107+
'driver' => 'sqlite',
108+
'database' => ':memory:',
109+
]);
110+
$db->getConnection()->getSchemaBuilder()->create('failed_jobs', function (Blueprint $table) {
111+
$table->id();
112+
$table->text('connection');
113+
$table->text('queue');
114+
$table->longText('payload');
115+
$table->longText('exception');
116+
$table->timestamp('failed_at')->useCurrent();
117+
});
118+
$provider = new DatabaseFailedJobProvider($db->getDatabaseManager(), 'default', 'failed_jobs');
119+
120+
$provider->log('connection-1', 'default', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
121+
$provider->log('connection-2', 'default', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
122+
$this->assertSame(1, $provider->count('connection-1'));
123+
$this->assertSame(1, $provider->count('connection-2'));
124+
125+
$provider->log('connection-1', 'default', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
126+
$this->assertSame(2, $provider->count('connection-1'));
127+
$this->assertSame(1, $provider->count('connection-2'));
128+
}
129+
130+
public function testJobsCanBeCountedByQueue()
131+
{
132+
$db = new DB;
133+
$db->addConnection([
134+
'driver' => 'sqlite',
135+
'database' => ':memory:',
136+
]);
137+
$db->getConnection()->getSchemaBuilder()->create('failed_jobs', function (Blueprint $table) {
138+
$table->id();
139+
$table->text('connection');
140+
$table->text('queue');
141+
$table->longText('payload');
142+
$table->longText('exception');
143+
$table->timestamp('failed_at')->useCurrent();
144+
});
145+
$provider = new DatabaseFailedJobProvider($db->getDatabaseManager(), 'default', 'failed_jobs');
146+
147+
$provider->log('database', 'queue-1', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
148+
$provider->log('database', 'queue-2', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
149+
$this->assertSame(1, $provider->count(queue: 'queue-1'));
150+
$this->assertSame(1, $provider->count(queue: 'queue-2'));
151+
152+
$provider->log('database', 'queue-1', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
153+
$this->assertSame(2, $provider->count(queue: 'queue-1'));
154+
$this->assertSame(1, $provider->count(queue: 'queue-2'));
155+
}
156+
157+
public function testJobsCanBeCountedByQueueAndConnection()
158+
{
159+
$db = new DB;
160+
$db->addConnection([
161+
'driver' => 'sqlite',
162+
'database' => ':memory:',
163+
]);
164+
$db->getConnection()->getSchemaBuilder()->create('failed_jobs', function (Blueprint $table) {
165+
$table->id();
166+
$table->text('connection');
167+
$table->text('queue');
168+
$table->longText('payload');
169+
$table->longText('exception');
170+
$table->timestamp('failed_at')->useCurrent();
171+
});
172+
$provider = new DatabaseFailedJobProvider($db->getDatabaseManager(), 'default', 'failed_jobs');
173+
174+
$provider->log('connection-1', 'queue-99', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
175+
$provider->log('connection-1', 'queue-99', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
176+
$provider->log('connection-2', 'queue-99', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
177+
$provider->log('connection-1', 'queue-1', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
178+
$provider->log('connection-2', 'queue-1', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
179+
$provider->log('connection-2', 'queue-1', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
180+
$this->assertSame(2, $provider->count('connection-1', 'queue-99'));
181+
$this->assertSame(1, $provider->count('connection-2', 'queue-99'));
182+
$this->assertSame(1, $provider->count('connection-1', 'queue-1'));
183+
$this->assertSame(2, $provider->count('connection-2', 'queue-1'));
101184
}
102185
}

tests/Queue/DatabaseUuidFailedJobProviderTest.php

Lines changed: 89 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,96 @@ public function testJobsCanBeCounted()
2828
});
2929
$provider = new DatabaseUuidFailedJobProvider($db->getDatabaseManager(), 'default', 'failed_jobs');
3030

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

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

36-
$provider->log('database', 'default', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
37-
$provider->log('database', 'default', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
38-
$this->assertCount(3, $provider);
36+
$provider->log('connection-1', 'queue-1', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
37+
$provider->log('connection-2', 'queue-2', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
38+
$this->assertSame(3, $provider->count());
39+
}
40+
41+
public function testJobsCanBeCountedByConnection()
42+
{
43+
$db = new DB;
44+
$db->addConnection([
45+
'driver' => 'sqlite',
46+
'database' => ':memory:',
47+
]);
48+
$db->getConnection()->getSchemaBuilder()->create('failed_jobs', function (Blueprint $table) {
49+
$table->uuid();
50+
$table->text('connection');
51+
$table->text('queue');
52+
$table->longText('payload');
53+
$table->longText('exception');
54+
$table->timestamp('failed_at')->useCurrent();
55+
});
56+
$provider = new DatabaseUuidFailedJobProvider($db->getDatabaseManager(), 'default', 'failed_jobs');
57+
58+
$provider->log('connection-1', 'default', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
59+
$provider->log('connection-2', 'default', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
60+
$this->assertSame(1, $provider->count('connection-1'));
61+
$this->assertSame(1, $provider->count('connection-2'));
62+
63+
$provider->log('connection-1', 'default', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
64+
$this->assertSame(2, $provider->count('connection-1'));
65+
$this->assertSame(1, $provider->count('connection-2'));
66+
}
67+
68+
public function testJobsCanBeCountedByQueue()
69+
{
70+
$db = new DB;
71+
$db->addConnection([
72+
'driver' => 'sqlite',
73+
'database' => ':memory:',
74+
]);
75+
$db->getConnection()->getSchemaBuilder()->create('failed_jobs', function (Blueprint $table) {
76+
$table->uuid();
77+
$table->text('connection');
78+
$table->text('queue');
79+
$table->longText('payload');
80+
$table->longText('exception');
81+
$table->timestamp('failed_at')->useCurrent();
82+
});
83+
$provider = new DatabaseUuidFailedJobProvider($db->getDatabaseManager(), 'default', 'failed_jobs');
84+
85+
$provider->log('database', 'queue-1', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
86+
$provider->log('database', 'queue-2', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
87+
$this->assertSame(1, $provider->count(queue: 'queue-1'));
88+
$this->assertSame(1, $provider->count(queue: 'queue-2'));
89+
90+
$provider->log('database', 'queue-1', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
91+
$this->assertSame(2, $provider->count(queue: 'queue-1'));
92+
$this->assertSame(1, $provider->count(queue: 'queue-2'));
93+
}
94+
95+
public function testJobsCanBeCountedByQueueAndConnection()
96+
{
97+
$db = new DB;
98+
$db->addConnection([
99+
'driver' => 'sqlite',
100+
'database' => ':memory:',
101+
]);
102+
$db->getConnection()->getSchemaBuilder()->create('failed_jobs', function (Blueprint $table) {
103+
$table->uuid();
104+
$table->text('connection');
105+
$table->text('queue');
106+
$table->longText('payload');
107+
$table->longText('exception');
108+
$table->timestamp('failed_at')->useCurrent();
109+
});
110+
$provider = new DatabaseUuidFailedJobProvider($db->getDatabaseManager(), 'default', 'failed_jobs');
111+
112+
$provider->log('connection-1', 'queue-99', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
113+
$provider->log('connection-1', 'queue-99', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
114+
$provider->log('connection-2', 'queue-99', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
115+
$provider->log('connection-1', 'queue-1', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
116+
$provider->log('connection-2', 'queue-1', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
117+
$provider->log('connection-2', 'queue-1', json_encode(['uuid' => (string) Str::uuid()]), new RuntimeException());
118+
$this->assertSame(2, $provider->count('connection-1', 'queue-99'));
119+
$this->assertSame(1, $provider->count('connection-2', 'queue-99'));
120+
$this->assertSame(1, $provider->count('connection-1', 'queue-1'));
121+
$this->assertSame(2, $provider->count('connection-2', 'queue-1'));
39122
}
40123
}

0 commit comments

Comments
 (0)