-
Notifications
You must be signed in to change notification settings - Fork 139
Expand file tree
/
Copy pathConfig.php
More file actions
202 lines (171 loc) · 5.65 KB
/
Copy pathConfig.php
File metadata and controls
202 lines (171 loc) · 5.65 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
<?php
declare(strict_types=1);
namespace Queue\Queue;
use Cake\Core\Configure;
use InvalidArgumentException;
class Config {
/**
* Timeout in seconds, after which the Task is reassigned to a new worker
* if not finished successfully.
* This should be high enough that it cannot still be running on a zombie worker (>> 2x) and cannot be zero.
*
* @return int
*/
public static function defaultworkertimeout(): int {
// Check for new config name first, fall back to old name for backward compatibility
$timeout = Configure::read('Queue.defaultRequeueTimeout');
if ($timeout === null) {
$timeout = Configure::read('Queue.defaultworkertimeout');
if ($timeout !== null) {
trigger_error(
'Config key "Queue.defaultworkertimeout" is deprecated. Use "Queue.defaultRequeueTimeout" instead.',
E_USER_DEPRECATED,
);
}
}
$timeout ??= 600; // 10min default
if ($timeout <= 0) {
throw new InvalidArgumentException('Queue.defaultRequeueTimeout (or deprecated defaultworkertimeout) is less or equal than zero. Indefinite running of jobs is not supported.');
}
return $timeout;
}
/**
* Seconds of running time after which the worker will terminate.
* Note: 0 = unlimited is allowed but not recommended. Use a non-zero value for better control.
*
* @return int
*/
public static function workermaxruntime(): int {
// Check for new config name first, fall back to old name for backward compatibility
$runtime = Configure::read('Queue.workerLifetime');
if ($runtime === null) {
$runtime = Configure::read('Queue.workermaxruntime');
if ($runtime !== null) {
trigger_error(
'Config key "Queue.workermaxruntime" is deprecated. Use "Queue.workerLifetime" instead.',
E_USER_DEPRECATED,
);
}
}
return $runtime ?? 120;
}
/**
* Minimum number of seconds before a cleanup run will remove a completed task (set to 0 to disable)
*
* @return int
*/
public static function cleanuptimeout(): int {
return Configure::read('Queue.cleanuptimeout', 2592000); // 30 days
}
/**
* @return int
*/
public static function sleeptime(): int {
return Configure::read('Queue.sleeptime', 10);
}
/**
* Threshold in seconds after which a queue_processes row whose `modified`
* timestamp is older is considered stale by a starting worker. Workers
* heartbeat (refresh `modified`) on every loop iteration, so a row not
* refreshed in ~90s almost certainly belongs to a dead worker — typically
* a container that was force-restarted. This is intentionally much shorter
* than `defaultRequeueTimeout` (which governs in-flight job requeueing).
*
* @return int
*/
public static function staleHeartbeatThreshold(): int {
$threshold = Configure::read('Queue.staleHeartbeatThreshold');
return $threshold ?? 90;
}
/**
* @return int
*/
public static function gcprob(): int {
return Configure::read('Queue.gcprob', 10);
}
/**
* @return int
*/
public static function defaultworkerretries(): int {
// Check for new config name first, fall back to old name for backward compatibility
$retries = Configure::read('Queue.defaultJobRetries');
if ($retries === null) {
$retries = Configure::read('Queue.defaultworkerretries');
if ($retries !== null) {
trigger_error(
'Config key "Queue.defaultworkerretries" is deprecated. Use "Queue.defaultJobRetries" instead.',
E_USER_DEPRECATED,
);
}
}
return $retries ?? 1;
}
/**
* @return int
*/
public static function maxworkers(): int {
return Configure::read('Queue.maxworkers', 1);
}
/**
* @return array<string>
*/
public static function ignoredTasks(): array {
$a = Configure::read('Queue.ignoredTasks', []);
if (!is_array($a)) {
throw new InvalidArgumentException('Queue.ignoredTasks is not an array');
}
return $a;
}
/**
* @param array<string> $tasks
*
* @throws \RuntimeException
*
* @return array<string, array<string, mixed>>
*/
public static function taskConfig(array $tasks): array {
$config = [];
$defaultTimeout = static::defaultworkertimeout();
$taskOverrides = Configure::read('Queue.tasks', []);
foreach ($tasks as $task => $className) {
[$pluginName, $taskName] = pluginSplit($task);
/** @var \Queue\Queue\Task $taskObject */
$taskObject = new $className();
// Get task-specific config overrides from Configure
$taskConfig = $taskOverrides[$task] ?? [];
$taskTimeout = $taskConfig['timeout'] ?? $taskObject->timeout ?? $defaultTimeout;
// Auto-cap task timeout to defaultRequeueTimeout to prevent duplicate execution
if ($taskTimeout > $defaultTimeout) {
$taskTimeout = $defaultTimeout;
}
$config[$task]['class'] = $className;
$config[$task]['name'] = $taskName;
$config[$task]['plugin'] = $pluginName;
$config[$task]['timeout'] = $taskTimeout;
$config[$task]['retries'] = $taskConfig['retries'] ?? $taskObject->retries ?? static::defaultworkerretries();
$config[$task]['rate'] = $taskConfig['rate'] ?? $taskObject->rate;
$config[$task]['costs'] = $taskConfig['costs'] ?? $taskObject->costs;
$config[$task]['unique'] = $taskConfig['unique'] ?? $taskObject->unique;
unset($taskObject);
}
return $config;
}
/**
* @phpstan-param class-string<\Queue\Queue\Task>|string $class
*
* @param string $class
*
* @return string
*/
public static function taskName(string $class): string {
preg_match('#^(.+?)\\\\Queue\\\\Task\\\\(.+?)Task$#', $class, $matches);
if (!$matches) {
throw new InvalidArgumentException('Invalid class name: ' . $class);
}
$namespace = str_replace('\\', '/', $matches[1]);
if ($namespace === Configure::read('App.namespace')) {
return $matches[2];
}
return $namespace . '.' . $matches[2];
}
}