After successful Capistrano update (cap deploy) if we use Memcached - we should clear it. How can we do it without root access to the server? There are two ways to clear memcached without restarting it:
- Memcached command: flush_all
- Rails.cache.clear
One flush to rule them all - flush_all
If we have a dedicated server with one application on it - we can clear whole memcached memory, to do so, we create a rake task (/lib/tasks/memcached.rake):
require 'socket'
namespace :memcached do
desc 'Flushes whole memcached local instance'
task :flush do
server = '127.0.0.1'
port = 11211
command = "flush_all\r\n"
socket = TCPSocket.new(server, port)
socket.write(command)
result = socket.recv(2)
if result != 'OK'
STDERR.puts "Error flushing memcached: #{result}"
end
socket.close
end
end
Usage:
bundle exec rake memcached:flush
It is worth mentioning, that this task doesn't require the Rails environment to be loaded. If it goes about the server address and port - you can always modify it so it will accept the env settings instead of hardcoding it.
Be aware, that this command will clear out all the data that is stored in Memcached instance, even the data that was used by other applications (other than our). If you want to clear out data used by one of many apps that are using same Memcached server, see the solution presented below.
Clearing single Rails app memcached data - Rails.cache.clear
Apart from flushing all the data that is in Memcached, we can always clear only the Rails cache by creating a really simple rake task (/lib/tasks/memcached.rake):
namespace :memcached do
desc 'Clears the Rails cache'
task :flush => :environment do
Rails.cache.clear
end
end
The execution process is exactly like in the previous case:
bundle exec rake memcached:flush
In this Rake task we do load the Rails environment (because we want to use Rails.cache instance). In multi application environment, this Memcached cleaning method seems way better because we work with our application scope only.
Capistrano task for clearing Memcached
So we have our rake task, but it would mean nothing without a Capistrano hookup:
namespace :memcached do
desc "Flushes memcached local instance"
task :flush, :roles => [:app] do
run("cd #{current_path} && rake memcached:flush")
end
end
Now we can use it like this:
bundle exec cap memcached:flush
Or we can hookup it to update process:
after 'deploy:update' do
memcached.flush
end