RailsアプリをHerokuにデプロイするときにMemcachedを自動的にクリアする最良の方法は何ですか?
ホームページをキャッシュしていますが、変更を加えて再デプロイすると、ページがキャッシュから提供され、更新が組み込まれません。
これを完全に自動化したいと思います。デプロイするたびにherokuコンソールのキャッシュをクリアする必要はありません。
ありがとう!
GitHubとHerokuPush、データベースの移行、アプリケーションのメンテナンスモードのアクティブ化、キャッシュのクリアアクションを自動化するbashスクリプトを使用してアプリケーションをデプロイします。
このスクリプトでは、キャッシュをクリアするコマンドは次のとおりです。
heroku run --app YOUR_APP_NAME Rails runner -e production Rails.cache.clear
これは、HerokuToolbeltパッケージのCeladonCedarで機能します。これはRakeベースのソリューションではないことはわかっていますが、非常に効率的です。
注:environment
コマンドのrunner
/-e
オプションはproduction
で実行されるため、必ずdevelopment
に設定してください。さもないと。
編集:数日後、Herokuでこのコマンドの問題が発生しました(Rails3.2.21)。 Originの問題を確認する時間がありませんでしたが、-e production
を削除することでうまくいきました。コマンドが成功しない場合は、代わりに次のコマンドを実行してください。
heroku run --app YOUR_APP_NAME Rails runner Rails.cache.clear
[セラドンシダースタックについて]
-[2012年6月18日更新-これは機能しなくなりました。別の回避策を見つけることができるかどうかを確認します]
これらのデプロイ後のフックを処理するために私が見つけた最もクリーンな方法は、slugのコンパイル中にすでに呼び出されているassets:precompileタスクをラッチすることです。アイデアのためのasset_syncGemに賛成:
Rake::Task["assets:precompile"].enhance do
# How to invoke a task that exists elsewhere
# Rake::Task["assets:environment"].invoke if Rake::Task.task_defined?("assets:environment")
# Clear cache on deploy
print "Clearing the Rails memcached cache\n"
Rails.cache.clear
end
これをlib/tasks/heroku_deploy.rakeファイルに入れるだけで、うまくピックアップされます。
最終的に行ったのは、herokuにデプロイしてキャッシュをクリアする新しいrakeタスクを作成することでした。 deploy.rakeファイルを作成しました。これは次のとおりです。
namespace :deploy do
task :production do
puts "deploying to production"
system "git Push heroku"
puts "clearing cache"
system "heroku console Rails.cache.clear"
puts "done"
end
end
ここで、git Push herokuと入力する代わりに、rake deploy:productionと入力します。
2013年1月25日:これはRails 3.2.11 app running on Ruby 1.9.3 on Cedar
Gemfile
に次の行を追加して、Ruby 1.9.3:
Ruby '1.9.3'
次の内容でlib/tasks/clear_cache.rake
という名前のファイルを作成します。
if Rake::Task.task_defined?("assets:precompile:nondigest")
Rake::Task["assets:precompile:nondigest"].enhance do
Rails.cache.clear
end
else
Rake::Task["assets:precompile"].enhance do
# Rails 3.1.1 will clear out Rails.application.config if the env vars
# Rails_GROUP and Rails_ENV are not defined. We need to reload the
# assets environment in this case.
# Rake::Task["assets:environment"].invoke if Rake::Task.task_defined?("assets:environment")
Rails.cache.clear
end
end
最後に、アプリでheroku labs:enable user-env-compile
を実行して、プリコンパイルの一部としてその環境を利用できるようにすることもお勧めします。
'application start'で実行されるアプリケーション内で実行できることは別として、アプリケーション内のURLにヒットするherokuデプロイフック(http://devcenter.heroku.com/articles/deploy-hooks#http_post_hook)を使用できます。キャッシュをクリアします
私もこの問題を抱えていましたが、ラッパーとして追加のスクリプトを使用せずにgitデプロイメントに固執したかったのです。
したがって、私のアプローチは、スラッグの生成中に、現在のプリコンパイルをマークするuuidを使用してファイルを書き込むことです。これは、assets:precompile
のフックとして実行されます。
# /lib/tasks/store_asset_cacheversion.rake
# add uuidtools to Gemfile
require "uuidtools"
def storeCacheVersion
cacheversion = UUIDTools::UUID.random_create
File.open(".cacheversion", "w") { |file| file.write(cacheversion) }
end
Rake::Task["assets:precompile"].enhance do
puts "Storing git hash in file for cache invalidation (assets:precompile)\n"
storeCacheVersion
end
Rake::Task["assets:precompile:nondigest"].enhance do
puts "Storing git hash in file for cache invalidation (assets:precompile:nondigest)\n"
storeCacheVersion
end
もう1つは、このIDをキャッシュされたバージョンと照合する初期化子です。それらが異なる場合は、別のプリコンパイルが行われ、キャッシュが無効になります。
したがって、スラグの生成は1回だけ行われるため、アプリケーションがスピンアップまたはスピンダウンする頻度や、ワーカーが分散されるノードの数は関係ありません。
# /config/initializers/00_asset_cache_check.rb
currenthash = File.read ".cacheversion"
cachehash = Rails.cache.read "cacheversion"
puts "Checking cache version: #{cachehash} against slug version: #{currenthash}\n"
if currenthash != cachehash
puts "flushing cache\n"
Rails.cache.clear
Rails.cache.write "cacheversion", currenthash
else
puts "cache ok\n"
end
Gitハッシュやその他の有用なIDを取得する方法がわからないため、ランダムIDを使用する必要がありました。おそらくENV[REQUEST_ID]
ですが、これもランダムIDです。
Uuidの良いところは、herokuからも独立していることです。
私が使用したい解決策は次のとおりです。
まず、アプリごとに異なる設定をしたパラメーターを探すdeploy_hookアクションを実装します。通常、これは「ホーム」または「パブリック」コントローラーで実行します。これは、それほど多くのコードを必要としないためです。
### routes.rb ###
post 'deploy_hook' => 'home#deploy'
### home_controller.rb ###
def deploy_hook
Rails.cache.clear if params[:secret] == "a3ad3d3"
end
そして、デプロイするたびにそのアクションに投稿するデプロイフックをセットアップするようにherokuに指示するだけです!
heroku addons:add deployhooks:http \
--url=http://example.com/deploy_hook?secret=a3ad3d3
これで、デプロイするたびに、herokuがサイトにHTTPポストバックを実行して、デプロイが正常に機能したことを通知します。
私にとっては魅力のように機能します。もちろん、シークレットトークンは「高セキュリティ」ではなく、キャッシュがクリアされた場合にサイトをダウンさせるための適切な攻撃ベクトルがあった場合は、これを使用しないでください。ただし、正直なところ、サイトが攻撃にとって非常に重要である場合は、Herokuでホストしないでください。ただし、セキュリティを少し強化したい場合は、Heroku構成変数を使用して、ソースコードに「トークン」をまったく含めないようにすることができます。
人々がこれが役に立つと思うことを願っています。
私は追加しました config/initializers/expire_cache.rb
と
ActionController::Base.expire_page '/'
甘い作品!
Heroku gemは非推奨になっているため、Solomonsの非常にエレガントな答えの更新バージョンは、次のコードをlib/tasks/heroku_deploy.rake
に保存することです。
namespace :deploy do
task :production do
puts "deploying to production"
system "git Push heroku"
puts "clearing cache"
system "heroku run rake cache:clear"
puts "done"
end
end
namespace :cache do
desc "Clears Rails cache"
task :clear => :environment do
Rails.cache.clear
end
end
次に、コマンドラインでgit Push heroku master
の代わりにrake deploy:production
と入力します。キャッシュをクリアするには、rake cache:clear
を実行できます。