Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/components/chapters_sidebar_component.html.erb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<% cache "chapters-sidebar" do %>
<% cache ['chapters-sidebar', title, I18n.locale, :v2], skip_digest: true, expires_in: 10.minutes do %>
<% if title %>
<h3><%= title %></h3>
<% end %>
Expand Down
7 changes: 0 additions & 7 deletions app/models/chapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@ class Chapter < ApplicationRecord
has_many :feedbacks, through: :workshops

before_save :set_slug
after_update_commit :expire_chapters_sidebar_cache
after_create_commit :expire_chapters_sidebar_cache
after_destroy_commit :expire_chapters_sidebar_cache

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

Expand Down Expand Up @@ -65,10 +62,6 @@ def members_for_group(name)
members.where(groups: { name: }).distinct
end

def expire_chapters_sidebar_cache
Rails.cache.delete('chapters-sidebar')
end

def time_zone_exists
return unless time_zone && ActiveSupport::TimeZone[time_zone].nil?

Expand Down
24 changes: 0 additions & 24 deletions spec/models/chapter_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,30 +44,6 @@
end
end

context 'with cache expiration' do
let(:cache_key) { 'chapters-sidebar' }

it 'expires cache when chapter is created' do
Rails.cache.write(cache_key, 'cached content')
Fabricate(:chapter)
expect(Rails.cache.read(cache_key)).to be_nil
end

it 'expires cache when chapter is updated' do
Rails.cache.write(cache_key, 'cached content')
chapter = Fabricate(:chapter)
chapter.update!(name: 'Updated Name')
expect(Rails.cache.read(cache_key)).to be_nil
end

it 'expires cache when chapter is destroyed' do
Rails.cache.write(cache_key, 'cached content')
chapter = Fabricate(:chapter)
chapter.destroy
expect(Rails.cache.read(cache_key)).to be_nil
end
end

describe '#students' do
let(:chapter) { Fabricate(:chapter) }
let(:student_group) { Fabricate(:group, chapter:, name: 'Students') }
Expand Down
67 changes: 67 additions & 0 deletions spec/requests/chapters_sidebar_caching_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
require 'rails_helper'

RSpec.describe 'Homepage chapters sidebar fragment' do
let(:fragment_store) { ActiveSupport::Cache::MemoryStore.new }

around do |example|
old_perform_caching = ActionController::Base.perform_caching
old_cache_store = ActionController::Base.cache_store

ActionController::Base.perform_caching = true
ActionController::Base.cache_store = fragment_store

example.run
ensure
ActionController::Base.perform_caching = old_perform_caching
ActionController::Base.cache_store = old_cache_store
end

before do
Fabricate(:chapter, name: 'Newcastle', slug: 'newcastle')
Fabricate(:chapter, name: 'London', slug: 'london')
end

def count_sidebar_queries
queries = 0
subscriber = ActiveSupport::Notifications.subscribe('sql.active_record') do |_name, _start, _finish, _id, payload|
queries += 1 if payload[:sql].match?(/"chapters"\."active"/)
end
yield
queries
ensure
ActiveSupport::Notifications.unsubscribe(subscriber)
end

it 'stores the sidebar as a fragment' do
get '/'

fragment_keys = fragment_store.instance_variable_get(:@data).keys
expect(fragment_keys.grep(/chapters-sidebar/)).to be_present
end

it 'runs no sidebar query on a warm fragment' do
get '/'

warm_queries = count_sidebar_queries { get '/' }

expect(response).to have_http_status(:ok)
expect(warm_queries).to be_zero
end

it 'drops a chapter deactivated by a direct database update within the TTL' do
get '/'
expect(response.body).to include('Newcastle')

Chapter.where(slug: 'newcastle').update_all(active: false)

get '/'
expect(response.body).to include('Newcastle')

travel_to(11.minutes.from_now) do
get '/'

expect(response.body).to include('London')
expect(response.body).not_to include('Newcastle')
end
end
end
Loading