2
2
3
3
namespace Medilies \RmQ ;
4
4
5
+ use Closure ;
5
6
use Illuminate \Support \Facades \Config ;
6
7
use Illuminate \Support \Facades \Date ;
8
+ use Illuminate \Support \Facades \DB ;
7
9
use Medilies \RmQ \Models \RmqFile ;
8
10
use Symfony \Component \Uid \Ulid ;
11
+ use Throwable ;
9
12
use TypeError ;
10
13
11
14
class RmQ
12
15
{
13
16
private string $ instance ;
14
17
15
- private bool $ useArray = false ;
18
+ private bool $ isUsingMiddleware = false ;
19
+
20
+ private bool $ isWithinTransaction = false ;
21
+
22
+ private bool $ hasFilesInDb = false ;
16
23
17
24
/** @var string[] */
18
- private array $ store = [];
25
+ private array $ arrayStorage = []; // ? Dto[]
26
+
27
+ /** @var string[] */
28
+ private array $ transactionStorage = [];
19
29
20
30
public function __construct ()
21
31
{
22
32
$ this ->instance = (new Ulid )->toRfc4122 ();
23
33
}
24
34
25
- public function useArray ( ): static
35
+ public function transaction ( Closure $ callback ): static
26
36
{
27
- $ this ->useArray = true ;
37
+ $ this ->withinTransaction ();
38
+
39
+ try {
40
+ DB ::transaction ($ callback ); // @phpstan-ignore-line
41
+
42
+ if ($ this ->isUsingMiddleware ) {
43
+ $ this ->arrayStorage = array_merge ($ this ->arrayStorage , $ this ->transactionStorage );
44
+ } else {
45
+ $ this ->stageInDb ($ this ->transactionStorage );
46
+ }
47
+ } catch (Throwable $ th ) {
48
+ throw $ th ;
49
+ } finally {
50
+ $ this ->transactionStorage = [];
51
+
52
+ $ this ->withinTransaction (false );
53
+ }
28
54
29
55
return $ this ;
30
56
}
@@ -35,16 +61,16 @@ public function stage(array|string $paths): void
35
61
// TODO: take query builder with one selected column => force stageInDb
36
62
// ? validate not empty or exists?
37
63
38
- $ this ->useArray ?
39
- $ this ->stageInArray ($ paths ) :
64
+ $ this ->isWithinTransaction ?
65
+ $ this ->stageInTransactionStorage ($ paths ) :
40
66
$ this ->stageInDb ($ paths );
41
67
}
42
68
43
69
/** @param string[]|string $paths */
44
- private function stageInArray (array |string $ paths ): void
70
+ private function stageInTransactionStorage (array |string $ paths ): void
45
71
{
46
72
if (is_string ($ paths )) {
47
- $ this ->store [] = $ paths ;
73
+ $ this ->transactionStorage [] = $ paths ;
48
74
49
75
return ;
50
76
}
@@ -54,28 +80,29 @@ private function stageInArray(array|string $paths): void
54
80
->filter (fn (mixed $ path ) => is_string ($ path ))
55
81
->toArray ();
56
82
57
- $ this ->store = array_merge ($ this ->store , $ newPaths );
83
+ $ this ->transactionStorage = array_merge ($ this ->transactionStorage , $ newPaths );
58
84
}
59
85
60
86
/** @param string[]|string $paths */
61
87
private function stageInDb (array |string $ paths ): void
62
88
{
63
89
$ data = match (true ) {
64
- is_string ($ paths ) => $ this ->pathToRecord ($ paths ),
90
+ is_string ($ paths ) => $ this ->pathToStagedRecord ($ paths ),
65
91
is_array ($ paths ) => collect ($ paths )
66
92
->filter (fn (mixed $ path ) => is_string ($ path ))
67
- ->map (fn (string $ path ) => $ this ->pathToRecord ($ path ))
93
+ ->map (fn (string $ path ) => $ this ->pathToStagedRecord ($ path ))
68
94
->toArray (),
69
95
};
70
96
71
97
RmqFile::insert ($ data );
98
+
99
+ $ this ->hasFilesInDb = true ;
72
100
}
73
101
74
102
public function delete (): void
75
103
{
76
- $ this ->useArray ?
77
- $ this ->performDeleteUsingArray () :
78
- $ this ->performDeleteUsingDb (true );
104
+ $ this ->performDeleteUsingDb (true );
105
+ $ this ->performDeleteUsingArrayStorage ();
79
106
}
80
107
81
108
public function deleteAll (): void
@@ -86,17 +113,11 @@ public function deleteAll(): void
86
113
throw new TypeError ('rm-q.after must be an integer ' );
87
114
}
88
115
89
- $ this ->performDeleteUsingDb (false , $ after );
90
- }
116
+ if ($ this ->hasFilesInDb ) {
117
+ $ this ->performDeleteUsingDb (false , $ after );
118
+ }
91
119
92
- /** @return array{path: string, instance: string} */
93
- private function pathToRecord (string $ path , int $ status = RmqFile::STAGED ): array
94
- {
95
- return [
96
- 'path ' => $ path ,
97
- 'instance ' => $ this ->instance ,
98
- 'status ' => $ status ,
99
- ];
120
+ $ this ->performDeleteUsingArrayStorage ();
100
121
}
101
122
102
123
private function performDeleteUsingDb (bool $ filterInstance = false , int $ beforeSeconds = 0 ): void
@@ -131,15 +152,17 @@ private function performDeleteUsingDb(bool $filterInstance = false, int $beforeS
131
152
'processed_at ' => $ now ,
132
153
]);
133
154
}
155
+
156
+ $ this ->hasFilesInDb = false ;
134
157
}
135
158
136
- private function performDeleteUsingArray (): void
159
+ private function performDeleteUsingArrayStorage (): void
137
160
{
138
161
$ now = Date::now ();
139
162
140
163
$ data = [];
141
164
142
- foreach ($ this ->store as $ path ) {
165
+ foreach ($ this ->arrayStorage as $ path ) {
143
166
if (@unlink ($ path )) {
144
167
$ data [] = [
145
168
'path ' => $ path ,
@@ -161,9 +184,33 @@ private function performDeleteUsingArray(): void
161
184
RmqFile::insert ($ data );
162
185
}
163
186
187
+ public function usingMiddleware (bool $ flag = true ): static
188
+ {
189
+ $ this ->isUsingMiddleware = $ flag ;
190
+
191
+ return $ this ;
192
+ }
193
+
194
+ public function withinTransaction (bool $ flag = true ): static
195
+ {
196
+ $ this ->isWithinTransaction = $ flag ;
197
+
198
+ return $ this ;
199
+ }
200
+
201
+ /** @return array{path: string} */
202
+ private function pathToStagedRecord (string $ path ): array
203
+ {
204
+ return [
205
+ 'path ' => $ path ,
206
+ 'instance ' => $ this ->instance ,
207
+ 'status ' => RmqFile::STAGED ,
208
+ ];
209
+ }
210
+
164
211
/** @return string[] */
165
- public function getStore (): array
212
+ public function getStorage (): array
166
213
{
167
- return $ this ->store ;
214
+ return $ this ->arrayStorage ;
168
215
}
169
216
}
0 commit comments