/activerecord-slotted_counters

Active Record extension providing slotted counters support

Primary LanguageRubyMIT LicenseMIT

Gem Version Build

Active Record slotted counters

This gem adds slotted counters support to Active Record counter cache. Slotted counters help to reduce contention on a single row update in case you have many concurrent operations (like updating a page views counter during traffic spikes).

Read more about slotted counters in this post.

Sponsored by Evil Martians

Installation

Add to your project:

# Gemfile
gem "activerecord-slotted_counters"

Requirements

  • Ruby >= 2.7.0
  • Rails 6+

Usage

First, add and apply the required migration(-s):

bin/rails generate slotted_counters:install
bin/rails db:migrate

Then, add the following line to the model to add a slotted counter:

class User < ApplicationRecord
  has_slotted_counter :comments
end

Now you can use all the common counter cache APIs as before:

# Manipulating the counter explicitly
user = User.first

User.increment_counter(:comments_count, user.id)
User.decrement_counter(:comments_count, user.id)
User.reset_counters(user.id, :comments)
# etc.

# Reading the value
user.comments_count

Under the hood, a row in the slotted_counters table is created associated with the record.

NOTE: Reading the current value performs SQL query once:

user.comments_count #=> select * from slotted_counters where ...
user.comments_count #=> no sql

If you want to preload counters for multiple records, you can use a convenient #with_slotted_counters method:

User.all.with_slotted_counters(:comments).find_each do
  _1.comments_count #=> no sql
end

Using counter_cache: true on belongs_to associations also works as expected.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/evilmartians/activerecord-slotted_counters.

Credis

This gem is generated via new-gem-generator.

License

The gem is available as open source under the terms of the MIT License.