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
|
<?php
class Taskmanager
{
// Mirror production status codes
const NO_SUCH_TASK = 'NO_SUCH_TASK';
const TASK_FINISHED = 'TASK_FINISHED';
const TASK_ERROR = 'TASK_ERROR';
const TASK_WAITING = 'TASK_WAITING';
const NO_SUCH_INSTANCE = 'NO_SUCH_INSTANCE';
const TASK_PROCESSING = 'TASK_PROCESSING';
public static array $submissions = []; // list of ['id'=>, 'task'=>, 'data'=>]
public static array $statusById = []; // id => ['id'=>, 'statusCode'=>..., 'data'=>[]]
private static int $nextId = 1;
public static function reset(): void
{
self::$submissions = [];
self::$statusById = [];
self::$nextId = 1;
}
/**
* Stubbed submit compatible with production signature.
* @return array{id: string, statusCode: string, data: array}|bool
*/
public static function submit(string $task, ?array $data = null, ?bool $async = false)
{
$id = (string)self::$nextId++;
$record = ['id' => $id, 'task' => $task, 'data' => $data ?? []];
self::$submissions[] = $record;
// Default initial status: waiting
self::$statusById[$id] = ['id' => $id, 'statusCode' => self::TASK_WAITING, 'data' => $record['data']];
if ($async) return true;
return self::$statusById[$id];
}
/**
* @param string|array $task
*/
public static function status($task)
{
if (is_array($task) && isset($task['id'])) {
$task = $task['id'];
}
if (!is_string($task)) return false;
return self::$statusById[$task] ?? ['id' => $task, 'statusCode' => self::NO_SUCH_TASK];
}
public static function isFailed($task): bool
{
if (!is_array($task) || !isset($task['statusCode']) || !isset($task['id']))
return true;
// Consider failed if statusCode is none of waiting/processing/finished
return !in_array($task['statusCode'], [self::TASK_WAITING, self::TASK_PROCESSING, self::TASK_FINISHED], true);
}
public static function isFinished($task): bool
{
if (!is_array($task) || !isset($task['statusCode']) || !isset($task['id']))
return false;
return !in_array($task['statusCode'], [self::TASK_WAITING, self::TASK_PROCESSING], true);
}
public static function isRunning($task): bool
{
if (!is_array($task) || !isset($task['statusCode']) || !isset($task['id']))
return false;
return in_array($task['statusCode'], [self::TASK_WAITING, self::TASK_PROCESSING], true);
}
public static function isTask($task): bool
{
if ($task === false) return false;
if (is_string($task)) {
$task = self::status($task);
}
return isset($task['statusCode'])
&& $task['statusCode'] !== self::NO_SUCH_INSTANCE
&& $task['statusCode'] !== self::NO_SUCH_TASK;
}
public static function addErrorMessage($task): void
{
if (!class_exists('Message')) return;
if ($task === false) {
Message::addError('main.taskmanager-error');
return;
}
if (!isset($task['statusCode'])) {
Message::addError('main.taskmanager-format');
return;
}
if (isset($task['data']['error'])) {
Message::addError('main.task-error', $task['statusCode'] . ' (' . $task['data']['error'] . ')');
return;
}
Message::addError('main.task-error', $task['statusCode']);
}
/**
* Release a task: mark as NO_SUCH_TASK from now on
*/
public static function release($task): void
{
if (is_array($task) && isset($task['id'])) {
$task = $task['id'];
}
if (!is_string($task)) return;
self::$statusById[$task] = ['id' => $task, 'statusCode' => self::NO_SUCH_TASK];
}
}
|