lib/backup/database/redis.rb in backup-3.11.0 vs lib/backup/database/redis.rb in backup-4.0.0rc1

- old
+ new

@@ -3,74 +3,125 @@ module Backup module Database class Redis < Base class Error < Backup::Error; end + MODES = [:copy, :sync] + ## - # Name of the redis dump file. + # Mode of operation. # - # This is set in `redis.conf` as `dbfilename`. - # This must be set to the name of that file without the `.rdb` extension. - # Default: 'dump' - attr_accessor :name + # [:copy] + # Copies the redis dump file specified by {#rdb_path}. + # This data will be current as of the last RDB Snapshot + # performed by the server (per your redis.conf settings). + # You may set {#invoke_save} to +true+ to have Backup issue + # a +SAVE+ command to update the dump file with the current + # data before performing the copy. + # + # [:sync] + # Performs a dump of your redis data using +redis-cli --rdb -+. + # Redis implements this internally using a +SYNC+ command. + # The operation is analogous to requesting a +BGSAVE+, then having the + # dump returned. This mode is capable of dumping data from a local or + # remote server. Requires Redis v2.6 or better. + # + # Defaults to +:copy+. + attr_accessor :mode ## - # Path to the redis dump file. + # Full path to the redis dump file. # - # This is set in `redis.conf` as `dir`. - attr_accessor :path + # Required when {#mode} is +:copy+. + attr_accessor :rdb_path ## - # Password for the redis-cli utility to perform the `SAVE` command - # if +invoke_save+ is set `true`. - attr_accessor :password + # Perform a +SAVE+ command using the +redis-cli+ utility + # before copying the dump file specified by {#rdb_path}. + # + # Only valid when {#mode} is +:copy+. + attr_accessor :invoke_save ## - # Connectivity options for the +invoke_save+ option. + # Connectivity options for the +redis-cli+ utility. attr_accessor :host, :port, :socket ## - # Determines whether Backup should invoke the `SAVE` command through - # the `redis-cli` utility to persist the most recent data before - # copying the dump file specified by +path+ and +name+. - attr_accessor :invoke_save + # Password for the +redis-cli+ utility. + attr_accessor :password ## - # Additional "redis-cli" options + # Additional options for the +redis-cli+ utility. attr_accessor :additional_options def initialize(model, database_id = nil, &block) super instance_eval(&block) if block_given? - @name ||= 'dump' + @mode ||= :copy + + unless MODES.include?(mode) + raise Error, "'#{ mode }' is not a valid mode" + end + + if mode == :copy && rdb_path.nil? + raise Error, '`rdb_path` must be set when `mode` is :copy' + end end ## - # Copies and optionally compresses the Redis dump file to the - # +dump_path+ using the +dump_filename+. + # Performs the dump based on {#mode} and stores the Redis dump file + # to the +dump_path+ using the +dump_filename+. # # <trigger>/databases/Redis[-<database_id>].rdb[.gz] - # - # If +invoke_save+ is true, `redis-cli SAVE` will be invoked. def perform! super - invoke_save! if invoke_save - copy! + case mode + when :sync + # messages output by `redis-cli --rdb` on $stderr + Logger.configure do + ignore_warning(/Transfer finished with success/) + ignore_warning(/SYNC sent to master/) + end + sync! + when :copy + save! if invoke_save + copy! + end log!(:finished) end private - def invoke_save! - resp = run(redis_save_cmd) + def sync! + pipeline = Pipeline.new + dump_ext = 'rdb' + + pipeline << "#{ redis_cli_cmd } --rdb -" + + model.compressor.compress_with do |command, ext| + pipeline << command + dump_ext << ext + end if model.compressor + + pipeline << "#{ utility(:cat) } > " + + "'#{ File.join(dump_path, dump_filename) }.#{ dump_ext }'" + + pipeline.run + + unless pipeline.success? + raise Error, "Dump Failed!\n" + pipeline.error_messages + end + end + + def save! + resp = run("#{ redis_cli_cmd } SAVE") unless resp =~ /OK$/ raise Error, <<-EOS - Could not invoke the Redis SAVE command. - Command was: #{ redis_save_cmd } + Failed to invoke the `SAVE` command Response was: #{ resp } EOS end rescue Error @@ -82,31 +133,30 @@ end raise end def copy! - src_path = File.join(path, name + '.rdb') - unless File.exist?(src_path) + unless File.exist?(rdb_path) raise Error, <<-EOS Redis database dump not found - File path was #{ src_path } + `rdb_path` was '#{ rdb_path }' EOS end dst_path = File.join(dump_path, dump_filename + '.rdb') if model.compressor model.compressor.compress_with do |command, ext| - run("#{ command } -c '#{ src_path }' > '#{ dst_path + ext }'") + run("#{ command } -c '#{ rdb_path }' > '#{ dst_path + ext }'") end else - FileUtils.cp(src_path, dst_path) + FileUtils.cp(rdb_path, dst_path) end end - def redis_save_cmd + def redis_cli_cmd "#{ utility('redis-cli') } #{ password_option } " + - "#{ connectivity_options } #{ user_options } SAVE" + "#{ connectivity_options } #{ user_options }" end def password_option "-a '#{ password }'" if password end @@ -121,21 +171,9 @@ end def user_options Array(additional_options).join(' ') end - - attr_deprecate :utility_path, :version => '3.0.21', - :message => 'Use Backup::Utilities.configure instead.', - :action => lambda {|klass, val| - Utilities.configure { redis_cli val } - } - - attr_deprecate :redis_cli_utility, :version => '3.3.0', - :message => 'Use Backup::Utilities.configure instead.', - :action => lambda {|klass, val| - Utilities.configure { redis_cli val } - } end end end