2020-07-21 18:06:19 +02:00
|
|
|
<?php
|
|
|
|
/**
|
|
|
|
* Periodic loop.
|
|
|
|
*
|
|
|
|
* @author Daniil Gentili <daniil@daniil.it>
|
|
|
|
* @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
|
|
|
|
* @license https://opensource.org/licenses/MIT MIT
|
|
|
|
*/
|
|
|
|
|
|
|
|
namespace danog\Loop\Generic;
|
|
|
|
|
2020-07-21 22:20:03 +02:00
|
|
|
use Amp\Promise;
|
2020-07-21 21:45:22 +02:00
|
|
|
use danog\Loop\ResumableSignalLoop;
|
2020-07-21 18:06:19 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Periodic loop.
|
|
|
|
*
|
|
|
|
* Runs a callback at a periodic interval.
|
|
|
|
*
|
|
|
|
* The loop can be stopped from the outside or
|
|
|
|
* from the inside by signaling or returning `true`.
|
|
|
|
*
|
2020-07-23 13:26:16 +02:00
|
|
|
* @template T as bool
|
|
|
|
* @template TGenerator as \Generator<mixed,Promise|array<array-key,Promise>,mixed,Promise<T>|T>
|
|
|
|
* @template TPromise as Promise<T>
|
|
|
|
*
|
|
|
|
* @template TCallable as T|TPromise|TGenerator
|
|
|
|
*
|
2020-07-21 18:06:19 +02:00
|
|
|
* @author Daniil Gentili <daniil@daniil.it>
|
|
|
|
*/
|
|
|
|
class PeriodicLoop extends ResumableSignalLoop
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* Callback.
|
|
|
|
*
|
|
|
|
* @var callable
|
2020-07-23 13:26:16 +02:00
|
|
|
*
|
|
|
|
* @psalm-var callable():TCallable
|
2020-07-21 18:06:19 +02:00
|
|
|
*/
|
|
|
|
private $callback;
|
|
|
|
/**
|
|
|
|
* Loop name.
|
|
|
|
*
|
|
|
|
* @var string
|
|
|
|
*/
|
2020-07-22 17:46:05 +02:00
|
|
|
private $name;
|
2020-07-21 18:06:19 +02:00
|
|
|
/**
|
|
|
|
* Loop interval.
|
|
|
|
*
|
2020-07-22 18:18:57 +02:00
|
|
|
* @var ?int
|
2020-07-21 18:06:19 +02:00
|
|
|
*/
|
|
|
|
private $interval;
|
|
|
|
/**
|
|
|
|
* Constructor.
|
|
|
|
*
|
2020-07-22 18:18:57 +02:00
|
|
|
* @param callable $callback Callback to call
|
|
|
|
* @param string $name Loop name
|
|
|
|
* @param ?int $interval Loop interval
|
2020-07-23 13:26:16 +02:00
|
|
|
*
|
|
|
|
* @psalm-param callable():TCallable $callback Callable to run
|
2020-07-21 18:06:19 +02:00
|
|
|
*/
|
2020-07-22 18:18:57 +02:00
|
|
|
public function __construct(callable $callback, string $name, ?int $interval)
|
2020-07-21 18:06:19 +02:00
|
|
|
{
|
|
|
|
$this->callback = $callback;
|
|
|
|
$this->name = $name;
|
|
|
|
$this->interval = $interval;
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
* Loop implementation.
|
|
|
|
*
|
|
|
|
* @return \Generator
|
|
|
|
*/
|
|
|
|
public function loop(): \Generator
|
|
|
|
{
|
|
|
|
$callback = $this->callback;
|
|
|
|
while (true) {
|
2020-07-21 22:20:03 +02:00
|
|
|
/** @psalm-suppress MixedAssignment */
|
|
|
|
$result = $callback();
|
|
|
|
if ($result instanceof \Generator) {
|
2020-07-23 13:26:16 +02:00
|
|
|
/** @psalm-var TGenerator */
|
|
|
|
$result = yield from $result;
|
2020-07-21 22:20:03 +02:00
|
|
|
} elseif ($result instanceof Promise) {
|
2020-07-23 13:26:16 +02:00
|
|
|
/** @psalm-var TPromise */
|
|
|
|
$result = yield $result;
|
|
|
|
}
|
|
|
|
if ($result === true) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/** @psalm-suppress MixedAssignment */
|
|
|
|
$result = yield $this->waitSignal($this->pause($this->interval));
|
|
|
|
if ($result === true) {
|
|
|
|
return;
|
2020-07-21 22:20:03 +02:00
|
|
|
}
|
2020-07-21 18:06:19 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
* Get name of the loop.
|
|
|
|
*
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
public function __toString(): string
|
|
|
|
{
|
|
|
|
return $this->name;
|
|
|
|
}
|
|
|
|
}
|