Skip to content

Commit dc17cab

Browse files
committed
Delay middleware
1 parent f62b150 commit dc17cab

File tree

3 files changed

+127
-0
lines changed

3 files changed

+127
-0
lines changed

src/DelayMiddleware.php

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace ApiClients\Middleware\Delay;
4+
5+
use ApiClients\Foundation\Middleware\MiddlewareInterface;
6+
use ApiClients\Foundation\Middleware\PostTrait;
7+
use ApiClients\Foundation\Middleware\Priority;
8+
use Psr\Http\Message\RequestInterface;
9+
use React\EventLoop\LoopInterface;
10+
use React\Promise\CancellablePromiseInterface;
11+
use function React\Promise\resolve;
12+
use function WyriHaximus\React\timedPromise;
13+
14+
final class DelayMiddleware implements MiddlewareInterface
15+
{
16+
use PostTrait;
17+
18+
/**
19+
* @var LoopInterface
20+
*/
21+
private $loop;
22+
23+
/**
24+
* DelayMiddleware constructor.
25+
* @param LoopInterface $loop
26+
*/
27+
public function __construct(LoopInterface $loop)
28+
{
29+
$this->loop = $loop;
30+
}
31+
32+
/**
33+
* @param RequestInterface $request
34+
* @param array $options
35+
* @return CancellablePromiseInterface
36+
*/
37+
public function pre(RequestInterface $request, array $options = []): CancellablePromiseInterface
38+
{
39+
if (!isset($options[self::class][Options::DELAY])) {
40+
return resolve($request);
41+
}
42+
43+
return timedPromise(
44+
$this->loop,
45+
$options[self::class][Options::DELAY],
46+
$request
47+
)->then(function (RequestInterface $request) {
48+
return resolve($request);
49+
});
50+
}
51+
52+
/**
53+
* @return int
54+
*/
55+
public function priority(): int
56+
{
57+
return Priority::FIRST - 1;
58+
}
59+
}

src/Options.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace ApiClients\Middleware\Delay;
4+
5+
final class Options
6+
{
7+
const DELAY = 'delay';
8+
}

tests/DelayMiddlewareTest.php

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
3+
namespace ApiClients\Tests\Middleware\Delay;
4+
5+
use ApiClients\Middleware\Delay\DelayMiddleware;
6+
use ApiClients\Middleware\Delay\Options;
7+
use ApiClients\Tools\TestUtilities\TestCase;
8+
use Prophecy\Argument;
9+
use Psr\Http\Message\RequestInterface;
10+
use React\EventLoop\Factory;
11+
use function Clue\React\Block\await;
12+
use function React\Promise\resolve;
13+
14+
final class DelayMiddlewareTest extends TestCase
15+
{
16+
public function testRequest()
17+
{
18+
$loop = Factory::create();
19+
20+
$request = $this->prophesize(RequestInterface::class);
21+
22+
$options = [
23+
DelayMiddleware::class => [
24+
Options::DELAY => 3,
25+
],
26+
];
27+
$middleware = new DelayMiddleware($loop);
28+
$preCalled = false;
29+
$middleware->pre($request->reveal(), $options)->then(function () use (&$preCalled) {
30+
$preCalled = true;
31+
});
32+
33+
self::assertFalse($preCalled);
34+
35+
$start = microtime(true);
36+
37+
$loop->run();
38+
39+
$stop = microtime(true);
40+
41+
self::assertNotSame($start + 3, $stop);
42+
self::assertTrue($start + 3 < $stop, $start + 3 . ' vs ' . $stop);
43+
44+
self::assertTrue($preCalled);
45+
}
46+
47+
public function testRequestNoDelay()
48+
{
49+
$request = $this->prophesize(RequestInterface::class);
50+
51+
$options = [];
52+
$middleware = new DelayMiddleware(Factory::create());
53+
$preCalled = false;
54+
$middleware->pre($request->reveal(), $options)->then(function () use (&$preCalled) {
55+
$preCalled = true;
56+
});
57+
58+
self::assertTrue($preCalled);
59+
}
60+
}

0 commit comments

Comments
 (0)