TTR Does not work as advertised.
Nobody has claimed this yet.
- Dominant language
- PHP
- Stars
- 1.1k
- Forks
- 285
- Avg merge
- 5d 3h
- Merged PRs (30d)
- 2
Description
What steps will reproduce the problem?
Set up any queue with TTR 30.
Push a job that does this:
for ($i = 0; $i < 1000; $i++) {
echo $i . "\n";
sleep 1;
}
Run 2 queue runners.
What's expected?
Based on the docs:
The TTR option sets the time to reserve for job execution. If the execution of a job takes longer than this
time, execution will be stopped and it will be returned to the queue for later retry.
What do you get instead?
After the 30 seconds have passed the job is released by the queue (beanstalkd).
The second worker picks it up and starts executing it.
The first worker continues to execute it.
There are 2 solutions:
Proposal 1: Fix docs
Fixing the documentation will make it work as expected.
Proposal 2: Fix functionality
There are 2 methods of executing jobs, in-process and isolated process.
In the case of using an isolated process the solution is simple: kill it just before the TTR expires.
In case of in-process execution I have created a proof of concept to handle the TTR:
<?php
declare(ticks=1);
$end = microtime(true) + 5;
$handler = function() use ($end) {
$remaining = $end - microtime(true);
echo ".";
if ($remaining < 0) {
throw new \Exception('time limit exceeded');
}
};
register_tick_function($handler);
try {
$i = 0;
while ($i < 1000) {
// This handler suppresses errors.
try {
echo "\$i is $i\n";
sleep(1);
$i++;
} catch (\Throwable $t) {
// echo "E: {$t->getMessage()}\n";
}
}
} catch(\Throwable $t) {
unregister_tick_function($handler);
echo "Caught: {$t->getMessage()}\n";
} finally {
unregister_tick_function($handler);
}
..$i is 0
....$i is 1
....$i is 2
....$i is 3
....$i is 4
...Caught: time limit exceeded
The idea is simple:
- Register a tick function that keeps track of time.
- As soon as time is over we start throwing exceptions.
- Job code might be catching exceptions, but as soon as their try clause is called we throw another one (this is repeated for nested
try..catch). - Finally the exception reaches our own
catchclause where immediately unregister the tick function.
This way we can guarantee that no 2 workers are executing the same task at any point in time.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing the TTR 30 scenario with beanstalkd and two queue runners, then inspect the in-process and isolated-process execution paths described in the issue. Compare the current behavior with the TTR documentation and determine whether the accepted outcome is a documentation correction or enforcement that prevents both workers from executing the job.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- php
- Domain
- backend, distributed-systems
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 30/100