Completed
Push — master ( dd4171...91d4b6 )
by Vuong
01:32
created

Async   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 174
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 5

Test Coverage

Coverage 82.14%

Importance

Changes 0
Metric Value
wmc 15
lcom 2
cbo 5
dl 0
loc 174
ccs 46
cts 56
cp 0.8214
rs 10
c 0
b 0
f 0

10 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 1
A success() 0 9 1
A error() 0 9 1
A timeout() 0 6 1
A wait() 0 4 1
A setConcurrency() 0 4 1
A setTimeout() 0 4 1
A setSleepTimeWait() 0 4 1
A setAutoload() 0 4 1
B run() 0 30 6
1
<?php
2
/**
3
 * @link https://github.com/vuongxuongminh/yii2-async
4
 * @copyright Copyright (c) 2019 Vuong Xuong Minh
5
 * @license [New BSD License](http://www.opensource.org/licenses/bsd-license.php)
6
 */
7
8
namespace vxm\async;
9
10
use Yii;
11
use Closure;
12
use Throwable;
13
14
use yii\base\Component;
15
16
use Spatie\Async\Pool;
17
use Spatie\Async\Runtime\ParentRuntime;
18
19
/**
20
 * Support run code async. To use it, you just config it to your application components in configure file:
21
 *
22
 * ```php
23
 * 'components' => [
24
 *      'async' => 'vxm\async\Async'
25
 * ]
26
 *
27
 * ```
28
 *
29
 * And after that you can run an async code:
30
 *
31
 * ```php
32
 *
33
 * Yii::$app->async->run(function () {
34
 *
35
 *      sleep(15);
36
 * });
37
 *
38
 * ```
39
 *
40
 * If you want to wait until task done, you just to call [[wait]].
41
 *
42
 * ```php
43
 *
44
 * Yii::$app->async->run(function () {
45
 *
46
 *      sleep(15);
47
 * })->wait();
48
 *
49
 * ```
50
 *
51
 * Run multi tasks:
52
 *
53
 * ```php
54
 *
55
 * Yii::$app->async->run(function () {
56
 *
57
 *      sleep(15);
58
 * });
59
 *
60
 * Yii::$app->async->run(function () {
61
 *
62
 *      sleep(15);
63
 * });
64
 *
65
 * Yii::$app->async->wait(); // sleep 30s
66
 * ```
67
 *
68
 * @property string $autoload path of autoload file for runtime task execute environment.
69
 * @property int $sleepTimeWait time to sleep on wait tasks execute.
70
 * @property int $concurrency tasks executable.
71
 * @property int $timeout of task executable.
72
 *
73
 * @author Vuong Minh <[email protected]>
74
 * @since 1.0.0
75
 */
