Skip to content

Commit

Permalink
Do not use expensive hash keys for cheap queries
Browse files Browse the repository at this point in the history
Role.hashed uses Rails.all.cache_key - which is rather expensive

SELECT COUNT(*) AS `size`, MAX(`roles`.`updated_at`) AS timestamp FROM `roles`

to avoid querying 8 role titles. The problem is that all the
other code expects Role.hashed to be cheaper than querying the
database directly - which is no longer true with this approach.

E.g.

irb(main):001:0> Role.local_roles
   (0.2ms)  SELECT COUNT(*) AS `size`, MAX(`roles`.`updated_at`) AS timestamp FROM `roles`
   (0.3ms)  SELECT COUNT(*) AS `size`, MAX(`roles`.`updated_at`) AS timestamp FROM `roles`
   (0.2ms)  SELECT COUNT(*) AS `size`, MAX(`roles`.`updated_at`) AS timestamp FROM `roles`
   (0.2ms)  SELECT COUNT(*) AS `size`, MAX(`roles`.`updated_at`) AS timestamp FROM `roles`
   (0.2ms)  SELECT COUNT(*) AS `size`, MAX(`roles`.`updated_at`) AS timestamp FROM `roles`

I noticed these repeated queries when working on involved_packages
and wondered since then what is going on.
  • Loading branch information
coolo committed Dec 17, 2018
1 parent 9559d3d commit 4bbceb5
Showing 1 changed file with 8 additions and 1 deletion.
9 changes: 8 additions & 1 deletion src/api/app/models/role.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,22 @@ class NotFound < APIError

scope :global, -> { where(global: true) }

after_save :delete_hashed_cache
after_destroy :delete_hashed_cache

# Fetches all roles and stores them as a hash. Uses title attribute as hash key.
#
# {"Admin" => #<Role id:1>, "downloader" => #<Role id:2>, ... }
def self.hashed
Rails.cache.fetch(Role.all.cache_key) do
Rails.cache.fetch('hashed_roles') do
Hash[Role.all.map { |role| [role.title, role] }]
end
end

def delete_hashed_cache
Rails.cache.delete('hashed_roles')
end

def self.find_by_title!(title)
find_by_title(title) || raise(NotFound, "Couldn't find Role '#{title}'")
end
Expand Down

0 comments on commit 4bbceb5

Please sign in to comment.