.github | ||
examples | ||
lib | ||
test | ||
.gitignore | ||
.php-cs-fixer.dist.php | ||
composer.json | ||
LICENSE | ||
phpunit.xml.dist | ||
psalm-baseline.xml | ||
psalm.xml | ||
README.md |
Loop
danog/loop
provides a set of powerful async loop APIs for executing operations periodically or on demand, in background loops a-la threads.
A more flexible and powerful alternative to AMPHP's repeat function, allowing dynamically changeable repeat periods and resumes.
Installation
composer require danog/loop
API
- Basic
- Advanced
All loop APIs are defined by a set of interfaces: however, to use them, you would usually have to extend only one of the abstract class implementations.
Loop
A basic loop, capable of running in background (asynchronously) the code contained in the loop
function.
API:
namespace danog\Loop;
abstract class Loop
{
abstract public function loop();
abstract public function __toString(): string;
public function start(): bool;
public function isRunning(): bool;
protected function startedLoop(): void;
protected function exitedLoop(): void;
}
loop()
The loop
async fiber will be run only once, every time the start
method is called.
__toString()
This method should return the loop's name.
It's useful for implementing the log methods.
start()
Asynchronously starts the loop
methods once in background.
Multiple calls to start
will be ignored, returning false
instead of true
.
isRunning()
You can use the isRunning
method to check if the loop is already running.
startedLoop()
Optionally, you can override this method to detect and log when the loop is started.
Make sure to always call the parent startedLoop()
method to avoid issues.
You can use directly $this
as loop name when logging, thanks to the custom __toString method.
exitedLoop()
Optionally, you can override this method to detect and log when the loop is ended.
Make sure to always call the parent exitedLoop()
method to avoid issues.
You can use directly $this
as loop name when logging, thanks to the custom __toString method.
ResumableLoop
A way more useful loop that exposes APIs to pause and resume the execution of the loop, both from outside of the loop, and in a cron-like manner from inside of the loop.
namespace danog\Loop;
abstract class ResumableLoop extends Loop
{
public function pause(?int $time = null): Future;
public function resume(): Future;
}
All methods from Loop, plus:
pause()
Pauses the loop for the specified number of milliseconds, or forever if null
is provided.
resume()
Forcefully resume the loop from the outside.
Returns a future that is resolved when the loop is paused again.
GenericLoop
If you want a simpler way to use the ResumableLoop
, you can use the GenericLoop.
namespace danog\Loop\Generic;
class GenericLoop extends ResumableLoop
{
/**
* Stop the loop.
*/
const STOP = -1;
/**
* Pause the loop.
*/
const PAUSE = null;
/**
* Rerun the loop.
*/
const CONTINUE = 0;
/**
* Constructor.
*
* @param callable $callable Callable to run
* @param string $name Loop name
*/
public function __construct(callable $callable, string $name);
/**
* Report pause, can be overriden for logging.
*
* @param integer $timeout Pause duration, 0 = forever
*
* @return void
*/
protected function reportPause(int $timeout): void;
/**
* Get loop name, provided to constructor.
*/
public function __toString(): string;
/**
* Stops loop.
*/
public function stop(): void;
}
The return value of the callable can be:
- A number - the loop will be paused for the specified number of seconds
GenericLoop::STOP
- The loop will stopGenericLoop::PAUSE
- The loop will pause forever (or until theresume
method is called on the loop object from outside the loop)GenericLoop::CONTINUE
- Return this if you want to rerun the loop without waiting
If the callable does not return anything, the loop will behave is if GenericLoop::PAUSE
was returned.
PeriodicLoop
If you simply want to execute an action every N seconds, PeriodicLoop is the way to go.
namespace danog\Loop\Generic;
class PeriodicLoop extends ResumableLoop
{
/**
* Constructor.
*
* @param callable $callback Callback to call
* @param string $name Loop name
* @param ?int $interval Loop interval
*/
public function __construct(callable $callback, string $name, ?int $interval);
/**
* Get name of the loop, passed to the constructor.
*
* @return string
*/
public function __toString(): string;
/**
* Stops loop.
*/
public function stop(): void;
}
PeriodicLoop
runs a callback at a periodic interval.
The loop can be stopped from the outside by using stop()
and from the inside by returning true
.