Uložení Guzzle requestu do Nette cache
- pata.kusik111
- Člen | 78
Ahoj,
dělám nový pohled nad daty z jiného webu, takže si stáhnu HTML z URL a
to si rozparsuju.
Protože nechci zbytečně zatěžovat tu aplikaci, tak si všechny
„stabilní“ response ukládám do cache, ale zaboha nemohu přijít na to,
proč nemohu načítat z cache napříč requesty:
final class GoutteClientFactory
{
public static function create(IStorage $storage): GoutteClient
{
$stack = new HandlerStack();
$stack->setHandler(new CurlHandler());
$thisRequestCacheStrategy = new class(new class implements CacheStorageInterface
{
/** @var array */
private $storage = [];
public function fetch($key)
{
return $this->storage[$key] ?? null;
}
public function save(
$key, CacheEntry $data
): bool {
$this->storage[$key] = $data;
return true;
}
public function delete($key): bool
{
unset($this->storage[$key]);
return true;
}
}) implements CacheStrategyInterface
{
/** @var CacheStorageInterface */
private $cacheStorage;
public function __construct(CacheStorageInterface $cacheStorage)
{
$this->cacheStorage = $cacheStorage;
}
private static function key(RequestInterface $request): string
{
return sha1($request->getUri()->__toString());
}
public function fetch(RequestInterface $request): ?CacheEntry
{
Debugger::barDump([
'loading from memory',
self::key($request),
$this->cacheStorage->fetch(self::key($request))
]);
return $this->cacheStorage->fetch(self::key($request));
}
public function cache(RequestInterface $request, ResponseInterface $response): bool
{
Debugger::barDump(['saving to memory']);
return $this->cacheStorage->save(self::key($request),
new CacheEntry($request, $response, new DateTime()));
}
public function update(RequestInterface $request, ResponseInterface $response): bool
{
return $this->cacheStorage->save(self::key($request),
new CacheEntry($request, $response, new DateTime()));
}
public function delete(RequestInterface $request): bool
{
return $this->cacheStorage->delete(self::key($request));
}
};
$cache = new Cache($storage, 'webPage');
$netteCacheStrategy = new class($cache) implements CacheStrategyInterface
{
/** @var Cache */
private $cache;
public function __construct(Cache $cache)
{
$this->cache = $cache;
}
private static function key(RequestInterface $request): string
{
return sha1($request->getUri()->__toString());
}
public function fetch(RequestInterface $request): ?CacheEntry
{
Debugger::barDump([
'loading from nette',
self::key($request),
$this->cache->load(self::key($request))
]);
return $this->cache->load(self::key($request));
}
public function cache(RequestInterface $request, ResponseInterface $response): bool
{
Debugger::barDump(['saving to cache']);
$this->cache->save(self::key($request), new CacheEntry($request, $response, new DateTime()), [
Cache::EXPIRE => '20 minutes',
Cache::SLIDING => true,
]);
return true;
}
public function update(RequestInterface $request, ResponseInterface $response): bool
{
$this->cache->save(self::key($request), new CacheEntry($request, $response, new DateTime()), [
Cache::EXPIRE => '20 minutes',
Cache::SLIDING => true,
]);
return true;
}
public function delete(RequestInterface $request): bool
{
$this->cache->remove(self::key($request));
return true;
}
};
$strategy = new DelegatingCacheStrategy($netteCacheStrategy);
$strategy->registerRequestMatcher(new class implements RequestMatcherInterface
{
public function matches(RequestInterface $request): bool
{
return Strings::contains($request->getUri()->getPath(), 'VysledkySouteziPredbezne');
}
}, $thisRequestCacheStrategy);
$stack->push(new CacheMiddleware($strategy));
$panel = new Panel();
$stack->push(new Middleware($panel));
Debugger::getBar()->addPanel($panel);
return (new GoutteClient())->setClient(new Client(['handler' => $stack]));
}
}
- Jak to funguje teď
- všechny requesty na obsahující v URL „VysledkySouteziPredbezne“ se cachují pouze do paměti (tak abych v jednom běhu na mojí aplikaci se na tu URL dotazoval jenom jednou) – tady se data ale „rychle“ mění, tak to nehci cachovat napříč requesty
- vše ostatní se ukládá do nette pomocí
$netteCacheStrategy
- při druhém reqeustu na mojí aplikaci se data z
$netteCacheStrategy
pro URL nenačtou a já udělám nový request (vidím v Tracy panelu) - Jak to má fungovat
- při druhém reqeustu na mojí aplikaci se data z
$netteCacheStrategy
mají načíst a já nemám dělat request na aplikaci ze které data získávám. - Příklady z
barDump
/Tracy panelu - První request (26 dotazů jde na API skrz)
0 => "loading from nette"
1 => "bbda9713296440f71bcfddbe4a898ec30fe785e6"
2 => null
0 => "saving to cache"
0 => "loading from nette"
1 => "95f6b79a9f71631de6319a6427d337b8027c8773"
2 => null
0 => "saving to cache"
0 => "loading from nette"
1 => "92a27f114ba4b336b6ef2a153050f9815cbee820"
2 => null
atd.
Druhý request (opět 26 dotazů ale mělo by být 0):
0 => "loading from nette"
1 => "bbda9713296440f71bcfddbe4a898ec30fe785e6"
2 => CacheEntry
0 => "saving to cache"
0 => "loading from nette"
1 => "95f6b79a9f71631de6319a6427d337b8027c8773"
2 => CacheEntry
0 => "saving to cache"
0 => "loading from nette"
1 => "92a27f114ba4b336b6ef2a153050f9815cbee820"
2 => CacheEntry
atd.
Tady by se nemělo ani být "saving to cache"
…
Podotýkám, že $thisRequestCacheStrategy
funguje OK.
Vidíte někdo, v čem je problém?
- Jan Tvrdík
- Nette guru | 2595
Potřebuješ pomoc s nastavením xdebugu? Nebo vysvětlit, jak se pomocí xdebugu podobné problémy diagnostikují?