ActiveSupport::Cache::Store implementation backed by a database via ActiveRecord.
Tested with:
- PostgreSQL
- SQlite3
- MySQL/MariaDB
Add gem to Gemfile and bundle install.
gem 'activesupport-cache-database'
This gem requires a database table activesupport_cache_entries
to be created. To do so generate a migration that would create required table.
rails generate cache:database:install
Make sure to read through migration file, before running a migration. You might want to tweak it to fit your usecase.
rails db:migrate
Open and use the new cache instance:
cache = ActiveSupport::Cache::DatabaseStore.new namespace: 'my-scope'
value = cache.fetch('some-key') { 'default' }
To use as a Rails cache store, simply use a new instance.
config.cache_store = ActiveSupport::Cache::DatabaseStore.new
By default this gem doesn't use any compression to store records, but there is an option to use gzip
by providing a "compression" paramater. e.g
cache(project, compression: 'gzip') do
{code: 'to cache'}
end
There are some cases, when compression could be skipped - if value is numeric (e.g. increment/decrement counters) and when value is less than 1024 bytes. This is done to avoid unreasonable overhead on performance.
After you have started caching into the database, you will likely see the database size growing significantly. It is crucial to implement an effective strategy to evict the cache from your DB.
There may be a large number of cache entries that do not possess an expires_at
value, so it will be necessary to decide on an optimal timeframe for storing your cache.
This next piece of code should be run periodically:
ActiveSupport::Cache::DatabaseStore.new.cleanup(
created_before: 1.week.ago
)
Without providing a created_before
value, only those caches with expires_at
values will be cleaned, leaving behind plenty of dead cache.
If you're using PostgreSQL, consider running vacuum or pg_repack intermittently to delete data physically as well.
There are two things you need to be aware about while using this gem:
- For performance reasons, your database may not be the most suitable general purpose cache backend. But in some cases, caching complex quieries in cache could be a good enough improvement.
- While already generally usable as a Rails cache store, this gem doesn't yet implement all required methods.