Completed
Push — master ( e48e3f...5ab19a )
by Vuong
01:30
created

Async::await()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 3
cp 0
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 2
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 Throwable;
12
13
use yii\base\Component;
14
15
use Spatie\Async\Pool;
16
17
/**
18
 * Support run code async. To use it, you just config it to your application components in configure file:
19
 *
20
 * ```php
21
 * 'components' => [
22
 *      'async' => 'vxm\async\Async'
23
 * ]
24
 *
25
 * ```
26
 *
27
 * And after that you can run an async code:
28
 *
29
 * ```php
30
 *
31
 * Yii::$app->async(function () {
32
 *
33
 *      sleep(15);
34
 * });
35
 *
36
 * ```
37
 *
38
 * If you want to wait until task done, you just to call [[wait]].
39
 *
40
 * ```php
41
 *
42
 * Yii::$app->async(function () {
43
 *
44
 *      sleep(15);
45
 * })->wait();
46
 *
47
 * ```
48
 *
49
 * Run multi tasks:
50
 *
51
 * ```php
52
 *
53
 * Yii::$app->async(function () {
54
 *
55
 *      sleep(15);
56
 * });
57
 *
58
 * Yii::$app->async(function () {
59
 *
60
 *      sleep(15);
61
 * });
62
 *
63
 * Yii::$app->async->await(); // sleep 30s
64
 * ```
65
 *
66
 * @property string $autoload path of autoload file for runtime task execute environment.
67
 * @property int $sleepTimeWait time to sleep on wait tasks execute.
68
 * @property int $concurrency tasks executable.
69
 * @property int $timeout of task executable.
70
 *
71
 * @author Vuong Minh <[email protected]>
72
 * @since 1.0.0
73
 */
74
class Async extends Component
75
{
76
77
    /**
78
     * @event SuccessEvent an event that is triggered when task done.
79
     */
80
    const EVENT_SUCCESS = 'success';
81
82
    /**
83
     * @event ErrorEvent an event that is triggered when task error.
84
     */
85
    const EVENT_ERROR = 'error';
86
87
    /**
88
     * @event \yii\base\Event an event that is triggered when task timeout.
89
     */
90
    const EVENT_TIMEOUT = 'timeout';
91
92
    /**
93
     * @var Pool handling tasks.
94
     */
95
    protected $pool;
96
97
    /**
98
     * Async constructor.
99
     *
100
     * @param array $config
101
     * @throws \yii\base\InvalidConfigException
102
     */
103
    public function __construct($config = [])
104
    {
105
        $pool = $this->pool = Yii::createObject(Pool::class);
106
        $pool->autoload(__DIR__ . '/RuntimeAutoload.php');
107
108
        parent::__construct($config);
109
    }
110
111
    /**
112
     * Add task to the pool.
113
     *
114
     * @param callable|\Spatie\Async\Task|Task $callable need to execute.
115
     * @param array $callbacks event. Have key is an event name, value is a callable triggered when event happen,
116
     * have three events `error`, `success`, `timeout`.
117
     * @return static
118
     * @throws \yii\base\InvalidConfigException
119
     */
120
    public function addTask($callable, array $callbacks = []): self
121
    {
122
        $task = Yii::createObject([
123
            'class' => ChildRuntimeTask::class,
124
            'app' => Yii::$app,
125
            'callable' => $callable
126
        ]);
127
        $process = $this
128
            ->pool
129
            ->add($task)
130
            ->then([$this, 'success'])
131
            ->catch([$this, 'error'])
132
            ->timeout([$this, 'timeout']);
133
134
        foreach ($callbacks as $name => $callback) {
135
136
            switch (strtolower($name)) {
137
                case 'timeout':
138
                    $process->timeout($callback);
139
                    break;
140
                case 'success':
141
                    $process->then($callback);
142
                    break;
143
                case 'error':
144
                case 'catch':
145
                    $process->catch($callback);
146
                    break;
147
                default:
148
                    break;
149
            }
150
151
        }
152
153
        return $this;
154
    }
155
156
    /**
157
     * This method is called when task executed success.
158
     * When overriding this method, make sure you call the parent implementation to ensure the
159
     * event is triggered.
160
     *
161
     * @param mixed $output of task executed.
162
     * @throws \yii\base\InvalidConfigException
163
     */
164
    public function success($output): void
165
    {
166
        $event = Yii::createObject([
167
            'class' => SuccessEvent::class,
168
            'output' => $output
169
        ]);
170
171
        $this->trigger(self::EVENT_SUCCESS, $event);
172
    }
173
174
    /**
175
     * This method is called when task executed error.
176
     * When overriding this method, make sure you call the parent implementation to ensure the
177
     * event is triggered.
178
     *
179
     * @param Throwable $throwable when executing task.
180
     * @throws \yii\base\InvalidConfigException
181
     */
182
    public function error(Throwable $throwable): void
183
    {
184
        $event = Yii::createObject([
185
            'class' => ErrorEvent::class,
186
            'throwable' => $throwable
187
        ]);
188
189
        $this->trigger(self::EVENT_ERROR, $event);
190
    }
191
192
    /**
193
     * This method is called when task executed timeout.
194
     * When overriding this method, make sure you call the parent implementation to ensure the
195
     * event is triggered.
196
     *
197
     * @throws \yii\base\InvalidConfigException
198
     */
199
    public function timeout(): void
200
    {
201
        $event = Yii::createObject(Event::class);
202
203
        $this->trigger(self::EVENT_TIMEOUT, $event);
204
    }
205
206
    /**
207
     * An alias of [[addTask()]].
208
     *
209
     * @param callable $callable task
210
     * @param array $callbacks
211
     * @return static
212
     * @see addTask
213
     * @throws \yii\base\InvalidConfigException
214
     */
215
    public function __invoke($callable, array $callbacks = [])
216
    {
217
        return $this->addTask($callable, $callbacks);
218
    }
219
220
    /**
221
     * Wait until all tasks done.
222
     */
223
    public function await(): void
224
    {
225
        $this->pool->wait();
226
    }
227
228
    /**
229
     * Set concurrency process do tasks.
230
     *
231
     * @param int $concurrency
232
     */
233
    public function setConcurrency(int $concurrency): void
234
    {
235
        $this->pool->concurrency($concurrency);
236
    }
237
238
    /**
239
     * Set timeout of task when execute.
240
     *
241
     * @param int $timeout
242
     */
243
    public function setTimeout(int $timeout): void
244
    {
245
        $this->pool->timeout($timeout);
246
    }
247
248
    /**
249
     * Set sleep time when wait tasks execute.
250
     *
251
     * @param int $sleepTimeWait
252
     */
253
    public function setSleepTimeWait(int $sleepTimeWait): void
254
    {
255
        $this->pool->sleepTime($sleepTimeWait);
256
    }
257
258
    /**
259
     * Set autoload for environment tasks execute.
260
     * @param string $autoload
261
     */
262
    public function setAutoload(string $autoload): void
263
    {
264
        $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...
265
    }
266
267
}
268