Skip to content

Commit 8d52dd0

Browse files
author
Arif Hoque
committed
timeout option added for per job execution
1 parent 1dc6066 commit 8d52dd0

File tree

6 files changed

+83
-3
lines changed

6 files changed

+83
-3
lines changed

src/Attributes/Queueable.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@ class Queueable
1212
* @param int|null $retryAfter
1313
* @param int|null $delayFor
1414
* @param string|null $onQueue
15+
* @param int|null $timeout
1516
*/
1617
public function __construct(
1718
public ?int $tries = null,
1819
public ?int $retryAfter = null,
1920
public ?int $delayFor = null,
20-
public ?string $onQueue = null
21+
public ?string $onQueue = null,
22+
public ?int $timeout = null
2123
) {}
2224
}

src/Contracts/JobInterface.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,11 @@ public function getJobId(): ?string;
6161
* @return void
6262
*/
6363
public function setJobId(string $id): void;
64+
65+
/**
66+
* Get the timeout in seconds.
67+
*
68+
* @return int|null
69+
*/
70+
public function getTimeout(): ?int;
6471
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
3+
namespace Doppar\Queue\Exceptions;
4+
5+
class JobTimeoutException extends \RuntimeException
6+
{
7+
//
8+
}

src/InteractsWithQueueableAttributes.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ protected function applyQueueableAttributes(): void
4747
if ($attribute->onQueue !== null) {
4848
$this->queueName = $attribute->onQueue;
4949
}
50+
51+
if ($attribute->timeout !== null) {
52+
$this->timeout = $attribute->timeout;
53+
}
5054
}
5155
}
5256
}

src/Job.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,13 @@ abstract class Job implements JobInterface
5252
*/
5353
public $attempts = 0;
5454

55+
/**
56+
* Maximum execution time in seconds.
57+
*
58+
* @var int|null
59+
*/
60+
public $timeout = null;
61+
5562
/**
5663
* Get the number of times the job may be attempted.
5764
*
@@ -150,6 +157,16 @@ public function delayFor(int $delay): self
150157
return $this;
151158
}
152159

160+
/**
161+
* Get the timeout in seconds.
162+
*
163+
* @return int|null
164+
*/
165+
public function getTimeout(): ?int
166+
{
167+
return $this->timeout;
168+
}
169+
153170
/**
154171
* Dispatch the job to the queue.
155172
*

src/QueueWorker.php

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Doppar\Queue;
44

55
use Doppar\Queue\Models\QueueJob;
6+
use Doppar\Queue\Exceptions\JobTimeoutException;
67
use Doppar\Queue\Contracts\JobInterface;
78

89
class QueueWorker
@@ -187,8 +188,8 @@ protected function processJob(QueueJob $queueJob): void
187188
($this->onJobProcessing)($job);
188189
}
189190

190-
// Execute the job
191-
$this->executeJob($job);
191+
// Execute the job with timeout
192+
$this->executeJobWithTimeout($job);
192193

193194
// Delete the job from queue if successful
194195
$this->manager->delete($queueJob);
@@ -202,6 +203,47 @@ protected function processJob(QueueJob $queueJob): void
202203
}
203204
}
204205

206+
/**
207+
* Execute a job with timeout protection.
208+
*
209+
* @param JobInterface $job
210+
* @return void
211+
* @throws \Throwable
212+
*/
213+
protected function executeJobWithTimeout(JobInterface $job): void
214+
{
215+
$timeout = $job->getTimeout();
216+
217+
if ($timeout === null || !extension_loaded('pcntl')) {
218+
// No timeout or pcntl not available, execute normally
219+
$this->executeJob($job);
220+
return;
221+
}
222+
223+
// Set up timeout handler
224+
$timedOut = false;
225+
226+
pcntl_signal(SIGALRM, function () use (&$timedOut) {
227+
$timedOut = true;
228+
});
229+
230+
pcntl_alarm($timeout);
231+
232+
try {
233+
$this->executeJob($job);
234+
pcntl_alarm(0);
235+
} catch (\Throwable $e) {
236+
pcntl_alarm(0);
237+
throw $e;
238+
}
239+
240+
if ($timedOut) {
241+
throw new JobTimeoutException(
242+
"Job exceeded maximum execution time of {$timeout} seconds"
243+
);
244+
}
245+
}
246+
205247
/**
206248
* Execute a job.
207249
*

0 commit comments

Comments
 (0)