S3にjsonをあげて、取得するときはCloudFront経由にする構成を作っています。
jsonを更新/削除する際にCloudFrontのキャッシュを削除したかったのですが、余り記事が引っかからなかったので備忘までにメモしておきます。
前提
- Ruby 2.3.0
- aws-sdk 2.10.22
※ sdkのversionが1の場合は、Clientのクラスやapiのパラメータが異なりますので、こちらをご覧ください。
コード
Railsアプリケーションで削除するclassを作ったので、そのまま貼ります。
lib/clients/cloud_front.rb
module Clients
class CloudFront
include Singleton
@@instance = Aws::CloudFront::Client.new(
region: ENV['AWS_DEFAULT_REGION'],
access_key_id: ENV['AWS_ACCESS_KEY_ID'],
secret_access_key: ENV['AWS_SECRET_ACCESS_KEY']
)
# CloudFrontのInvalidationを作成する
# @see http://docs.aws.amazon.com/sdkforruby/api/Aws/CloudFront/Client.html#create_invalidation-instance_method
#
# @param [Array[String]] paths キャッシュオブジェクトのパスの配列
# @return [String] 結果のメッセージ
def self.create_invalidation(paths=[])
# 非同期のAPIをcall
ret = @@instance.create_invalidation({
distribution_id: ENV['AWS_CLOUD_FRONT_DISTRIBUTION_ID'],
invalidation_batch: {
paths: {
quantity: paths.size,
items: paths
},
# api callを同定するためのユニークな文字列
# @see http://docs.aws.amazon.com/cloudfront/latest/APIReference/API_CreateInvalidation.html#API_CreateInvalidation_RequestSyntax
caller_reference: Time.now.to_s
}
})
# invalidationの作成に成功したときは、
# レスポンスのinvalidation.statusにInProgressが入る
if ret.blank? or ret.invalidation.blank? or ret.invalidation.status != 'InProgress'
Rails.logger.warn "Fail to delete cache of #{paths.join(', ')}"
Rails.logger.warn "Response from CloudFront: #{ret.inspect}"
return 'キャッシュの削除に失敗しました。'
end
'キャッシュの削除を開始しました。しばらく待って確認してください。'
end
end
end
補足1: メソッドのレスポンスについて
invalidationのcallは元々非同期ですし、削除に失敗したからと言ってアプリケーションを止めたくなかったので、私の場合はメッセージを返してコントローラーでflashに入れるようにしています。場合によっては例外出してもいいかもしれません。
補足2: メソッドの引数について
引数経由で渡しているオブジェクトのpathですが、同じversionのS3クライアント(Aws::S3::Resource
)やWeb consoleとは異なり、冒頭の'/'が必須になるのでご注意ください。
- NG
- v1/hoge.json
- OK
- /v1/hoge.json