2
2
3
3
declare (strict_types=1 );
4
4
5
- namespace App \API \ Tasks ;
5
+ namespace App \API ;
6
6
7
7
use App \Commands \System \TasksCommand ;
8
8
use App \Libs \Attributes \Route \Get ;
9
9
use App \Libs \Attributes \Route \Route ;
10
10
use App \Libs \Enums \Http \Status ;
11
+ use App \Model \Events \Event ;
12
+ use App \Model \Events \EventsRepository ;
13
+ use App \Model \Events \EventsTable ;
14
+ use App \Model \Events \EventStatus ;
11
15
use Cron \CronExpression ;
12
- use DateInterval ;
13
16
use Psr \Http \Message \ResponseInterface as iResponse ;
14
17
use Psr \Http \Message \ServerRequestInterface as iRequest ;
15
- use Psr \SimpleCache \CacheInterface as iCache ;
16
18
use Psr \SimpleCache \InvalidArgumentException ;
17
19
18
- final class Index
20
+ final class Tasks
19
21
{
20
22
public const string URL = '%{api.prefix}/tasks ' ;
21
23
22
- public function __construct (private readonly iCache $ cache )
24
+ public function __construct (private EventsRepository $ eventsRepo )
23
25
{
24
26
}
25
27
@@ -29,22 +31,28 @@ public function __construct(private readonly iCache $cache)
29
31
#[Get(self ::URL . '[/] ' , name: 'tasks.index ' )]
30
32
public function tasksIndex (): iResponse
31
33
{
32
- $ queuedTasks = $ this ->cache ->get ('queued_tasks ' , []);
33
- $ response = [
34
- 'tasks ' => [],
35
- 'queued ' => $ queuedTasks ,
36
- 'status ' => isTaskWorkerRunning (),
37
- ];
34
+ $ tasks = [];
38
35
39
36
foreach (TasksCommand::getTasks () as $ task ) {
40
37
$ task = self ::formatTask ($ task );
41
- $ task ['queued ' ] = in_array (ag ($ task , 'name ' ), $ queuedTasks );
38
+ if (true === (bool )ag ($ task , 'hide ' , false )) {
39
+ continue ;
40
+ }
42
41
42
+ $ task ['queued ' ] = null !== $ this ->isQueued (ag ($ task , 'name ' ));
43
+ $ tasks [] = $ task ;
44
+ }
43
45
44
- $ response ['tasks ' ][] = $ task ;
46
+ $ queued = [];
47
+ foreach (array_filter ($ tasks , fn ($ item ) => $ item ['queued ' ] === true ) as $ item ) {
48
+ $ queued [] = $ item ['name ' ];
45
49
}
46
50
47
- return api_response (Status::OK , $ response );
51
+ return api_response (Status::OK , [
52
+ 'tasks ' => $ tasks ,
53
+ 'queued ' => $ queued ,
54
+ 'status ' => isTaskWorkerRunning (),
55
+ ]);
48
56
}
49
57
50
58
/**
@@ -59,29 +67,41 @@ public function taskQueue(iRequest $request, string $id): iResponse
59
67
return api_error ('Task not found. ' , Status::NOT_FOUND );
60
68
}
61
69
62
- $ queuedTasks = $ this ->cache -> get ( ' queued_tasks ' , [] );
70
+ $ queuedTask = $ this ->isQueued ( ag ( $ task , ' name ' ) );
63
71
64
72
if ('POST ' === $ request ->getMethod ()) {
65
- $ queuedTasks [] = $ id ;
66
- $ this ->cache ->set ('queued_tasks ' , $ queuedTasks , new DateInterval ('P3D ' ));
67
- return api_response (Status::ACCEPTED , ['queue ' => $ queuedTasks ]);
73
+ if (null !== $ queuedTask ) {
74
+ return api_error ('Task already queued. ' , Status::CONFLICT );
75
+ }
76
+
77
+ $ event = queueEvent (TasksCommand::NAME , ['name ' => $ id ], [
78
+ EventsTable::COLUMN_REFERENCE => r ('task://{name} ' , ['name ' => $ id ]),
79
+ ]);
80
+
81
+ return api_response (Status::ACCEPTED , $ event ->getAll ());
68
82
}
69
83
70
84
if ('DELETE ' === $ request ->getMethod ()) {
71
- $ queuedTasks = array_filter ($ queuedTasks , fn ($ v ) => $ v !== $ id );
72
- $ this ->cache ->set ('queued_tasks ' , $ queuedTasks , new DateInterval ('P3D ' ));
73
- return api_response (Status::OK , ['queue ' => $ queuedTasks ]);
85
+ if (null === $ queuedTask ) {
86
+ return api_error ('Task not queued. ' , Status::NOT_FOUND );
87
+ }
88
+
89
+ if ($ queuedTask ->status === EventStatus::RUNNING ) {
90
+ return api_error ('Cannot remove task in running state. ' , Status::BAD_REQUEST );
91
+ }
92
+
93
+ $ queuedTask ->status = EventStatus::CANCELLED ;
94
+ $ this ->eventsRepo ->save ($ queuedTask );
95
+
96
+ return api_response (Status::OK );
74
97
}
75
98
76
99
return api_response (Status::OK , [
77
100
'task ' => $ id ,
78
- 'is_queued ' => in_array ( $ id , $ queuedTasks ) ,
101
+ 'is_queued ' => null !== $ queuedTask ,
79
102
]);
80
103
}
81
104
82
- /**
83
- * @throws InvalidArgumentException
84
- */
85
105
#[Get(self ::URL . '/{id:[a-zA-Z0-9_-]+}[/] ' , name: 'tasks.task.view ' )]
86
106
public function taskView (string $ id ): iResponse
87
107
{
@@ -91,10 +111,8 @@ public function taskView(string $id): iResponse
91
111
return api_error ('Task not found. ' , Status::NOT_FOUND );
92
112
}
93
113
94
- $ queuedTasks = $ this ->cache ->get ('queued_tasks ' , []);
95
-
96
- $ data = Index::formatTask ($ task );
97
- $ data ['queued ' ] = in_array (ag ($ task , 'name ' ), $ queuedTasks );
114
+ $ data = Tasks::formatTask ($ task );
115
+ $ data ['queued ' ] = null !== $ this ->isQueued (ag ($ task , 'name ' ));
98
116
99
117
return api_response (Status::OK , $ data );
100
118
}
@@ -115,6 +133,7 @@ private function formatTask(array $task): array
115
133
'prev_run ' => null ,
116
134
'command ' => ag ($ task , 'command ' ),
117
135
'args ' => ag ($ task , 'args ' ),
136
+ 'hide ' => (bool )ag ($ task , 'hide ' , false ),
118
137
];
119
138
120
139
if (!is_string ($ item ['command ' ])) {
@@ -136,4 +155,11 @@ private function formatTask(array $task): array
136
155
137
156
return $ item ;
138
157
}
158
+
159
+ private function isQueued (string $ id ): Event |null
160
+ {
161
+ return $ this ->eventsRepo ->findByReference (r ('task://{name} ' , ['name ' => $ id ]), [
162
+ EventsTable::COLUMN_STATUS => EventStatus::PENDING ->value
163
+ ]);
164
+ }
139
165
}
0 commit comments