Use Laravel Cache to optimize access to user Settings

This commit is contained in:
Bubka 2023-02-10 14:16:40 +01:00
parent 28b239108f
commit 77eebbd35d
2 changed files with 86 additions and 6 deletions

View File

@ -7,10 +7,10 @@
use Exception;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Cache;
use Throwable;
class SettingService
@ -22,12 +22,27 @@ class SettingService
*/
private Collection $settings;
/**
* Cache duration
*
* @var int $minutes
*/
private int $minutes = 10;
/**
* Name of the cache item where options are persisted
*/
public const CACHE_ITEM_NAME = 'userOptions';
/**
* Constructor
*/
public function __construct()
{
self::build();
$this->settings = Cache::remember(self::CACHE_ITEM_NAME, now()->addMinutes($this->minutes), function () {
self::build();
return $this->settings;
});
}
/**
@ -74,7 +89,7 @@ public function set($setting, $value = null) : void
Log::info(sprintf('Setting %s is now %s', var_export($setting, true), var_export($this->restoreType($value), true)));
}
self::build();
self::buildAndCache();
}
/**
@ -86,6 +101,8 @@ public function delete(string $name) : void
{
Option::where('key', $name)->delete();
Log::info(sprintf('Setting %s deleted', var_export($name, true)));
self::buildAndCache();
}
/**
@ -121,6 +138,17 @@ private function build()
$this->settings = $settings;
}
/**
* Build and cache the options collection
*
* @return void
*/
private function buildAndCache()
{
self::build();
Cache::put(self::CACHE_ITEM_NAME, $this->settings, now()->addMinutes($this->minutes));
}
/**
* Replaces boolean by a patterned string as appstrack/laravel-options package does not support var type
*

View File

@ -3,8 +3,10 @@
namespace Tests\Feature\Services;
use App\Facades\Settings;
use App\Services\SettingService;
use App\Models\TwoFAccount;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Tests\FeatureTestCase;
@ -172,14 +174,17 @@ public function test_all_returns_native_and_user_settings()
/**
* @test
*/
public function test_set_setting_persist_correct_value()
public function test_set_setting_persist_correct_value_in_db_and_cache()
{
$value = Settings::set(self::SETTING_NAME, self::SETTING_VALUE_STRING);
$cached = Cache::get(SettingService::CACHE_ITEM_NAME); // returns a Collection
$this->assertDatabaseHas('options', [
self::KEY => self::SETTING_NAME,
self::VALUE => self::SETTING_VALUE_STRING,
]);
$this->assertEquals($cached->get(self::SETTING_NAME), self::SETTING_VALUE_STRING);
}
/**
@ -278,6 +283,7 @@ public function test_set_array_of_settings_persist_correct_values()
self::SETTING_NAME => self::SETTING_VALUE_STRING,
self::SETTING_NAME_ALT => self::SETTING_VALUE_INT,
]);
$cached = Cache::get(SettingService::CACHE_ITEM_NAME); // returns a Collection
$this->assertDatabaseHas('options', [
self::KEY => self::SETTING_NAME,
@ -288,6 +294,9 @@ public function test_set_array_of_settings_persist_correct_values()
self::KEY => self::SETTING_NAME_ALT,
self::VALUE => self::SETTING_VALUE_INT,
]);
$this->assertEquals($cached->get(self::SETTING_NAME), self::SETTING_VALUE_STRING);
$this->assertEquals($cached->get(self::SETTING_NAME_ALT), self::SETTING_VALUE_INT);
}
/**
@ -319,18 +328,20 @@ public function test_set_false_setting_persist_transformed_boolean()
/**
* @test
*/
public function test_del_remove_setting_from_db()
public function test_del_remove_setting_from_db_and_cache()
{
DB::table('options')->insert(
[self::KEY => self::SETTING_NAME, self::VALUE => strval(self::SETTING_VALUE_STRING)]
);
$value = Settings::delete(self::SETTING_NAME);
Settings::delete(self::SETTING_NAME);
$cached = Cache::get(SettingService::CACHE_ITEM_NAME); // returns a Collection
$this->assertDatabaseMissing('options', [
self::KEY => self::SETTING_NAME,
self::VALUE => self::SETTING_VALUE_STRING,
]);
$this->assertFalse($cached->has(self::SETTING_NAME));
}
/**
@ -354,4 +365,45 @@ public function test_isUserDefined_returns_false()
$this->assertFalse(Settings::isUserDefined('showTokenAsDot'));
}
/**
* @test
*/
public function test_cache_is_requested_at_instanciation()
{
Cache::shouldReceive('remember')
->andReturn(collect([]));
$settingService = new SettingService();
Cache::shouldHaveReceived('remember');
}
/**
*
*/
public function test_cache_is_updated_when_setting_is_set()
{
Cache::shouldReceive('remember', 'put')
->andReturn(collect([]), true);
$settingService = new SettingService();
$settingService->set(self::SETTING_NAME, self::SETTING_VALUE_STRING);
Cache::shouldHaveReceived('put');
}
/**
*
*/
public function test_cache_is_updated_when_setting_is_deleted()
{
Cache::shouldReceive('remember', 'put')
->andReturn(collect([]), true);
$settingService = new SettingService();
$settingService->delete(self::SETTING_NAME);
Cache::shouldHaveReceived('put');
}
}