Skip to content

Commit

Permalink
close #2058 invalidate cache for frequently use API
Browse files Browse the repository at this point in the history
  • Loading branch information
theachoem committed Nov 19, 2024
1 parent f739fd0 commit 12ffaf0
Show file tree
Hide file tree
Showing 11 changed files with 168 additions and 1 deletion.
16 changes: 16 additions & 0 deletions app/controllers/concerns/spree_cm_commissioner/content_cachable.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module SpreeCmCommissioner
module ContentCachable
extend ActiveSupport::Concern

included do
after_action :set_cache_control_for_cdn
end

def set_cache_control_for_cdn
return unless request.get? || request.head?
return unless request.base_url == ENV['CONTENT_HOST_URL']

response.set_header('Cache-Control', 'public, max-age=7200')
end
end
end
23 changes: 23 additions & 0 deletions app/controllers/spree/admin/base_controller_decorator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,29 @@ def parse_date(date, format: nil)
nil
end

# POST
def invalidate_api_caches
if params[:model].present?
api_patterns_map = {
'SpreeCmCommissioner::HomepageSection' => '/api/v2/storefront/homepage/*',
'SpreeCmCommissioner::HomepageBackground' => '/api/v2/storefront/homepage/*',
'Spree::Menu' => '/api/v2/storefront/menus*'
}

api_patterns = api_patterns_map[params[:model]]

if api_patterns.is_a?(Array)
api_patterns.each { |pattern| SpreeCmCommissioner::InvalidateCacheRequestJob.perform_later(pattern) }
elsif api_patterns.is_a?(String)
SpreeCmCommissioner::InvalidateCacheRequestJob.perform_later(api_patterns)
end
elsif params[:api_pattern].present?
SpreeCmCommissioner::InvalidateCacheRequestJob.perform_later(params[:api_pattern])
end

redirect_back fallback_location: admin_root_path
end

private

def redirect_to_billing
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module ActionController
module ApiDecorator
def self.prepended(base)
base.include SpreeCmCommissioner::ExceptionNotificable
base.include SpreeCmCommissioner::ContentCachable
end

# Annonymous block: https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Naming/BlockForwarding
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ module SpreeCmCommissioner
module ApplicationControllerDecorator
def self.prepended(base)
base.include SpreeCmCommissioner::ExceptionNotificable
base.include SpreeCmCommissioner::ContentCachable
end

# Annonymous block: https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Naming/BlockForwarding
Expand Down
31 changes: 31 additions & 0 deletions app/interactors/spree_cm_commissioner/invalidate_cache_request.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
require 'aws-sdk-cloudfront'

# pattern: '/api/v2/storefront/homepage_sections*'
# https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/invalidation-access-logs.html

module SpreeCmCommissioner
class InvalidateCacheRequest < BaseInteractor
delegate :pattern, to: :context

def call
client = ::Aws::CloudFront::Client.new(
region: ENV.fetch('AWS_REGION'),
access_key_id: ENV.fetch('AWS_ACCESS_KEY_ID'),
secret_access_key: ENV.fetch('AWS_SECRET_ACCESS_KEY'),
http_open_timeout: 15,
http_read_timeout: 60
)

context.response = client.create_invalidation(
distribution_id: ENV.fetch('ASSETS_SYNC_CF_DIST_ID'),
invalidation_batch: {
caller_reference: Time.now.to_i.to_s,
paths: {
quantity: 1,
items: [pattern]
}
}
)
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module SpreeCmCommissioner
class InvalidateCacheRequestJob < ApplicationJob
def perform(pattern)
SpreeCmCommissioner::InvalidateCacheRequest.call(pattern: pattern)
end
end
end
1 change: 1 addition & 0 deletions app/views/spree/admin/homepage_section/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<% end %>

<% content_for :page_actions do %>
<%= button_link_to Spree.t(:clear_cache), admin_invalidate_api_caches_path(model: SpreeCmCommissioner::HomepageSection.name), method: :post, class: "btn btn-outline-primary" %>
<%= button_link_to Spree.t(:new_homepage_section), new_admin_homepage_feed_homepage_section_path, { class: "btn-success", icon: 'add.svg', id: 'admin_new_homepage_section' } %>
<% end %>

Expand Down
8 changes: 7 additions & 1 deletion config/routes.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
Spree::Core::Engine.add_routes do
# Add your extension routes here
namespace :admin do
post '/invalidate_api_caches', to: 'base#invalidate_api_caches'

resources :promotions do
resources :custom_dates_rules, controller: :promotion_custom_dates_rules, only: %i[edit update] do
member do
Expand Down Expand Up @@ -436,7 +438,11 @@
resources :event_qrs, only: [:show]

resources :homepage, only: [] do
resources :homepage_sections, only: [:index]
resources :homepage_sections, only: [:index] do
collection do
post :invalidate_api_cache
end
end
resource :homepage_background, controller: :homepage_background, only: [:show]
end

Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
require 'spec_helper'

RSpec.describe SpreeCmCommissioner::InvalidateCacheRequest do
before do
ENV['AWS_REGION'] = 'ap-southeast-1'
ENV['AWS_ACCESS_KEY_ID'] = 'AXXXXXXXXXXXXXXXY'
ENV['AWS_SECRET_ACCESS_KEY'] = 'VO103FAKEFAKEFAKE3020X=I230x1'
ENV['ASSETS_SYNC_CF_DIST_ID'] = 'D12FAKEFAKE'
end

describe '.call', :vcr do
it 'requested to invalidate cache & return response' do
context = described_class.call(pattern: '/staging/422.html')

expect(context.response.location).to eq "https://cloudfront.amazonaws.com/2020-05-31/distribution/D12FAKEFAKE/invalidation/I2PGO1F2LAWEKXXYAKMN0P38N1"
expect(context.response.invalidation.id).to eq "I2PGO1F2LAWEKXXYAKMN0P38N1"
expect(context.response.invalidation.status).to eq "InProgress"
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
require 'spec_helper'

RSpec.describe SpreeCmCommissioner::InvalidateCacheRequestJob do
describe '#perform' do
it 'invokes StateUpdater.call' do
expect(SpreeCmCommissioner::InvalidateCacheRequest).to receive(:call).with(pattern: '/api/storefront/*')
described_class.new.perform('/api/storefront/*')
end
end
end

0 comments on commit 12ffaf0

Please sign in to comment.