Completed
Push — master ( 3ee744...093cf6 )
by Vuong
06:33
created

Async::timeout()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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