Skip to content

Commit fdbe72f

Browse files
authoredFeb 18, 2025··
Capture job dispatch duration (#106)
1 parent f1c8b9e commit fdbe72f

8 files changed

+44
-23
lines changed
 

‎src/Hooks/JobQueuedListener.php ‎src/Hooks/QueuedJobListener.php

+3-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Laravel\Nightwatch\Hooks;
44

55
use Illuminate\Queue\Events\JobQueued;
6+
use Illuminate\Queue\Events\JobQueueing;
67
use Laravel\Nightwatch\Core;
78
use Laravel\Nightwatch\State\CommandState;
89
use Laravel\Nightwatch\State\RequestState;
@@ -11,7 +12,7 @@
1112
/**
1213
* @internal
1314
*/
14-
final class JobQueuedListener
15+
final class QueuedJobListener
1516
{
1617
/**
1718
* @param Core<RequestState|CommandState> $nightwatch
@@ -22,7 +23,7 @@ public function __construct(
2223
//
2324
}
2425

25-
public function __invoke(JobQueued $event): void
26+
public function __invoke(JobQueueing|JobQueued $event): void
2627
{
2728
try {
2829
$this->nightwatch->sensor->queuedJob($event);

‎src/NightwatchServiceProvider.php

+3-2
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
use Illuminate\Notifications\Events\NotificationSending;
3535
use Illuminate\Notifications\Events\NotificationSent;
3636
use Illuminate\Queue\Events\JobQueued;
37+
use Illuminate\Queue\Events\JobQueueing;
3738
use Illuminate\Routing\Events\PreparingResponse;
3839
use Illuminate\Routing\Events\ResponsePrepared;
3940
use Illuminate\Routing\Events\RouteMatched;
@@ -54,12 +55,12 @@
5455
use Laravel\Nightwatch\Hooks\ExceptionHandlerResolvedHandler;
5556
use Laravel\Nightwatch\Hooks\HttpClientFactoryResolvedHandler;
5657
use Laravel\Nightwatch\Hooks\HttpKernelResolvedHandler;
57-
use Laravel\Nightwatch\Hooks\JobQueuedListener;
5858
use Laravel\Nightwatch\Hooks\LogoutListener;
5959
use Laravel\Nightwatch\Hooks\MailListener;
6060
use Laravel\Nightwatch\Hooks\NotificationListener;
6161
use Laravel\Nightwatch\Hooks\PreparingResponseListener;
6262
use Laravel\Nightwatch\Hooks\QueryExecutedListener;
63+
use Laravel\Nightwatch\Hooks\QueuedJobListener;
6364
use Laravel\Nightwatch\Hooks\RequestBootedHandler;
6465
use Laravel\Nightwatch\Hooks\RequestHandledListener;
6566
use Laravel\Nightwatch\Hooks\ResponsePreparedListener;
@@ -264,7 +265,7 @@ private function registerHooks(): void
264265
/**
265266
* @see \Laravel\Nightwatch\Records\QueuedJob
266267
*/
267-
$events->listen(JobQueued::class, (new JobQueuedListener($core))(...));
268+
$events->listen([JobQueueing::class, JobQueued::class], (new QueuedJobListener($core))(...));
268269

269270
/**
270271
* @see \Laravel\Nightwatch\Records\Notification

‎src/SensorManager.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Illuminate\Notifications\Events\NotificationSent;
1616
use Illuminate\Queue\Events\JobAttempted;
1717
use Illuminate\Queue\Events\JobQueued;
18+
use Illuminate\Queue\Events\JobQueueing;
1819
use Laravel\Nightwatch\Sensors\CacheEventSensor;
1920
use Laravel\Nightwatch\Sensors\CommandSensor;
2021
use Laravel\Nightwatch\Sensors\ExceptionSensor;
@@ -179,7 +180,7 @@ public function log(LogRecord $record): void
179180
$sensor($record);
180181
}
181182

182-
public function queuedJob(JobQueued $event): void
183+
public function queuedJob(JobQueueing|JobQueued $event): void
183184
{
184185
$sensor = $this->queuedJobSensor ??= new QueuedJobSensor(
185186
executionState: $this->executionState,

‎src/Sensors/MailSensor.php

+1-5
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@ final class MailSensor
2121
{
2222
private ?float $startTime = null;
2323

24-
private ?int $duration = null;
25-
2624
public function __construct(
2725
private RequestState|CommandState $executionState,
2826
private Clock $clock,
@@ -40,7 +38,6 @@ public function __invoke(MessageSending|MessageSent $event): void
4038

4139
if ($event instanceof MessageSending) {
4240
$this->startTime = $now;
43-
$this->duration = null;
4441

4542
return;
4643
}
@@ -51,7 +48,6 @@ public function __invoke(MessageSending|MessageSent $event): void
5148
throw new RuntimeException("No start time found for [{$class}].");
5249
}
5350

54-
$this->duration = (int) round(($now - $this->startTime) * 1_000_000);
5551
$this->executionState->mail++;
5652

5753
$this->executionState->records->write(new Mail(
@@ -71,7 +67,7 @@ class: $class,
7167
cc: count($event->message->getCc()),
7268
bcc: count($event->message->getBcc()),
7369
attachments: count($event->message->getAttachments()),
74-
duration: $this->duration,
70+
duration: (int) round(($now - $this->startTime) * 1_000_000),
7571
failed: false, // TODO: The framework doesn't dispatch a failed event.
7672
));
7773
}

‎src/Sensors/NotificationSensor.php

+1-5
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@ final class NotificationSensor
2222
{
2323
private ?float $startTime = null;
2424

25-
private ?int $duration = null;
26-
2725
public function __construct(
2826
private RequestState|CommandState $executionState,
2927
private Clock $clock,
@@ -37,7 +35,6 @@ public function __invoke(NotificationSending|NotificationSent $event): void
3735

3836
if ($event instanceof NotificationSending) {
3937
$this->startTime = $now;
40-
$this->duration = null;
4138

4239
return;
4340
}
@@ -52,7 +49,6 @@ public function __invoke(NotificationSending|NotificationSent $event): void
5249
$class = $event->notification::class;
5350
}
5451

55-
$this->duration = (int) round(($now - $this->startTime) * 1_000_000);
5652
$this->executionState->notifications++;
5753

5854
$this->executionState->records->write(new Notification(
@@ -67,7 +63,7 @@ public function __invoke(NotificationSending|NotificationSent $event): void
6763
user: $this->executionState->user->id(),
6864
channel: $event->channel,
6965
class: $class,
70-
duration: $this->duration,
66+
duration: (int) round(($now - $this->startTime) * 1_000_000),
7167
failed: false, // TODO: The framework doesn't dispatch the `NotificationFailed` event.
7268
));
7369
}

‎src/Sensors/QueuedJobSensor.php

+20-4
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,21 @@
44

55
use Illuminate\Events\CallQueuedListener;
66
use Illuminate\Queue\Events\JobQueued;
7+
use Illuminate\Queue\Events\JobQueueing;
78
use Laravel\Nightwatch\Clock;
89
use Laravel\Nightwatch\Concerns\NormalizesQueue;
910
use Laravel\Nightwatch\Records\QueuedJob;
1011
use Laravel\Nightwatch\State\CommandState;
1112
use Laravel\Nightwatch\State\RequestState;
1213
use ReflectionClass;
14+
use RuntimeException;
1315

1416
use function hash;
1517
use function is_object;
1618
use function is_string;
1719
use function method_exists;
1820
use function property_exists;
21+
use function round;
1922

2023
/**
2124
* @internal
@@ -24,6 +27,8 @@ final class QueuedJobSensor
2427
{
2528
use NormalizesQueue;
2629

30+
private ?float $startTime = null;
31+
2732
/**
2833
* @param array<string, array{ queue?: string, driver?: string, prefix?: string, suffix?: string }> $connectionConfig
2934
*/
@@ -35,19 +40,30 @@ public function __construct(
3540
//
3641
}
3742

38-
public function __invoke(JobQueued $event): void
43+
public function __invoke(JobQueueing|JobQueued $event): void
3944
{
40-
$nowMicrotime = $this->clock->microtime();
45+
$now = $this->clock->microtime();
46+
47+
if ($event instanceof JobQueueing) {
48+
$this->startTime = $now;
49+
50+
return;
51+
}
52+
4153
$name = match (true) {
4254
is_string($event->job) => $event->job,
4355
method_exists($event->job, 'displayName') => $event->job->displayName(),
4456
default => $event->job::class,
4557
};
4658

59+
if ($this->startTime === null) {
60+
throw new RuntimeException("No start time found for [{$name}].");
61+
}
62+
4763
$this->executionState->jobsQueued++;
4864

4965
$this->executionState->records->write(new QueuedJob(
50-
timestamp: $nowMicrotime,
66+
timestamp: $now,
5167
deploy: $this->executionState->deploy,
5268
server: $this->executionState->server,
5369
_group: hash('md5', $name),
@@ -60,7 +76,7 @@ public function __invoke(JobQueued $event): void
6076
name: $name,
6177
connection: $event->connectionName,
6278
queue: $this->normalizeQueue($event->connectionName, $this->resolveQueue($event)),
63-
duration: 0, // TODO
79+
duration: (int) round(($now - $this->startTime) * 1_000_000)
6480
));
6581
}
6682

‎tests/Feature/Sensors/QueuedJobSensorTest.php

+10-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Illuminate\Foundation\Bus\Dispatchable;
88
use Illuminate\Foundation\Testing\RefreshDatabaseState;
99
use Illuminate\Queue\Events\JobQueued;
10+
use Illuminate\Queue\Events\JobQueueing;
1011
use Illuminate\Queue\InteractsWithQueue;
1112
use Illuminate\Queue\SerializesModels;
1213
use Illuminate\Support\Facades\Bus;
@@ -74,7 +75,7 @@
7475
'name' => 'MyJob',
7576
'connection' => 'database',
7677
'queue' => 'default',
77-
'duration' => 0,
78+
'duration' => 5200,
7879
],
7980
]);
8081
});
@@ -184,6 +185,14 @@
184185
'suffix' => '-production',
185186
]);
186187

