public function testStampedeProtection() { Coroutine\create(function () { $cache = new MemoryDriver(); file_put_contents(__DIR__ . "/stampede", 1); $factory = function () use(&$counter) { $count = (int) file_get_contents(__DIR__ . "/stampede"); file_put_contents(__DIR__ . "/stampede", ++$count); (yield $count); }; $cache->set("counter", $factory); $cache->set("counter", $factory); $cache->set("counter", $factory); $cache->get("counter"); $cache->get("counter"); // resolve the first "counter" value (yield $cache->get("counter")); // fetch the second "counter" value from the cache memory store $actual = (yield $cache->get("counter")); // first check to see that the count stored in the filesystem // is correct... Loop\timer(0.5, function () { $count = (int) file_get_contents(__DIR__ . "/stampede"); $this->assertEquals(2, $count); unlink(__DIR__ . "/stampede"); }); // then check to see that the count stored in the cache // is correct... $this->assertEqualsAfterDelay(2, $actual); })->done(); Loop\run(); }
<?php require "vendor/autoload.php"; use AsyncPHP\Icicle\Cache\Driver\MemoryDriver; use Icicle\Http\Client\Client; use Icicle\Http\Message\RequestInterface; use Icicle\Http\Message\Response; use Icicle\Http\Server\Server; use Icicle\Loop; use Icicle\Socket\SocketInterface; use Icicle\Stream\MemorySink; $cache = new MemoryDriver(); $server = new Server(function (RequestInterface $request, SocketInterface $socket) use($cache) { try { $cached = (yield $cache->get("foo")); if (!$cached) { $cached = (yield $cache->set("foo", function () { $client = new Client(); /** @var ResponseInterface $response */ $response = (yield $client->request("GET", "https://icicle.io/")); $data = ""; $stream = $response->getBody(); while ($stream->isReadable()) { $data .= (yield $stream->read()); } (yield $data); })); } $stream = new MemorySink(); (yield $stream->end($cached)); $response = new Response(200, ["content-type" => "text/html", "content-length" => $stream->getLength()], $stream);