部分キャッシュ
この記事では部分キャッシュを扱います。
部分キャッシュは、よく“ドーナツキャッシュ(donut caching)”と“ドーナツの穴キャッシュ(donut hole caching)”の2つのカテゴリに分けられる
BEAR.Sundayは ドーナツキャッシュ、ドーナツの穴キャッシュ、どちらにも対応しています。部分キャッシュはページをキャッシュできる部分とそうでない部分に分けて管理しようという技術です。ちなみにドーナッツの語源はdo-nut cache(音がdo not cache)から来ています。
ドーナッツキャッシュ
ESI
この部分キャッシュをCDNレベルで行うのがEdge Side Includes (ESI)です。
BEAR.Sundayではこれをサーバーサイドで実現することで、より効率的に部分キャッシュを実現しています。
設計と実装
以下のようなページの設計と実装を考えてみます。
青のlayoutの部分はヘッダー、フッター、Navバーなどページのレイアウトなどで静的ですす。そのlayoutの中に、キャッシュできないコンテンツ(donut)があるとします。
#[DonutCache]
class BlogPosting extends ResourceObject
{
#[Embed(rel: "donut", src: "app://self/live-content")]
public function onGet(int $id = 0): static
{
$this->body['article'] = 'hello world';
return $this;
}
}
live-content
はリクエストの度に値が代わり、キャッシュすることができません。なのでページ全体はキャッシュすることも出来ません。生存期間0のETagは無意味なのでETagも付きません。
しかしarticle
をbodyにアサインして計算したLayoutはキャッシュされ、再利用されます。
これは内部で小さなテンプレートエンジンを生成してレンダリングしているようなものです。以下のようなテンプレートを作っています
<html> ...
...<p>hello world</p>
...
[le:app://self/live-content]
...
..
</html>
このテンプレートから埋め込みリンクのapp://self/live-content
を取得して、レンダリングしてプレースフォルダの[le:app://self/live-content]
と入れ替えています。
コンテンツ全体のキャッシュは出来ないため、ネットワーク資源の節約は出来ません。しかし計算資源を最小化しています。二度目のリクエストでonGet
メソッドの実行や、layoutテンプレートレンダリングが行われることはなく再利用されます。
REST制約
これはBEAR.Sundayの、URIとステートレスとリソースはその表現を持つという3つのRESTの特性で可能になっています。
この問題を既存のMVCフレームワークがAOPなしでどう解決するかを考えてみてください。良い設計エクセサイズになるのではないでしょうか?
優れた制約は考えてもいなかった問題を既に解決していることがあります。
BEAR.Sundayの実装を進めていく過程は、まさにこの認識の繰り返しでした。