188+
nightwatch()->sensor->queuedJob(new JobQueueing(
189+
connectionName: 'my-sqs-queue',
190+
queue: 'https://sqs.us-east-1.amazonaws.com/your-account-id/queue-name-production',
191+
job: 'MyJobClass',
192+
payload: '{"uuid":"00000000-0000-0000-0000-000000000000"}',
193+
delay: 0,
194+
));
195+
187196
nightwatch()->sensor->queuedJob(new JobQueued(
188197
connectionName: 'my-sqs-queue',
189198
queue: 'https://sqs.us-east-1.amazonaws.com/your-account-id/queue-name-production',

‎tests/Unit/Hooks/JobQueuedListenerTest.php ‎tests/Unit/Hooks/QueuedJobListenerTest.php

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
<?php
22

33
use Illuminate\Queue\Events\JobQueued;
4-
use Laravel\Nightwatch\Hooks\JobQueuedListener;
4+
use Illuminate\Queue\Events\JobQueueing;
5+
use Laravel\Nightwatch\Hooks\QueuedJobListener;
56
use Laravel\Nightwatch\SensorManager;
67

78
it('gracefully handles exceptions', function () {
@@ -11,14 +12,14 @@
1112

1213
public function __construct() {}
1314

14-
public function queuedJob(JobQueued $event): void
15+
public function queuedJob(JobQueueing|JobQueued $event): void
1516
{
1617
$this->thrown = true;
1718

1819
throw new RuntimeException('Whoops!');
1920
}
2021
});
21-
$handler = new JobQueuedListener($nightwatch);
22+
$handler = new QueuedJobListener($nightwatch);
2223

2324
$handler(new JobQueued('redis', 'default', '1', fn () => null, '{}', 0));
2425

0 commit comments

Comments
 (0)
Please sign in to comment.