Skip to content

Commit 58dbd60

Browse files
fix: lazy load Redis connection to prevent boot-time errors
Redis connection is now initialized on first use instead of in constructor. This prevents connection errors during package discovery and composer install when Redis is not available.
1 parent 82b1697 commit 58dbd60

File tree

1 file changed

+66
-44
lines changed

1 file changed

+66
-44
lines changed

src/Support/RedisMetricsStore.php

Lines changed: 66 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -11,28 +11,46 @@
1111
* Simple wrapper around Laravel's Redis for queue metrics storage.
1212
* Uses Laravel's Redis connection directly instead of abstraction layer.
1313
*/
14-
final readonly class RedisMetricsStore
14+
final class RedisMetricsStore
1515
{
16-
private Connection $redis;
16+
private ?Connection $redis = null;
1717

18-
private string $prefix;
18+
private ?string $prefix = null;
1919

20-
public function __construct()
20+
/**
21+
* Get Redis connection (lazy loaded).
22+
*/
23+
private function getRedis(): Connection
24+
{
25+
if ($this->redis === null) {
26+
/** @var string $connection */
27+
$connection = config('queue-metrics.storage.connection', 'default');
28+
$this->redis = Redis::connection($connection);
29+
}
30+
31+
return $this->redis;
32+
}
33+
34+
/**
35+
* Get prefix (lazy loaded).
36+
*/
37+
private function getPrefix(): string
2138
{
22-
/** @var string $connection */
23-
$connection = config('queue-metrics.storage.connection', 'default');
24-
$this->redis = Redis::connection($connection);
25-
/** @var string $prefix */
26-
$prefix = config('queue-metrics.storage.prefix', 'queue_metrics');
27-
$this->prefix = $prefix;
39+
if ($this->prefix === null) {
40+
/** @var string $prefix */
41+
$prefix = config('queue-metrics.storage.prefix', 'queue_metrics');
42+
$this->prefix = $prefix;
43+
}
44+
45+
return $this->prefix;
2846
}
2947

3048
/**
3149
* Build a Redis key from segments.
3250
*/
3351
public function key(string ...$segments): string
3452
{
35-
return $this->prefix.':'.implode(':', $segments);
53+
return $this->getPrefix().':'.implode(':', $segments);
3654
}
3755

3856
/**
@@ -49,7 +67,7 @@ public function getTtl(string $type): int
4967
*/
5068
public function connection(): Connection
5169
{
52-
return $this->redis;
70+
return $this->getRedis();
5371
}
5472

5573
/**
@@ -67,10 +85,11 @@ public function driver(): self
6785
*/
6886
public function setHash(string $key, array $data, ?int $ttl = null): void
6987
{
70-
$this->redis->hmset($key, $data);
88+
$redis = $this->getRedis();
89+
$redis->hmset($key, $data);
7190

7291
if ($ttl !== null) {
73-
$this->redis->expire($key, $ttl);
92+
$redis->expire($key, $ttl);
7493
}
7594
}
7695

@@ -79,22 +98,23 @@ public function setHash(string $key, array $data, ?int $ttl = null): void
7998
*/
8099
public function getHash(string $key): array
81100
{
82-
$result = $this->redis->hgetall($key);
101+
$result = $this->getRedis()->hgetall($key);
83102

84103
return is_array($result) ? $result : [];
85104
}
86105

87106
public function getHashField(string $key, string $field): mixed
88107
{
89-
return $this->redis->hget($key, $field);
108+
return $this->getRedis()->hget($key, $field);
90109
}
91110

92111
public function incrementHashField(string $key, string $field, int|float $value): void
93112
{
113+
$redis = $this->getRedis();
94114
if (is_float($value)) {
95-
$this->redis->hincrbyfloat($key, $field, $value);
115+
$redis->hincrbyfloat($key, $field, $value);
96116
} else {
97-
$this->redis->hincrby($key, $field, $value);
117+
$redis->hincrby($key, $field, $value);
98118
}
99119
}
100120

@@ -103,10 +123,10 @@ public function incrementHashField(string $key, string $field, int|float $value)
103123
*/
104124
public function addToSortedSet(string $key, array $membersWithScores, ?int $ttl = null): void
105125
{
106-
$this->redis->zadd($key, $membersWithScores);
126+
$this->getRedis()->zadd($key, $membersWithScores);
107127

108128
if ($ttl !== null) {
109-
$this->redis->expire($key, $ttl);
129+
$this->getRedis()->expire($key, $ttl);
110130
}
111131
}
112132

@@ -115,35 +135,35 @@ public function addToSortedSet(string $key, array $membersWithScores, ?int $ttl
115135
*/
116136
public function getSortedSetByRank(string $key, int $start, int $stop): array
117137
{
118-
return $this->redis->zrange($key, $start, $stop);
138+
return $this->getRedis()->zrange($key, $start, $stop);
119139
}
120140

121141
/**
122142
* @return array<int, string>
123143
*/
124144
public function getSortedSetByScore(string $key, string $min, string $max): array
125145
{
126-
return $this->redis->zrangebyscore($key, $min, $max);
146+
return $this->getRedis()->zrangebyscore($key, $min, $max);
127147
}
128148

129149
public function countSortedSetByScore(string $key, string $min, string $max): int
130150
{
131-
return (int) $this->redis->zcount($key, $min, $max);
151+
return (int) $this->getRedis()->zcount($key, $min, $max);
132152
}
133153

134154
public function removeSortedSetByRank(string $key, int $start, int $stop): int
135155
{
136-
return (int) $this->redis->zremrangebyrank($key, $start, $stop);
156+
return (int) $this->getRedis()->zremrangebyrank($key, $start, $stop);
137157
}
138158

139159
public function removeSortedSetByScore(string $key, string $min, string $max): int
140160
{
141-
return (int) $this->redis->zremrangebyscore($key, $min, $max);
161+
return (int) $this->getRedis()->zremrangebyscore($key, $min, $max);
142162
}
143163

144164
public function removeFromSortedSet(string $key, string $member): void
145165
{
146-
$this->redis->zrem($key, $member);
166+
$this->getRedis()->zrem($key, $member);
147167
}
148168

149169
/**
@@ -152,7 +172,7 @@ public function removeFromSortedSet(string $key, string $member): void
152172
public function addToSet(string $key, array $members): void
153173
{
154174
if (! empty($members)) {
155-
$this->redis->sadd($key, $members);
175+
$this->getRedis()->sadd($key, $members);
156176
}
157177
}
158178

@@ -161,7 +181,7 @@ public function addToSet(string $key, array $members): void
161181
*/
162182
public function getSetMembers(string $key): array
163183
{
164-
return $this->redis->smembers($key);
184+
return $this->getRedis()->smembers($key);
165185
}
166186

167187
/**
@@ -170,22 +190,22 @@ public function getSetMembers(string $key): array
170190
public function removeFromSet(string $key, array $members): void
171191
{
172192
if (! empty($members)) {
173-
$this->redis->srem($key, $members);
193+
$this->getRedis()->srem($key, $members);
174194
}
175195
}
176196

177197
public function set(string $key, mixed $value, ?int $ttl = null): void
178198
{
179199
if ($ttl !== null) {
180-
$this->redis->setex($key, $ttl, $value);
200+
$this->getRedis()->setex($key, $ttl, $value);
181201
} else {
182-
$this->redis->set($key, $value);
202+
$this->getRedis()->set($key, $value);
183203
}
184204
}
185205

186206
public function get(string $key): mixed
187207
{
188-
return $this->redis->get($key);
208+
return $this->getRedis()->get($key);
189209
}
190210

191211
/**
@@ -201,17 +221,17 @@ public function delete(array|string $keys): int
201221
return 0;
202222
}
203223

204-
return (int) $this->redis->del(...$keys);
224+
return (int) $this->getRedis()->del(...$keys);
205225
}
206226

207227
public function exists(string $key): bool
208228
{
209-
return (bool) $this->redis->exists($key);
229+
return (bool) $this->getRedis()->exists($key);
210230
}
211231

212232
public function expire(string $key, int $seconds): bool
213233
{
214-
return (bool) $this->redis->expire($key, $seconds);
234+
return (bool) $this->getRedis()->expire($key, $seconds);
215235
}
216236

217237
/**
@@ -221,10 +241,10 @@ public function scanKeys(string $pattern): array
221241
{
222242
// Get the underlying PhpRedis client - it includes Redis connection prefix
223243
/** @var \Redis $client */
224-
$client = $this->redis->client();
244+
$client = $this->getRedis()->client();
225245

226246
// Get Laravel's Redis connection prefix (e.g., 'laravel_database_')
227-
$connectionPrefix = $this->redis->_prefix('');
247+
$connectionPrefix = $this->getRedis()->_prefix('');
228248

229249
// Combine connection prefix with our pattern
230250
$fullPattern = $connectionPrefix.$pattern;
@@ -255,7 +275,7 @@ public function scanKeys(string $pattern): array
255275
public function pipeline(callable $callback): void
256276
{
257277
// @phpstan-ignore-next-line - PhpRedis pipeline accepts no parameters in newer versions
258-
$this->redis->pipeline(function ($pipe) use ($callback) {
278+
$this->getRedis()->pipeline(function ($pipe) use ($callback) {
259279
$wrapper = new PipelineWrapper($pipe);
260280
$callback($wrapper);
261281
});
@@ -270,19 +290,21 @@ public function pipeline(callable $callback): void
270290
*/
271291
public function transaction(callable $callback): array
272292
{
293+
$redis = $this->getRedis();
294+
273295
// Laravel Redis uses multi() and exec() for transactions
274-
$this->redis->multi();
296+
$redis->multi();
275297

276298
try {
277299
// @phpstan-ignore-next-line - Laravel Connection type is compatible with PipelineWrapper
278-
$wrapper = new PipelineWrapper($this->redis);
300+
$wrapper = new PipelineWrapper($redis);
279301
$callback($wrapper);
280302

281-
$results = $this->redis->exec();
303+
$results = $redis->exec();
282304

283305
return is_array($results) ? $results : [];
284306
} catch (\Throwable $e) {
285-
$this->redis->discard();
307+
$redis->discard();
286308
throw $e;
287309
}
288310
}
@@ -295,7 +317,7 @@ public function transaction(callable $callback): array
295317
public function eval(string $script, int $numKeys, ...$args): mixed
296318
{
297319
// @phpstan-ignore-next-line - Redis eval accepts variadic args but PHPStan expects array
298-
return $this->redis->eval($script, $numKeys, ...$args);
320+
return $this->getRedis()->eval($script, $numKeys, ...$args);
299321
}
300322

301323
/**
@@ -305,6 +327,6 @@ public function eval(string $script, int $numKeys, ...$args): mixed
305327
*/
306328
public function command(string $method, array $parameters = []): mixed
307329
{
308-
return $this->redis->command($method, $parameters);
330+
return $this->getRedis()->command($method, $parameters);
309331
}
310332
}

0 commit comments

Comments
 (0)