Simplified codebase in a major refactor before moving to initial Toalett release
This commit is contained in:
@@ -1,17 +0,0 @@
|
||||
<?php
|
||||
|
||||
use JoopSchilder\React\Stream\NonBlockingInput\ReadableNonBlockingInputStream;
|
||||
use React\EventLoop\Factory;
|
||||
|
||||
require_once __DIR__ . '/../vendor/autoload.php';
|
||||
require_once __DIR__ . '/demo_classes.php';
|
||||
|
||||
$input = new DemoNonBlockingInput();
|
||||
|
||||
$loop = Factory::create();
|
||||
$stream = new ReadableNonBlockingInputStream($input, $loop);
|
||||
$stream->on('data', fn() => print('m'));
|
||||
$stream->on('error', fn() => print('e'));
|
||||
$stream->on('close', fn() => print('c'));
|
||||
$loop->addPeriodicTimer(0.2, fn() => print('.'));
|
||||
$loop->run();
|
||||
99
examples/classes.php
Normal file
99
examples/classes.php
Normal file
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
use Toalett\React\Stream\EndlessTrait;
|
||||
use Toalett\React\Stream\Source;
|
||||
|
||||
final class WillThrowExceptionAfter4Seconds implements Source
|
||||
{
|
||||
use EndlessTrait;
|
||||
|
||||
private const EMISSION_INTERVAL = 1.0;
|
||||
private const SECONDS_BEFORE_EMITTING_ERROR = 4.0;
|
||||
private float $lastEmission = 0;
|
||||
private float $openedAt = 0;
|
||||
|
||||
public function open(): void
|
||||
{
|
||||
$this->openedAt = microtime(true);
|
||||
}
|
||||
|
||||
public function select(): ?float
|
||||
{
|
||||
$now = microtime(true);
|
||||
if ($now - $this->openedAt > self::SECONDS_BEFORE_EMITTING_ERROR) {
|
||||
throw new RuntimeException('An error has occured!');
|
||||
}
|
||||
if ($now - $this->lastEmission > self::EMISSION_INTERVAL) {
|
||||
$this->lastEmission = $now;
|
||||
return $now;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
final class Joker implements Source
|
||||
{
|
||||
use EndlessTrait;
|
||||
|
||||
private float $deadline = 0;
|
||||
private array $jokes = [
|
||||
'What did the Buddhist ask the hot dog vendor? - Make me one with everything.',
|
||||
'You know why you never see elephants hiding up in trees? - Because they’re really good at it.',
|
||||
'What is red and smells like blue paint? - Red paint.',
|
||||
'A dyslexic man walks into a bra.',
|
||||
'Where does the General keep his armies? - In his sleevies!',
|
||||
'What do you call bears with no ears? - B',
|
||||
'Why dont blind people skydive? - Because it scares the crap out of their dogs.',
|
||||
];
|
||||
|
||||
public function open(): void
|
||||
{
|
||||
$this->scheduleNextJoke();
|
||||
}
|
||||
|
||||
public function select(): ?string
|
||||
{
|
||||
if (microtime(true) < $this->deadline) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$this->scheduleNextJoke();
|
||||
return $this->jokes[array_rand($this->jokes)];
|
||||
}
|
||||
|
||||
private function scheduleNextJoke(): void
|
||||
{
|
||||
$delay = mt_rand() / mt_getrandmax(); // somewhere between 0 - 1
|
||||
$this->deadline = microtime(true) + (5.0 * $delay);
|
||||
}
|
||||
}
|
||||
|
||||
final class ReachesEofIn5Iterations implements Source
|
||||
{
|
||||
private array $buffer = [
|
||||
'line 1',
|
||||
'line 2',
|
||||
'line 3',
|
||||
'line 4',
|
||||
'line 5',
|
||||
];
|
||||
|
||||
public function open(): void
|
||||
{
|
||||
}
|
||||
|
||||
public function select(): ?string
|
||||
{
|
||||
return array_shift($this->buffer);
|
||||
}
|
||||
|
||||
public function close(): void
|
||||
{
|
||||
}
|
||||
|
||||
public function eof(): bool
|
||||
{
|
||||
return count($this->buffer) === 0;
|
||||
}
|
||||
}
|
||||
@@ -1,124 +0,0 @@
|
||||
<?php
|
||||
|
||||
use JoopSchilder\React\Stream\NonBlockingInput\NonBlockingInputInterface;
|
||||
|
||||
/**
|
||||
* Class DemoNonBlockingInput
|
||||
* Provides an implementation of a non-blocking input that generates
|
||||
* some data every second. After a lifetime of 4 seconds, an exception
|
||||
* is thrown to show how the stream handles exceptions from the input.
|
||||
*/
|
||||
final class DemoNonBlockingInput implements NonBlockingInputInterface
|
||||
{
|
||||
private const DATA_AVAILABLE_INTERVAL_S = 1.0;
|
||||
private const ERROR_AFTER_S = 4.0;
|
||||
|
||||
private float $lastEmission = 0;
|
||||
|
||||
private float $initialEmission = 0;
|
||||
|
||||
|
||||
public function open(): void
|
||||
{
|
||||
$this->initialEmission = microtime(true);
|
||||
}
|
||||
|
||||
|
||||
public function select(): ?object
|
||||
{
|
||||
$now = microtime(true);
|
||||
if ($now - $this->initialEmission > self::ERROR_AFTER_S) {
|
||||
throw new Exception('Oh no!');
|
||||
}
|
||||
if ($now - $this->lastEmission > self::DATA_AVAILABLE_INTERVAL_S) {
|
||||
$this->lastEmission = $now;
|
||||
|
||||
return new stdClass();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public function close(): void
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Class Joke
|
||||
* Used as a payload for the DemoJokeGenerator.
|
||||
* @see DemoJokeGenerator
|
||||
*/
|
||||
final class Joke
|
||||
{
|
||||
private string $joke;
|
||||
|
||||
|
||||
public function __construct(string $joke)
|
||||
{
|
||||
$this->joke = $joke;
|
||||
}
|
||||
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return $this->joke;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Class DemoJokeGenerator
|
||||
* Generates a random joke at a random interval (0 - 2 seconds).
|
||||
*/
|
||||
final class DemoJokeGenerator implements NonBlockingInputInterface
|
||||
{
|
||||
private float $lastEmission = 0;
|
||||
|
||||
private float $deadline = 0;
|
||||
|
||||
private array $jokes = [
|
||||
'What did the Buddhist ask the hot dog vendor? - Make me one with everything.',
|
||||
'You know why you never see elephants hiding up in trees? - Because they’re really good at it.',
|
||||
'What is red and smells like blue paint? - Red paint.',
|
||||
'A dyslexic man walks into a bra.',
|
||||
'Where does the General keep his armies? - In his sleevies!',
|
||||
'What do you call bears with no ears? - B',
|
||||
'Why dont blind people skydive? - Because it scares the crap out of their dogs.',
|
||||
];
|
||||
|
||||
|
||||
private function scheduleNextJoke()
|
||||
{
|
||||
$this->lastEmission = microtime(true);
|
||||
$delay = mt_rand() / mt_getrandmax();
|
||||
$this->deadline = $this->lastEmission + (2.0 * $delay);
|
||||
}
|
||||
|
||||
|
||||
public function open(): void
|
||||
{
|
||||
$this->scheduleNextJoke();
|
||||
}
|
||||
|
||||
|
||||
public function select(): ?object
|
||||
{
|
||||
$now = microtime(true);
|
||||
if ($now > $this->deadline) {
|
||||
$this->scheduleNextJoke();
|
||||
|
||||
return new Joke($this->jokes[array_rand($this->jokes)]);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public function close(): void
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
29
examples/eof_in_5_iterations.php
Normal file
29
examples/eof_in_5_iterations.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
use React\EventLoop\Factory;
|
||||
use Toalett\React\Stream\StreamAdapter;
|
||||
|
||||
require_once __DIR__ . '/../vendor/autoload.php';
|
||||
require_once __DIR__ . '/classes.php';
|
||||
|
||||
$loop = Factory::create();
|
||||
|
||||
$stream = new StreamAdapter(new ReachesEofIn5Iterations(), $loop, 0.1);
|
||||
$stream->on('data', fn(string $s) => printf('Data received: %s.%s', $s, PHP_EOL));
|
||||
$stream->on('end', fn() => print('Stream reached eof.' . PHP_EOL));
|
||||
$stream->on('close', fn() => print('Stream closed.' . PHP_EOL));
|
||||
|
||||
print(<<<EOF
|
||||
This program demonstrates an example of a source that reaches EOF after 5 lines.
|
||||
|
||||
The stream adapter reads eagerly from the source: data is emitted as long as
|
||||
select() on the source returns a non-null value. This means that all lines from
|
||||
the source in this example ar read at once. If you want the adapter to read
|
||||
at most one unit (message) from the source, you should probably be using a
|
||||
periodic timer directly, or use time mechanics as used by the other examples.
|
||||
|
||||
|
||||
EOF
|
||||
);
|
||||
|
||||
$loop->run();
|
||||
25
examples/exception_after_4_seconds.php
Normal file
25
examples/exception_after_4_seconds.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
use React\EventLoop\Factory;
|
||||
use Toalett\React\Stream\StreamAdapter;
|
||||
|
||||
require_once __DIR__ . '/../vendor/autoload.php';
|
||||
require_once __DIR__ . '/classes.php';
|
||||
|
||||
$loop = Factory::create();
|
||||
$loop->addPeriodicTimer(0.2, fn() => print('.'));
|
||||
|
||||
$stream = new StreamAdapter(new WillThrowExceptionAfter4Seconds(), $loop);
|
||||
$stream->on('data', fn() => print('Data received.' . PHP_EOL));
|
||||
$stream->on('error', fn(Throwable $t) => print('Error: ' . $t->getMessage() . PHP_EOL));
|
||||
$stream->on('close', fn() => print('Stream closed.' . PHP_EOL));
|
||||
|
||||
print(<<<EOF
|
||||
This program demonstrates an example of a source that fails after 4 seconds.
|
||||
Press CTRL+C to stop.
|
||||
|
||||
|
||||
EOF
|
||||
);
|
||||
|
||||
$loop->run();
|
||||
23
examples/infinite_stream_of_jokes.php
Normal file
23
examples/infinite_stream_of_jokes.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
use React\EventLoop\Factory;
|
||||
use Toalett\React\Stream\StreamAdapter;
|
||||
|
||||
require_once __DIR__ . '/../vendor/autoload.php';
|
||||
require_once __DIR__ . '/classes.php';
|
||||
|
||||
$loop = Factory::create();
|
||||
|
||||
$stream = new StreamAdapter(new Joker(), $loop);
|
||||
$stream->on('data', fn(string $joke) => print($joke . PHP_EOL));
|
||||
|
||||
print(<<<EOF
|
||||
This program demonstrates an example of an endless source.
|
||||
The stream presents a joke at random intervals (0.0 - 5.0 seconds).
|
||||
Press CTRL+C to stop.
|
||||
|
||||
|
||||
EOF
|
||||
);
|
||||
|
||||
$loop->run();
|
||||
@@ -1,16 +0,0 @@
|
||||
<?php
|
||||
|
||||
use JoopSchilder\React\Stream\NonBlockingInput\ReadableNonBlockingInputStream;
|
||||
use React\EventLoop\Factory;
|
||||
|
||||
require_once __DIR__ . '/../vendor/autoload.php';
|
||||
require_once __DIR__ . '/demo_classes.php';
|
||||
|
||||
$input = new DemoJokeGenerator();
|
||||
|
||||
$loop = Factory::create();
|
||||
$stream = new ReadableNonBlockingInputStream($input, $loop);
|
||||
$stream->on('data', fn(Joke $joke) => print($joke . PHP_EOL));
|
||||
$loop->addPeriodicTimer(0.2, fn() => print('.' . PHP_EOL));
|
||||
$loop->run();
|
||||
|
||||
Reference in New Issue
Block a user