76
class Async extends Component
77
{
78
79
    /**
80
     * @event SuccessEvent an event that is triggered when task done.
81
     */
82
    const EVENT_SUCCESS = 'success';
83
84
    /**
85
     * @event ErrorEvent an event that is triggered when task error.
86
     */
87
    const EVENT_ERROR = 'error';
88
89
    /**
90
     * @event \yii\base\Event an event that is triggered when task timeout.
91
     */
92
    const EVENT_TIMEOUT = 'timeout';
93
94
    /**
95
     * @var Pool handling tasks.
96
     */
97
    protected $pool;
98
99
    /**
100
     * Async constructor.
101
     *
102
     * @param array $config
103
     * @throws \yii\base\InvalidConfigException
104
     */
105 6
    public function __construct($config = [])
106
    {
107 6
        $pool = $this->pool = Yii::createObject(Pool::class);
108 6
        $pool->autoload(__DIR__ . '/RuntimeAutoload.php');
109
110 6
        parent::__construct($config);
111 6
    }
112
113
    /**
114
     * Execute async task.
115
     *
116
     * @param callable|\Spatie\Async\Task|Task $callable need to execute.
117
     * @param array $callbacks event. Have key is an event name, value is a callable triggered when event happen,
118
     * have three events `error`, `success`, `timeout`.
119
     * @return static
120
     */
121 6
    public function run($callable, array $callbacks = []): self
122
    {
123 6
        $process = ParentRuntime::createProcess($callable)
124 6
            ->then(Closure::fromCallable([$this, 'success']))
125 6
            ->catch(Closure::fromCallable([$this, 'error']))
126 6
            ->timeout(Closure::fromCallable([$this, 'timeout']));
127
128 6
        foreach ($callbacks as $name => $callback) {
129
130 4
            switch (strtolower($name)) {
131 4
                case 'success':
132 2
                    $process->then(Closure::fromCallable($callback));
133 2
                    break;
134 2
                case 'error':
135 1
                case 'catch':
136 1
                    $process->catch(Closure::fromCallable($callback));
137 1
                    break;
138 1
                case 'timeout':
139 1
                    $process->timeout(Closure::fromCallable($callback));
140 1
                    break;
141
                default:
142
                    break;
143
            }
144
145
        }
146
147 6
        $this->pool->add($process);
148
149 6
        return $this;
150
    }
151
152
    /**
153
     * This method is called when task executed success.
154
     * When overriding this method, make sure you call the parent implementation to ensure the
155
     * event is triggered.
156
     *
157
     * @param mixed $output of task executed.
158
     * @throws \yii\base\InvalidConfigException
159
     */
160 2
    public function success($output): void
161
    {
162 2
        $event = Yii::createObject([
163 2
            'class' => SuccessEvent::class,
164 2
            'output' => $output
165
        ]);
166
167 2
        $this->trigger(self::EVENT_SUCCESS, $event);
168 2
    }
169
170
    /**
171
     * This method is called when task executed error.
172
     * When overriding this method, make sure you call the parent implementation to ensure the
173
     * event is triggered.
174
     *
175
     * @param Throwable $throwable when executing task.
176
     * @throws \yii\base\InvalidConfigException
177
     */
178 2
    public function error(Throwable $throwable): void
179
    {
180 2
        $event = Yii::createObject([
181 2
            'class' => ErrorEvent::class,
182 2
            'throwable' => $throwable
183
        ]);
184
185 2
        $this->trigger(self::EVENT_ERROR, $event);
186 2
    }
187
188
    /**
189
     * This method is called when task executed timeout.
190
     * When overriding this method, make sure you call the parent implementation to ensure the
191
     * event is triggered.
192
     *
193
     * @throws \yii\base\InvalidConfigException
194
     */
195 1
    public function timeout(): void
196
    {
197 1
        $event = Yii::createObject(Event::class);
198
199 1
        $this->trigger(self::EVENT_TIMEOUT, $event);
200 1
    }
201
202
    /**
203
     * Wait until all tasks done.
204
     */
205 5
    public function wait(): void
206
    {
207 5
        $this->pool->wait();
208 5
    }
209
210
    /**
211
     * Set concurrency process do tasks.
212
     *
213
     * @param int $concurrency
214
     */
215
    public function setConcurrency(int $concurrency): void
216
    {
217
        $this->pool->concurrency($concurrency);
218
    }
219
220
    /**
221
     * Set timeout of task when execute.
222
     *
223
     * @param int $timeout
224
     */
225 6
    public function setTimeout(int $timeout): void
226
    {
227 6
        $this->pool->timeout($timeout);
228 6
    }
229
230
    /**
231
     * Set sleep time when wait tasks execute.
232
     *
233
     * @param int $sleepTimeWait
234
     */
235
    public function setSleepTimeWait(int $sleepTimeWait): void
236
    {
237
        $this->pool->sleepTime($sleepTimeWait);
238
    }
239
240
    /**
241
     * Set autoload for environment tasks execute.
242
     * @param string $autoload
243
     */
244
    public function setAutoload(string $autoload): void
245
    {
246
        $this->pool->autoload(Yii::getAlias($autoload));
0 ignored issues
show
Bug introduced by
It seems like \Yii::getAlias($autoload) targeting yii\BaseYii::getAlias() can also be of type boolean; however, Spatie\Async\Pool::autoload() does only seem to accept string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
247
    }
248
249
}
250