Skip to content

Commit f8630c6

Browse files
feat: cache & requestTimeout
1 parent e9cd0df commit f8630c6

4 files changed

Lines changed: 287 additions & 18 deletions

File tree

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
vendor
1+
vendor
2+
index.php
3+
web/cache/*

composer.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
{
22
"name": "syntaxphoenix/bgpview-php",
3-
"version": "0.0.1",
3+
"version": "0.0.2",
44
"type": "framework",
55
"autoload": {
66
"psr-4": {
77
"SyntaxPhoenix\\Api\\BGPView\\" : "src/"
88
}
99
},
1010
"require": {
11-
"guzzlehttp/guzzle": "7.0"
11+
"guzzlehttp/guzzle": "7.0",
12+
"nette/caching": "^3.1"
1213
}
1314
}

composer.lock

Lines changed: 224 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/BGPView.php

Lines changed: 57 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,69 +3,112 @@
33
namespace SyntaxPhoenix\Api\BGPView;
44

55
use GuzzleHttp\Client;
6-
use Psr\Http\Message\ResponseInterface;
6+
use Nette\Caching\Cache;
7+
use Nette\Caching\Storage;
8+
use Nette\Caching\Storages\FileStorage;
79
use SyntaxPhoenix\Api\BGPView\Exceptions\RequestFailedException;
810

911
class BGPView
1012
{
1113

1214
private string $baseUrl;
15+
private bool $caching;
1316
private Client $client;
17+
private Storage $storage;
18+
private Cache $cache;
19+
private string $cacheTime;
20+
private float $lastRequestTimestamp = 0;
21+
private float $requestTimeout;
1422

15-
public function __construct(string $baseUrl) {
23+
public function __construct(string $baseUrl, float $requestTimeout = 0.4, bool $caching = false, ?string $cachingUrl = 'web/cache/bgpview', ?string $cacheTime = '10 minutes') {
24+
if ($caching) {
25+
$this->createPath($cachingUrl);
26+
$this->storage = new FileStorage($cachingUrl);
27+
$this->cache = new Cache($this->storage, 'bgpview-requests');
28+
}
1629
$this->baseUrl = $baseUrl;
30+
$this->caching = $caching;
31+
$this->cacheTime = $cacheTime;
32+
$this->requestTimeout = $requestTimeout;
1733
$this->client = new Client([
18-
'base_uri' => $baseUrl,
19-
'timeout' => 2.0,
34+
'base_uri' => $baseUrl
2035
]);
2136
}
2237

2338
public function getAsnDetails(int $asNumber): array
2439
{
25-
return json_decode($this->getDataByApi('asn/' . $asNumber)->getBody(), true)['data'];
40+
return $this->getDataByApi('asn/' . $asNumber)['data'];
2641
}
2742

2843
public function getAsnPrefixes(int $asNumber): array
2944
{
30-
return json_decode($this->getDataByApi('asn/' . $asNumber . '/prefixes')->getBody(), true)['data'];
45+
return $this->getDataByApi('asn/' . $asNumber . '/prefixes')['data'];
3146
}
3247

3348
public function getAsnPeers(int $asNumber): array
3449
{
35-
return json_decode($this->getDataByApi('asn/' . $asNumber . '/peers')->getBody(), true)['data'];
50+
return $this->getDataByApi('asn/' . $asNumber . '/peers')['data'];
3651
}
3752

3853
public function getAsnUpstreams(int $asNumber): array
3954
{
40-
return json_decode($this->getDataByApi('asn/' . $asNumber . '/upstreams')->getBody(), true)['data'];
55+
return $this->getDataByApi('asn/' . $asNumber . '/upstreams')['data'];
4156
}
4257

4358
public function getAsnDownstreams(int $asNumber): array
4459
{
45-
return json_decode($this->getDataByApi('asn/' . $asNumber . '/downstreams')->getBody(), true)['data'];
60+
return $this->getDataByApi('asn/' . $asNumber . '/downstreams')['data'];
4661
}
4762

4863
public function getPrefix(string $ipAddress, int $cidr): array
4964
{
50-
return json_decode($this->getDataByApi('prefix/' . $ipAddress . '/' . $cidr)->getBody(), true)['data'];
65+
return $this->getDataByApi('prefix/' . $ipAddress . '/' . $cidr)['data'];
5166
}
5267

5368
public function getIPDetails(string $ipAddress): array
5469
{
55-
return json_decode($this->getDataByApi('prefix/ip/' . $ipAddress)->getBody(), true)['data'];
70+
return $this->getDataByApi('ip/' . $ipAddress)['data'];
5671
}
5772

5873
public function getIXDetails(int $ixId): array
5974
{
60-
return json_decode($this->getDataByApi('ix/' . $ixId)->getBody(), true)['data'];
75+
return $this->getDataByApi('ix/' . $ixId)['data'];
6176
}
6277

63-
private function getDataByApi(string $urlPart): ResponseInterface
78+
private function getDataByApi(string $urlPart): array
6479
{
80+
if ($this->caching) {
81+
$response = $this->cache->load($urlPart);
82+
if ($response) {
83+
return $response;
84+
}
85+
}
86+
$time = microtime(true);
87+
if (($this->lastRequestTimestamp + $this->requestTimeout) > $time) {
88+
$restTime = $this->requestTimeout - ($time - $this->lastRequestTimestamp);
89+
usleep($restTime * 1000 * 1000);
90+
}
6591
$response = $this->client->request('GET', $urlPart);
6692
if ($response->getStatusCode() != 200) {
6793
throw new RequestFailedException();
6894
}
69-
return $response;
95+
$finalResponse = json_decode($response->getBody(), true);
96+
if ($this->caching) {
97+
$this->cache->save($urlPart, $finalResponse, [
98+
Cache::EXPIRE => $this->cacheTime ?? '10 minutes',
99+
]);
100+
}
101+
$this->lastRequestTimestamp = microtime(true);
102+
103+
return $finalResponse;
104+
}
105+
106+
private function createPath($path) {
107+
if (is_dir($path)) {
108+
return true;
109+
}
110+
$prev_path = substr($path, 0, strrpos($path, '/', -2) + 1 );
111+
$return = $this->createPath($prev_path);
112+
return ($return && is_writable($prev_path)) ? mkdir($path) : false;
70113
}
71114
}

0 commit comments

Comments
 (0)