📌

Solid Cacheメモ

2024/10/11に公開

はじめに

Solid CacheはRails 8から標準搭載されるキャッシュエンジン。RDBMSを利用するのでキャッシュのためにRedisやMemcachedを用意する必要はない。

インストール

Rails 7.2とSolid Cache 1.0.6、データベースはMySQL 8.0で確認した。

余談

1.0系はRails 7.2から。その前の0.7.0はRails 7.1をサポートしていたが、1.0.0でサポートが切られた。

0.7.0では同じスキーマにsolid_cache_entriesテーブルが作成されたが、1.0.6(2024年10月11日現在の最新)ではキャッシュ用のテーブルは別のスキーマに作成される。

https://github.com/rails/solid_cache/pull/202

READMEの手順通りに下記のコマンドを順番に実行する。

bundle add solid_cache

Gemfileに追加され、

bin/rails solid_cache:install

Solid Cacheの構成ファイルおよびスキーマが作成されてproduction.rbcache_storeが変更される。

config/cache.yml
default: &default
  store_options:
    # Cap age of oldest cache entry to fulfill retention policies
    # max_age: <%= 60.days.to_i %>
    max_size: <%= 256.megabytes %>
    namespace: <%= Rails.env %>

development:
  <<: *default

test:
  <<: *default

production:
  database: cache
  <<: *default
config/environments/production.rb
  # Use a different cache store in production.
  config.cache_store = :solid_cache_store
db/cache_schema.rb
# frozen_string_literal: true

ActiveRecord::Schema[7.2].define(version: 1) do
  create_table "solid_cache_entries", force: :cascade do |t|
    t.binary "key", limit: 1024, null: false
    t.binary "value", limit: 536870912, null: false
    t.datetime "created_at", null: false
    t.integer "key_hash", limit: 8, null: false
    t.integer "byte_size", limit: 4, null: false
    t.index ["byte_size"], name: "index_solid_cache_entries_on_byte_size"
    t.index ["key_hash", "byte_size"], name: "index_solid_cache_entries_on_key_hash_and_byte_size"
    t.index ["key_hash"], name: "index_solid_cache_entries_on_key_hash", unique: true
  end
end

config/database.ymlは変更されないため更新する必要がある。スキーマが別ファイルのためMultiple Databasesにする。

config/database.yml
production:
  primary: &primary_production
    <<: *default
    database: blog_production
    username: blog
    password: <%= ENV["BLOG_DATABASE_PASSWORD"] %>
  cache:
    <<: *primary_production
    database: blog_production_cache
    migrations_paths: db/cache_migrate

開発環境でも利用できるようにする

本番環境に対してのみ構成されるため開発環境で検証できない。開発でも使えるようにするにはconfig/cache.ymlconfig/environments/development.rbを変更する必要がある。また同じようにconfig/database.ymlも変更する。

config/cache.yml
development:
  database: cache
  <<: *default
config/environments/development.rb
    config.cache_store = :solid_cache_store
config/database.yml
development:
  primary: &primary_development
    <<: *default
    database: blog_development
  cache:
    <<: *primary_development
    database: blog_development_cache
    migrations_paths: db/cache_migrate

bin/rails db:prepareを実行するとblog_development_cacheデータベースが作成されてその中にsolid_cache_entriesテーブルが作成される。

$ bin/rails dev:cache

Development mode is now being cached.

$ bin/rails c
blog(dev)> Rails.cache.read("blog-key-1")

読み込んでも当然何もヒットしない

SolidCache::Entry Load (5.0ms) SELECT solid_cache_entries.key, solid_cache_entries.value FROM solid_cache_entries WHERE solid_cache_entries.key_hash IN ('-1621313636976743433')
=> nil

書き込んでから

blog(dev)> Rails.cache.write("blog-key-1", "test")

SolidCache::Entry Upsert (12.7ms) INSERT INTO solid_cache_entries (key,value,key_hash,byte_size,created_at) VALUES (x'646576656c6f706d656e743a626c6f672d6b65792d31', x'001102000000000000f0bfffffffff74657374', -1621313636976743433, 181, CURRENT_TIMESTAMP(6)) AS solid_cache_entries_values ON DUPLICATE KEY UPDATE key=solid_cache_entries_values.key,value=solid_cache_entries_values.value,byte_size=solid_cache_entries_values.byte_size
=> true

読み込むと

blog(dev)> Rails.cache.read("blog-key-1")

SolidCache::Entry Load (1.0ms) SELECT solid_cache_entries.key, solid_cache_entries.value FROM solid_cache_entries WHERE solid_cache_entries.key_hash IN ('-1621313636976743433')
=> "test"

ヒットする。

成果物

https://github.com/trysmr/zenn-rails72-solid-cache

Discussion