|
2 | 2 |
|
3 | 3 | namespace MikeFrancis\LaravelUnleash;
|
4 | 4 |
|
5 |
| -use function GuzzleHttp\json_decode; |
6 |
| - |
7 | 5 | use GuzzleHttp\ClientInterface;
|
| 6 | +use GuzzleHttp\Exception\InvalidArgumentException; |
| 7 | +use GuzzleHttp\Exception\TransferException; |
8 | 8 | use Illuminate\Contracts\Cache\Repository as Cache;
|
9 | 9 | use Illuminate\Contracts\Config\Repository as Config;
|
10 | 10 | use Illuminate\Http\Request;
|
11 | 11 | use Illuminate\Support\Arr;
|
12 | 12 | use MikeFrancis\LaravelUnleash\Strategies\Contracts\DynamicStrategy;
|
13 | 13 | use MikeFrancis\LaravelUnleash\Strategies\Contracts\Strategy;
|
| 14 | +use Symfony\Component\HttpFoundation\Exception\JsonException; |
| 15 | +use function GuzzleHttp\json_decode; |
14 | 16 |
|
15 | 17 | class Unleash
|
16 | 18 | {
|
17 |
| - protected $client; |
| 19 | + const DEFAULT_CACHE_TTL = 15; |
18 | 20 |
|
| 21 | + protected $client; |
19 | 22 | protected $cache;
|
20 |
| - |
21 | 23 | protected $config;
|
22 |
| - |
23 | 24 | protected $request;
|
24 |
| - |
25 |
| - protected $features = []; |
| 25 | + protected $features; |
26 | 26 |
|
27 | 27 | public function __construct(ClientInterface $client, Cache $cache, Config $config, Request $request)
|
28 | 28 | {
|
29 | 29 | $this->client = $client;
|
30 | 30 | $this->cache = $cache;
|
31 | 31 | $this->config = $config;
|
32 | 32 | $this->request = $request;
|
33 |
| - |
34 |
| - if (!$this->config->get('unleash.isEnabled')) { |
35 |
| - return; |
36 |
| - } |
37 |
| - |
38 |
| - if ($this->config->get('unleash.cache.isEnabled')) { |
39 |
| - $this->features = $this->cache->remember( |
40 |
| - 'unleash', |
41 |
| - $this->config->get('unleash.cache.ttl'), |
42 |
| - function () { |
43 |
| - return $this->fetchFeatures(); |
44 |
| - } |
45 |
| - ); |
46 |
| - } else { |
47 |
| - $this->features = $this->fetchFeatures(); |
48 |
| - } |
49 | 33 | }
|
50 | 34 |
|
51 | 35 | public function getFeatures(): array
|
52 | 36 | {
|
53 |
| - return $this->features; |
| 37 | + try { |
| 38 | + $features = $this->getCachedFeatures(); |
| 39 | + |
| 40 | + // Always store the failover cache, in case it is turned on during failure scenarios. |
| 41 | + $this->cache->forever('unleash.features.failover', $features); |
| 42 | + |
| 43 | + return $features; |
| 44 | + } catch (TransferException | JsonException $e) { |
| 45 | + if ($this->config->get('unleash.cache.failover') === true) { |
| 46 | + return $this->cache->get('unleash.features.failover', []); |
| 47 | + } |
| 48 | + } |
| 49 | + |
| 50 | + return []; |
54 | 51 | }
|
55 | 52 |
|
56 | 53 | public function getFeature(string $name)
|
@@ -109,16 +106,36 @@ public function isFeatureDisabled(string $name, ...$args): bool
|
109 | 106 | return !$this->isFeatureEnabled($name, ...$args);
|
110 | 107 | }
|
111 | 108 |
|
| 109 | + protected function getCachedFeatures(): array |
| 110 | + { |
| 111 | + if (!$this->config->get('unleash.isEnabled')) { |
| 112 | + return []; |
| 113 | + } |
| 114 | + |
| 115 | + if ($this->config->get('unleash.cache.isEnabled')) { |
| 116 | + return $this->cache->remember( |
| 117 | + 'unleash', |
| 118 | + $this->config->get('unleash.cache.ttl', self::DEFAULT_CACHE_TTL), |
| 119 | + function () { |
| 120 | + return $this->fetchFeatures(); |
| 121 | + } |
| 122 | + ); |
| 123 | + } |
| 124 | + |
| 125 | + return $this->features ?? $this->features = $this->fetchFeatures(); |
| 126 | + } |
| 127 | + |
112 | 128 | protected function fetchFeatures(): array
|
113 | 129 | {
|
114 |
| - try { |
115 |
| - $response = $this->client->get($this->getFeaturesApiUrl(), $this->getRequestOptions()); |
116 |
| - $data = json_decode((string) $response->getBody(), true); |
| 130 | + $response = $this->client->get($this->getFeaturesApiUrl(), $this->getRequestOptions()); |
117 | 131 |
|
118 |
| - return $this->formatResponse($data); |
119 |
| - } catch (\InvalidArgumentException $e) { |
120 |
| - return []; |
| 132 | + try { |
| 133 | + $data = json_decode((string)$response->getBody(), true, 512, \JSON_BIGINT_AS_STRING); |
| 134 | + } catch (InvalidArgumentException $e) { |
| 135 | + throw new JsonException('Could not decode unleash response body.', $e->getCode(), $e); |
121 | 136 | }
|
| 137 | + |
| 138 | + return $this->formatResponse($data); |
122 | 139 | }
|
123 | 140 |
|
124 | 141 | protected function getFeaturesApiUrl(): string
|
|
0 commit comments