Skip to content

Commit a0bfb7d

Browse files
committed
- Optimize settings retrieval with runtime and per-class config caching.
- Add `clearSettingsCache` method to handle clearing runtime and Redis cache. - Update README with Redis request counting instructions.
1 parent 24ed93a commit a0bfb7d

2 files changed

Lines changed: 91 additions & 19 deletions

File tree

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,18 @@ class User extends Model
283283
}
284284

285285
```
286+
## Counting redis requests
287+
```
288+
docker compose exec redis redis-cli monitor | grep -E '"(GET|SET|DEL)"' | grep "model_settings" | awk '{
289+
if ($0 ~ /"GET"/) get++;
290+
else if ($0 ~ /"SET"/) set++;
291+
else if ($0 ~ /"DEL"/) del++;
292+
total++;
293+
printf "\rGET: %d, SET: %d, DEL: %d, TOTAL: %d", get, set, del, total;
294+
}'
295+
```
296+
297+
286298

287299
## Changelog <a name="changelog"></a>
288300
Please see [CHANGELOG](CHANGELOG.md) for more information what has changed recently.

src/Traits/HasSettingsTable.php

Lines changed: 79 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,61 +8,121 @@
88
use Illuminate\Database\Eloquent\Relations\MorphOne;
99
use Illuminate\Support\Facades\Cache;
1010

11-
/**
12-
* Trait HasSettingsTable
13-
* @package Glorand\Model\Settings\Traits
14-
* @property ModelSettings $modelSettings
15-
* @property array $settings
16-
* @method morphOne($model, $name)
17-
*/
1811
trait HasSettingsTable
1912
{
2013
use HasSettings;
2114

15+
protected $settingsRuntimeCache = null;
16+
protected $settingsManagerInstance = null;
17+
protected static $configCache = [];
18+
2219
/**
23-
* @return \Glorand\Model\Settings\Contracts\SettingsManagerContract
20+
* Returns a settings manager instance for the model, creating one if necessary.
21+
* @return SettingsManagerContract
2422
* @throws \Glorand\Model\Settings\Exceptions\ModelSettingsException
2523
*/
2624
public function settings(): SettingsManagerContract
2725
{
28-
return new TableSettingsManager($this);
26+
if ($this->settingsManagerInstance === null) {
27+
$this->settingsManagerInstance = new TableSettingsManager($this);
28+
}
29+
30+
return $this->settingsManagerInstance;
2931
}
3032

3133
/**
34+
* Retrieves the settings value for the model, optionally using a cache.
3235
* @return array
3336
*/
3437
public function getSettingsValue(): array
3538
{
36-
if (config('model_settings.settings_table_use_cache')) {
37-
return Cache::rememberForever($this->getSettingsCacheKey(), function () {
38-
return $this->__getSettingsValue();
39-
});
39+
// Runtime cache = ZERO Redis calls after first access
40+
if ($this->settingsRuntimeCache !== null) {
41+
return $this->settingsRuntimeCache;
42+
}
43+
44+
// Cache config lookup once per class (not per instance)
45+
if (!isset(static::$configCache['use_cache'])) {
46+
static::$configCache['use_cache'] = config('model_settings.settings_table_use_cache');
47+
}
48+
49+
if (static::$configCache['use_cache']) {
50+
// Only 1 Redis call per request
51+
$this->settingsRuntimeCache = Cache::rememberForever(
52+
$this->getSettingsCacheKey(),
53+
fn() => $this->__getSettingsValue()
54+
);
55+
} else {
56+
$this->settingsRuntimeCache = $this->__getSettingsValue();
4057
}
4158

42-
return $this->__getSettingsValue();
59+
return $this->settingsRuntimeCache;
4360
}
4461

62+
/**
63+
* Retrieves the settings value for the model.
64+
* @return array
65+
*/
4566
private function __getSettingsValue(): array
4667
{
47-
if ($modelSettings = $this->modelSettings()->first()) {
48-
return $modelSettings->settings;
68+
// Eager loading support (prevents N+1)
69+
if ($this->relationLoaded('modelSettings')) {
70+
$modelSettings = $this->getRelation('modelSettings');
71+
return $modelSettings ? $modelSettings->settings : [];
4972
}
5073

51-
return [];
74+
$modelSettings = $this->modelSettings()
75+
->select('settings', 'model_id', 'model_type')
76+
->first();
77+
78+
return $modelSettings ? $modelSettings->settings : [];
5279
}
5380

5481
/**
55-
* @return \Illuminate\Database\Eloquent\Relations\MorphOne
82+
* Define an inverse one-to-one or many relationship.
83+
* @return MorphOne
5684
*/
5785
public function modelSettings(): MorphOne
5886
{
5987
return $this->morphOne(ModelSettings::class, 'model');
6088
}
6189

90+
/**
91+
* Retrieves the cache key for settings associated with the model.
92+
*
93+
* This method ensures that a consistent cache key is generated for
94+
* the model's settings by utilizing a shared static configuration
95+
* for the cache prefix and combining it with the table name and
96+
* primary key of the current model instance.
97+
*
98+
* @return string The generated cache key for the model's settings.
99+
*/
62100
public function getSettingsCacheKey(): string
63101
{
64-
return config('model_settings.settings_table_cache_prefix') . $this->getTable() . '::' . $this->getKey();
102+
// Static config cache shared across all instances
103+
if (!isset(static::$configCache['cache_prefix'])) {
104+
static::$configCache['cache_prefix'] = config('model_settings.settings_table_cache_prefix');
105+
}
106+
107+
return static::$configCache['cache_prefix'] . $this->getTable() . '::' . $this->getKey();
108+
}
109+
110+
/**
111+
* Clears the runtime cache and optionally the cache for the model's settings.'
112+
* @return void
113+
*/
114+
public function clearSettingsCache(): void
115+
{
116+
$this->settingsRuntimeCache = null;
117+
118+
if (static::$configCache['use_cache'] ?? config('model_settings.settings_table_use_cache')) {
119+
Cache::forget($this->getSettingsCacheKey());
120+
}
65121
}
66122

123+
/**
124+
* Retrieves the name of the database table associated with the model.
125+
* @return string
126+
*/
67127
abstract public function getTable();
68128
}

0 commit comments

Comments
 (0)