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 121421e
Show file tree
Hide file tree
Showing 11 changed files with 163 additions and 0 deletions.
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
2 changes: 2 additions & 0 deletions 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

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 121421e

Please sign in to comment.