henzeb / warmable
框架无关的缓存预热器
Requires
- php: ^8.1
- henzeb/datetime: ^1.0
- psr/simple-cache: ^3.0
Requires (Dev)
- infection/infection: *
- mockery/mockery: ^1.6
- phpunit/phpunit: ^9|^10
This package is auto-updated.
Last update: 2024-09-22 11:26:16 UTC
README
本软件包受到了@timacdonald的一次演讲的启发,他在演讲中展示了一种通过简单的可调用类预热缓存条目的技术。
当你缓存了复杂操作的结果,偶尔会有用户需要等待操作被重新缓存。如果请求速率足够高,可能有多个人同时需要这样做。
本软件包提供了实现这一点的框架。它实现了PSR16缓存接口,因此几乎支持你能够想到的所有缓存机制,如果不支持,你可以实现一个包装器,它仍然支持你能够想到的所有缓存机制。
Laravel开发人员也可以使用此软件包,但为了充分利用Laravel的功能,最好是安装并使用Warmable for Laravel
安装
只需使用以下命令进行安装。
composer require henzeb/warmable
术语
预热/正在预热
预热
或正在预热
这一术语指的是在计划任务或队列任务中缓存。
预加热
当缓存在与执行的同时填充时使用此术语,这是缓存不存在时的默认操作。这也可以分发给像队列系统这样的后台操作。
用法
创建Warmable
创建Warmable
非常简单。
use Henzeb\Warmable\Warmable; use Psr\SimpleCache\CacheInterface; use DateTimeInterface; use DateInterval; class HeavyOperation extends Warmable { protected function key() : string { // ... return your key } protected function ttl() : DateTimeInterface|DateInterval|int|null { // ... return your desired ttl } protected function gracePeriod() : DateTimeInterface|DateInterval|int|null { // ... return your desired grace period } protected function cache(): CacheInterface { // ... your cache implementation } protected function warmable(): mixed { // ... your heavy operation } }
注意:可以省略key
和ttl
。省略key
时,将基于你的对象的FQCN生成一个键。省略ttl
时,Warmable
结果将永久存储在缓存中。
链式方法。
Warmable
允许链式调用方法。你可以从任何你希望的方法开始。
HeavyOperation::withKey('yourKey')->get(); HeavyOperation::withTtl(300)->withKey('yourKey')->get(); HeavyOperation::withKey('yourKey')->withTtl(300)->get();
make
使用make
可以轻松获取你的Warmable
实例。你可以添加传递给构造函数的参数。
// equivalent to new HeavyOperation(); HeavyOperation::make(); // equivalent to new HeavyOperation(new YourService()); HeavyOperation::make(new YourService());
get
使用此方法可以轻松访问缓存数据。
HeavyOperation::get(); HeavyOperation::make()->get();
默认情况下,如果尚未存在,Warmable
会预先加热数据。如果你不希望在响应之前发生这种情况,可以设置默认值。在这种情况下,它将在将响应发送到浏览器之后才执行该操作。
HeavyOperation::get([]); HeavyOperation::get(true); HeavyOperation::get(fn()=>false);
注意:这不适用于null
。请使用withoutPreheating代替。
with
Warmable
方法支持基本的依赖注入。使用此方法,你可以使缓存对每个用户或项目是唯一的。你不需要做任何事情,只需将其传递给构造函数即可。
use Henzeb\Warmable\Warmable; class HeavyOperation extends Warmable { // ... public function warmable(int $id): mixed { // ... return 'this is '.$id; } } HeavyOperation::with(12)->get(); // returns 'this is 12' HeavyOperation::with(14)->get(); // returns 'this is 14' HeavyOperation::with(12)->get(); // returns 'this is 12' from cache HeavyOperation::with(14)->get(); // returns 'this is 14' from cache
key
默认情况下,Warmable
会为你生成一个唯一的键。你不需要做任何事情。即使你想为不同的项目重用Warmable
,Warmable
也会为你提供支持。但如果你想自定义键,有两种方法可以做到这一点。
第一种是在你的Warmable
类上设置key
方法。
use Henzeb\Warmable\Warmable; class HeavyOperation extends Warmable { protected function key() : string{ return 'your-key'; } } HeavyOperation::get(); // retrieves from 'your-key' HeavyOperation::with(12)->get(); // retrieves from 'your-key.<sha1 hash>'
第二种方法是内联的。
HeavyOperation::withKey('other-key')->get(); // retrieves from 'other-key' HeavyOperation::withKey('other-key') ->with(12) ->get(); // retrieves from 'other-key.<sha1 hash>'
缓存
缓存显然是必需的元素。通过强制性的cache
方法设置。还有一个可以内联使用的withCache
方法。
use Psr\SimpleCache\CacheInterface; HeavyOperation::withCache(<CacheInterface::class>); HeavyOperation::make()->withCache(<CacheInterface::class>);
注意:Warmable
接受任何实现了PSR-16 CacheInterface
的缓存实现。如果你使用的缓存系统没有实现它,你可以轻松创建一个实现了它的包装器。
生存时间 (TTL)
允许您使用与类内部定义的不同 TTL。
注意,Ttl 默认为 null
,因此默认为 永远
。
use Henzeb\Warmable\Warmable; class HeavyOperation extends Warmable { protected function ttl(): DateTimeInterface|DateInterval|int|null { return DateInterval::createFromDateString('300 seconds'); } }
或者您可以直接设置
use Henzeb\Warmable\Warmable; // expires on given date HeavyOperation::withTtl(new DateTime('2024-02-31 23:00')); // expires in 300 seconds HeavyOperation::withTtl( DateInterval::createFromDateString('300 seconds') ); // expires in 300 seconds HeavyOperation::withTtl(300);
宽限期
与 TTL 结合使用,宽限期允许您在更新缓存的同时向用户提供旧数据。此更新发生在返回浏览器响应之后。
以下示例将创建一个存活时间为 600 秒的缓存项。在 300 秒后,下一次调用将返回缓存中的值,并注册一个更新缓存项的关闭函数,该缓存项将存活 600 秒,依此类推。
use Henzeb\Warmable\Warmable; class HeavyOperation extends Warmable { protected function ttl(): DateTimeInterface|DateInterval|int|null { return 300 } protected function gracePeriod(): DateTimeInterface|DateInterval|int|null { return 300 } }
getKey
有时您可能需要查看您的 Warmable
使用的键。
// returns warmable.HeavyOperation HeavyOperation::getKey(); // returns test HeavyOperation::withKey('test')->getKey(); // returns test.<sha1 hash> HeavyOperation::withKey('test')->with(id)->getKey();
missing
// returns true HeavyOperation::missing(); // returns false HeavyOperation::get(); // will preheat the cache HeavyOperation::make()->missing(); HeavyOperation::missing();
isPreheated
此方法告诉您缓存是否已预热。
$operation = HeavyOperation::make(); $operation->isPreheated(); // returns false $operation->get(); // will preheat the cache $operation->isPreheated(); // returns true
withoutPreheating
此方法允许您显式禁用预热。
HeavyOperation::withoutPreheating()->get(); // returns null when not warmed up // and when called again: HeavyOperation::withoutPreheating()->get(); // returns null when not warmed up
withPreheating
与 withoutPreheating 完全相同,但它切换了预热。
// would preheat the warmable data. HeavyOperation::withPreheating()->get(); // would preheat the data after shutdown, and return default instead. HeavyOperation::withPreheating()->get([]);
shouldPreheat
此方法告诉您预热标志是否开启。
HeavyOperation::shouldPreheat(); // returns true (default) HeavyOperation::withPreheating()->shouldPreheat(); // returns true HeavyOperation::withoutPreheating()->shouldPreheat(); // returns false
cooldown
如果由于某些原因需要删除缓存,可以调用 cooldown
。
HeavyOperation::cooldown(); HeavyOperation::make()->cooldown();
自定义预热策略
如果您的应用程序可以访问队列,则很容易更改预热策略。默认情况下,它会在执行时进行预热。
use Henzeb\Warmable\Warmable; class HeavyOperation extends Warmable { // ... your Warmable definition protected function getPreheated(bool $hasDefault): mixed { // ... } }
注意:返回 null
会导致 get
方法使用默认值。
重写公共接口
在底层,Warmable
使用 __call
和 __callStatic
来允许链式静态和动态调用。如果您想重写公共接口上的方法,您应该找到它的 call<method>
对应方法。
例如:如果您想重写 with
方法,您应该扩展 callWith
方法。
测试
composer test
贡献
请参阅 CONTRIBUTING 以获取详细信息。
安全
如果您发现任何安全相关的问题,请通过电子邮件 henzeberkheij@gmail.com 而不是使用问题跟踪器。
鸣谢
许可证
GNU AGPLv. 请参阅 许可证文件 以获取更多信息。