LoginSignup
1

More than 5 years have passed since last update.

[Grails]Cacheプラグインでblockのkey毎にキャッシュを消す方法

Posted at

概要

GrailsのCacheプラグインで、GSPの中で利用できる<cache:block>というタグが有ります。
<cache:block></cache:block>で囲まれた中の処理はキャッシュされ、2度目のアクセスからはキャッシュされた内容が返されるので、処理速度の向上が図れます。

また、key属性を使うことで、ページごとに異なった内容をキャッシュさせることも出来ます。
<cache:block key="contentId-123>みたいな感じですね。

問題点

Serviceのキャッシュなどと違い、何故かこの<cache:block>には、key毎にキャッシュを削除するメソッドが存在しません。
なので、特定のページ(例えばcontentId-123の商品を表示しているページ)の<cache:block>でキャッシュされたものをクリアする、と言うことが出来ません。
キャッシュをクリアするためにはgrailsCacheAdminService.clearBlocksCache()というメソッドを使うしかありません。処理的には問題ありませんが、消す必要のないキャッシュまで全て消えてしまいます。

対策

自前で処理を追加します。
方法は色々有りますが、私は以下のようにしています。

キャッシュの作成

キャッシュの生成自体は上のサンプル通りです。
適当なGSP内で、キャッシュしたい内容を<cache:block>で囲みます。

<cache:block key="contentId-${contentId}">
...ココに重い処理。この部分がキャッシュされる
</cache:block>

キャッシュの削除メソッド

どこかのServiceに以下のメソッドを追加。

@CacheEvict(value='grailsBlocksCache', key="#key")
void clearBlockCacheByKey(String key){}

value='grailsBlocksCache' というvalueは固定です。コレはCacheプラグインが自動で付与しているものです。

削除メソッドを呼ぶ

ココが味噌です。先ほどclearBlockCacheByKeyに削除したいキャッシュのkeyを渡すだけなのですが、実は<cache:block>taglibを使うと、指定したkeyにGSPのクラス名が付与されています。
フォーマットは{GSPのクラス名}:{自分で指定したkey}となっています。
余り効率的なコードではありませんが、私は以下のようにして、grailsBlocksCacheに紐付いているkey名を一気に取得して、その中から、自分が指定したkey名を含むものを探しだして、先ほどのclearBlocksCacheByKeyに渡すようにしています。

def deleteCacheBlock() {

    String valueForCacheBlock = "grailsBlocksCache" // コレは固定
    String deleteKey = "contentId-123"    // この値を指定して、削除したいキャッシュのキーを切り替える

    String targetCacheKey = grailsCacheManager.getCache(valueForCacheBlock).getAllKeys().find {String key ->
        key.split(':')[-1] == deleteKey

    }
    if (targetCacheKey) {
        myCacheService.clearBlockCacheByKey(targetCacheKey)
    }
    render "ok"
}

まとめ

特に難しい内容でもなく、理想的な対処方法ではありませんが、ちょっとハマったのでメモです。
いやいや、もっと効率的な方法あるよとか、そもそもそのためにXXXというメソッドがあるよ、など有りましたら教えていただけると嬉しいです。。。

参考

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1