henzeb / warmable-laravel
Laravel 框架的缓存预热器
Requires
- php: ^8.1
- henzeb/warmable: ^v1.1.0
- illuminate/support: ^9.0|^10
Requires (Dev)
- infection/infection: *
- orchestra/testbench: ^7.0|^8.0
- phpunit/phpunit: ^9|^10
This package is auto-updated.
Last update: 2024-09-22 10:19:05 UTC
README
本包受到 2024 年 LaraconEU 大会 @timacdonald 的启发,他在会上展示了一种使用简单的可调用类预热的缓存条目的技术。
当你缓存一个重操作的结果时,有时用户将不得不等待操作再次被缓存。如果请求速率足够高,可能有多个人同时这样做。
本包旨在通过利用调度器和队列尽可能减少这种情况。
它主要针对 Laravel 构建,但由于我使用了 PSR-16 psr/simple-cache
CacheInterface,任何人都可以使用它。只需安装纯净的 Warmable 即可,因为这个包是 Laravel 特定的
安装
只需使用以下命令进行安装。
composer require henzeb/warmable-laravel
术语
预热/正在预热
预热或正在预热是指通过 cron 或队列进行缓存。
预加热
预加热是指在执行过程中填充缓存时使用的术语,这是缓存不存在时的默认操作。这也可以派发到像队列系统这样的后台操作。
使用
这里的说明是针对 Laravel 的。有关更多信息,请参阅 Warmable 的文档。
创建一个可预热对象
创建一个 Warmable
非常简单。正如你所看到的,不需要 cache
方法,因为默认情况下,Warmable
使用默认的 Cache
驱动器。
你仍然可以选择覆盖它并使用不同的驱动器。你不必坚持使用 CacheInterface
实现,你也可以使用字符串。你可以在任何可以输入缓存驱动器的地方使用字符串。
注意:实际上,使用字符串在性能上更好,因为当在队列中进行序列化时,它需要遍历所有配置的存储来确定其名称。
use Henzeb\Warmable\Illuminate\Warmable; use DateTimeInterface; use DateInterval; class HeavyOperation extends Warmable { protected function warmable(): mixed { // ... your heavy operation } }
依赖注入
Warmable Laravel
利用 Laravel 的依赖注入系统。它的工作方式与在 Controller
上解决依赖项的方式相似,因为它使用相同的实现。
use Henzeb\Warmable\Illuminate\Warmable; use DateTimeInterface; use DateInterval; class HeavyOperation extends Warmable { protected function warmable(YourInjectedService $service): mixed { // ... your heavy operation } }
可以使用 with
方法注入依赖项,就像纯 Warmable
实现一样,额外的是你可以使用关联数组来注入自定义变量。
以下示例将注入 YourInjectedService
的实例,而不是使用应用程序容器解析新的实例。
HeavyOperation::with([ 'service' => new YourInjectedService() ]); // The following however isn't possible: HeavyOperation::with( [ 'service' => new YourInjectedService() ], 'another item' );
注意:请注意,使用 with
注入的服务会改变键,使其唯一。有关更多信息,请参阅 Warmable。
在构造函数中注入
你也可以像你习惯的那样在构造函数中注入依赖项。你不必使用 resolve
解析实例,因为 Warmable
在幕后使用 make
为你做了这件事。
use Henzeb\Warmable\Illuminate\Warmable; class HeavyOperation extends Warmable { public function __construct( private YourService $yourService private YourOtherService $otherService ) { } } HeavyOperation::make(); HeavyOperation::make(['yourService' => new YourService()]);
get
get 方法的行为与其纯版本类似,但不同的是,当缓存项目尚不存在时,它将自身作为作业派发到队列,然后立即返回设置的默认值。像你习惯的那样,它接受可调用的默认值。
注意:如果将 connection
变量设置为 sync
,它将立即创建缓存并返回其结果。当设置了默认值时,它将在向浏览器返回响应后执行此操作。
调度与队列
Warmable
是一个实现了 ShouldQueue
接口的 Job
,这使得调度 Warmable
并将其发送到队列变得非常容易。
Warmable
是可调用的,允许您只需投入完全限定类名(FQCN),而无需回头再看。
$schedule->call(HeavyOperation::class)->daily(); // happens during execution $schedule->job(HeavyOperation::class)->hourly(); // dispatches to the queue
注意:它还实现了 ShouldBeUnique
接口,这确保它不会同时运行两次。由于 Warmable
仅仅是一个作业,您可以进一步配置它。有关更多信息,请参阅 Laravel 文档。
确保缓存已预热
两者都会在预定时间预热缓存。但是,如果您需要确保缓存在缓存过期或丢失后立即预热,则可以使用 withPreheating
,这将根据您的配置立即发送作业或调用,即使尚未达到指定的间隔。
$schedule->call(HeavyOperation::withPreheating())->daily(); // Will dispatch a job on the queue when preheating needs to happen $schedule->job(HeavyOperation::withPreheating(true))->hourly();
注意:所有这一切的美丽之处在于,每当 Warmable
预热后,它都不会排队或执行任何操作。因此,它不会预热然后再预热。
预热
这是一个非常有用的特殊方法,当数据偶尔发生变化且需要尽快反映这些变化时。它将 Warmable
作为作业发送到队列。这允许用户继续前进,无需等待保存操作完成。
此方法返回一个 PendingDispatch
实例,允许您在实际发送之前修改配置。
HeavyOperation::preheat()->onQueue('sync');
事件
总共有 Warmable
发射 4 个不同的事件。事件名称应该可以说明它们何时被发射。
每个事件接收 key
和 warmable
作为 FQCN。除 CacheFailedWarmingUp
外,该事件接收实际实例以供调试目的。
CacheWarmedUp
还接收 result
。这就是缓存中的内容。
使用自定义事件
可以使用实例变量更改每个事件。自定义事件仅由此 Warmable
发射。这允许您只需要监听特定 Warmable
的事件,而无需在监听器内部实现多个 if
或 match
语句。
use Henzeb\Warmable\Illuminate\Warmable; class YourEvent { public function __construct( public string $key, // not required, the key of your Warmable public string $warmable // not required, FQCN of your Warmable public mixed $result = null // not required, only for CacheWarmedUp events ) { } } class HeavyOperation extends Warmable { protected string $preheatingEvent = YourEvent::class; protected string $warmingUpEvent = YourEvent::class; protected string $failedWarmingUpEvent = YourEvent::class; protected string $warmedUpEvent = YourEvent::class; }
测试
composer test
贡献
请参阅CONTRIBUTING 获取详细信息。
安全
如果您发现任何与安全相关的问题,请通过电子邮件 henzeberkheij@gmail.com 而不是使用问题跟踪器。
鸣谢
许可证
GNU AGPLv. 请参阅许可证文件获取更多信息。