Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
Total | |
100.00% |
1 / 1 |
|
100.00% |
9 / 9 |
CRAP | |
100.00% |
50 / 50 |
Factory | |
100.00% |
1 / 1 |
|
100.00% |
9 / 9 |
17 | |
100.00% |
50 / 50 |
__construct | |
100.00% |
1 / 1 |
1 | |
100.00% |
5 / 5 |
|||
addEnvs | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
throwExceptionsOnFailure | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
addProcess | |
100.00% |
1 / 1 |
1 | |
100.00% |
4 / 4 |
|||
run | |
100.00% |
1 / 1 |
1 | |
100.00% |
4 / 4 |
|||
start | |
100.00% |
1 / 1 |
1 | |
100.00% |
4 / 4 |
|||
startDetached | |
100.00% |
1 / 1 |
1 | |
100.00% |
3 / 3 |
|||
getProcessInfos | |
100.00% |
1 / 1 |
2 | |
100.00% |
5 / 5 |
|||
launch | |
100.00% |
1 / 1 |
8 | |
100.00% |
21 / 21 |
1 | <?php |
2 | |
3 | namespace Qmp\Laravel\AsyncProcessFactory; |
4 | |
5 | use Illuminate\Support\Collection; |
6 | use Illuminate\Support\Facades\Log; |
7 | use Qmp\Laravel\AsyncProcessFactory\Exceptions\SubProcessException; |
8 | |
9 | class Factory |
10 | { |
11 | /** |
12 | * The process stack collection |
13 | * |
14 | * @var Illuminate\Support\Collection |
15 | */ |
16 | protected $processStack; |
17 | |
18 | /** |
19 | * The artisan command for all the processes in the factory |
20 | * |
21 | * @param string $command |
22 | */ |
23 | protected $command; |
24 | |
25 | /** |
26 | * The default callback |
27 | * |
28 | * @var callable |
29 | */ |
30 | protected $callBack = null; |
31 | |
32 | /** |
33 | * Run or start |
34 | * |
35 | * @var string |
36 | */ |
37 | protected $launchType = null; |
38 | |
39 | /** |
40 | * The process stack infos |
41 | * |
42 | * @var Illuminate\Support\Collection |
43 | */ |
44 | protected $processInfos; |
45 | |
46 | /** |
47 | * Envs vars |
48 | * |
49 | * @var Collection |
50 | */ |
51 | protected $envs; |
52 | |
53 | /** |
54 | * If process fail, throw exception |
55 | * |
56 | * @var boolean |
57 | */ |
58 | protected $throw = false; |
59 | |
60 | /** |
61 | * Create a new process factory |
62 | * |
63 | * @param string $command |
64 | */ |
65 | public function __construct(string $command) |
66 | { |
67 | $this->processStack = collect([]); |
68 | $this->processInfos = collect([]); |
69 | $this->command = $command; |
70 | $this->envs = collect([]); |
71 | } |
72 | |
73 | /** |
74 | * Undocumented function |
75 | * |
76 | * @param array $envs |
77 | * @return void |
78 | */ |
79 | public function addEnvs(array $envs) |
80 | { |
81 | $this->envs = $this->envs->merge($envs); |
82 | } |
83 | |
84 | /** |
85 | * Undocumented function |
86 | * |
87 | * @param boolean $trhow |
88 | * @return void |
89 | */ |
90 | public function throwExceptionsOnFailure($throw = true) |
91 | { |
92 | $this->throw = $throw; |
93 | } |
94 | |
95 | /** |
96 | * Add a process to the stack |
97 | * |
98 | * @param array $options |
99 | * @return void |
100 | */ |
101 | public function addProcess(array $options = []): void |
102 | { |
103 | $process = new ProcessHandler($this->command); |
104 | $process->addOptions($options); |
105 | |
106 | $this->processStack->put($process->getkey(), $process); |
107 | } |
108 | |
109 | /** |
110 | * Start processes one by one |
111 | * |
112 | * @param callable $callback |
113 | * @return void |
114 | */ |
115 | public function run(callable $callback = null): void |
116 | { |
117 | $this->callBack = $callback; |
118 | $this->launchType = 'run'; |
119 | $this->launch(); |
120 | } |
121 | |
122 | /** |
123 | * Start Processes in parralel |
124 | * |
125 | * @param callable $callback |
126 | * @return void |
127 | */ |
128 | public function start(callable $callback = null): void |
129 | { |
130 | $this->callBack = $callback; |
131 | $this->launchType = 'start'; |
132 | $this->launch(); |
133 | } |
134 | |
135 | /** |
136 | * Start Processes in parralel and detached |
137 | * |
138 | * @param callable $callback |
139 | * @return void |
140 | */ |
141 | public function startDetached(): void |
142 | { |
143 | $this->launchType = 'startDetached'; |
144 | $this->launch(); |
145 | } |
146 | |
147 | /** |
148 | * Start Processes in parralel |
149 | * |
150 | * @param callable $callback |
151 | * @return Illuminate\Support\Collection |
152 | */ |
153 | public function getProcessInfos(callable $closure = null): Collection |
154 | { |
155 | if ($closure) { |
156 | return $this->processInfos->mapWithKeys(function ($process) use ($closure) { |
157 | return [$closure($process->get('options')) => $process]; |
158 | }); |
159 | } |
160 | |
161 | return $this->processInfos; |
162 | } |
163 | |
164 | /** |
165 | * Launch process stack |
166 | * |
167 | * @return void |
168 | */ |
169 | protected function launch(): void |
170 | { |
171 | try { |
172 | $message = $this->launchType === 'startDetached' ? 'start detached from' : $this->launchType . ' in'; |
173 | |
174 | $this->processStack->each(function ($process, $key) use ($message) { |
175 | Log::debug("Process $message factory ! {task #$key}"); |
176 | if (!$process->isRunning()) { |
177 | $started = $process->setEnv($this->envs)->{$this->launchType}($this->callBack); |
178 | $this->processInfos->push($process->getInfos($started)); |
179 | } |
180 | }); |
181 | |
182 | if ($this->launchType !== 'startDetached') { |
183 | while ($this->processStack->count()) { |
184 | $this->processStack->each(function ($process, $key) { |
185 | if (!$process->isRunning()) { |
186 | $this->processStack->forget($key); |
187 | Log::debug("Process in factory is done ! {task #$key}"); |
188 | } |
189 | }); |
190 | } |
191 | } |
192 | } catch (SubProcessException $e) { |
193 | if ($this->throw) { |
194 | throw $e; |
195 | } else { |
196 | Log::debug("Process in factory fail ! {task #" . $e->getKey() . "}"); |
197 | $this->processStack->forget($e->getKey()); |
198 | $this->launch(); |
199 | } |
200 | } |
201 | } |
202 | } |