-
Notifications
You must be signed in to change notification settings - Fork 11.6k
Open
Description
Laravel Version
12.24.0
PHP Version
8.4.4
Database Driver & Version
No response
Description
The Sleep facade behaves weirdly in queued jobs via Horizon.
Let's take this job:
class SleepTestJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public function handle(): void
{
Log::debug("Should sleep for 60 seconds");
Sleep::for(60)->seconds();
Log::debug("Should be awake now");
}
}
In this case, the following happens (made up timestamps):
- 00:00:00 - "Should sleep for 60 seconds" gets logged
- 00:00:37 - "Should be awake now" gets logged - even though 60 seconds has not passed yet
- Sleep::goodnight() goes into action via the destructor and tries to sleep the remaining time
The expected behavior would be:
- 00:00:00 - "Should sleep for 60 seconds" gets logged
- 00:01:00 - "Should be awake now" gets logged
Is there any intended reason why Sleep is not sleeping?
Since Horizon sends pcntl signals that disrupts built-in sleep()
, simply calling sleep()
is not an option. If I understand correctly, the goodnight()
method should do some kind of signal-resistant sleeping, but it's happening at the wrong time and place.
Am I wrong? Is this an intended behavior? If so, what is the usecase?
Currently this is my workaround:
if (!function_exists('true_sleep')) {
function true_sleep(float|int $seconds): void
{
$end = microtime(true) + $seconds;
while (($remaining = $end - microtime(true)) > 0) {
usleep((int)($remaining * 1_000_000));
}
}
}
Steps To Reproduce
class SleepTestJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public function handle(): void
{
Log::debug("Should sleep for 60 seconds");
Sleep::for(60)->seconds();
Log::debug("Should be awake now");
}
}
// console.php
Schedule::job(SleepTestJob::class)
->name('Sleep test job')
->yearly();
php artisan schedule:test // select Sleep test job
Then watch the logs.
Metadata
Metadata
Assignees
Labels
No labels