Skip to content

Commit

Permalink
Timeout long-running operations.
Browse files Browse the repository at this point in the history
  • Loading branch information
airblade committed Aug 18, 2010
1 parent 255af6f commit 457d73e
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 30 deletions.
3 changes: 2 additions & 1 deletion config/sample.yml
Expand Up @@ -15,4 +15,5 @@ s3:
# S3 credentials
access_key_id: XXXXXXXXXXXXXXX
secret_access_key: XXXXXXXXXXXXXXXXXXXXXX

timeout: 30

69 changes: 43 additions & 26 deletions lib/mysql_s3_backup/backup.rb
@@ -1,61 +1,78 @@
require 'tempfile'
require 'lockfile'
require 'terminator'

module MysqlS3Backup
class Backup
attr_reader :mysql, :bucket
attr_reader :mysql, :bucket, :timeout

def initialize(mysql, bucket)
def initialize(mysql, bucket, timeout=30)
@mysql = mysql
@bucket = bucket
@timeout = timeout
@bin_log_prefix = "#{@mysql.database}/bin_logs"
end

def full(name=make_new_name)
lock do
# When the full backup runs it delete any binary log files that might already exist
# in the bucket. Otherwise the restore will try to restore them even though they’re
# older than the full backup.
@bucket.delete_all @bin_log_prefix

with_temp_file do |file|
@mysql.dump(file)
@bucket.store(dump_file_name(name), file)
@bucket.copy(dump_file_name(name), dump_file_name("latest"))
timeout do
# When the full backup runs it delete any binary log files that might already exist
# in the bucket. Otherwise the restore will try to restore them even though they’re
# older than the full backup.
@bucket.delete_all @bin_log_prefix

with_temp_file do |file|
@mysql.dump(file)
@bucket.store(dump_file_name(name), file)
@bucket.copy(dump_file_name(name), dump_file_name("latest"))
end
end
end
end

def incremental
lock do
@mysql.each_bin_log do |log|
@bucket.store "#{@bin_log_prefix}/#{File.basename(log)}", log
timeout do
@mysql.each_bin_log do |log|
@bucket.store "#{@bin_log_prefix}/#{File.basename(log)}", log
end
end
end
end
alias :inc :incremental

def restore(name="latest")
lock do
# restore from the dump file
with_temp_file do |file|
@bucket.fetch(dump_file_name(name), file)
@mysql.restore(file)
end

if name == "latest"
# Restoring binary log files
@bucket.find("#{@bin_log_prefix}/").sort.each do |log|
with_temp_file do |file|
@bucket.fetch log, file
@mysql.apply_bin_log file
timeout do
# restore from the dump file
with_temp_file do |file|
@bucket.fetch(dump_file_name(name), file)
@mysql.restore(file)
end

if name == "latest"
# Restoring binary log files
@bucket.find("#{@bin_log_prefix}/").sort.each do |log|
with_temp_file do |file|
@bucket.fetch log, file
@mysql.apply_bin_log file
end
end
end
end
end
end

private

def timeout
result = nil
Terminator.terminate @timeout do
result = yield
end
result
end

def lock
result = nil
Lockfile("mysql_s3_backup_lock", :retries => 0) do
Expand All @@ -81,4 +98,4 @@ def with_temp_file
dump_file.close!
end
end
end
end
5 changes: 3 additions & 2 deletions lib/mysql_s3_backup/config.rb
Expand Up @@ -9,6 +9,7 @@ def initialize(config)
@mysql_config = config[:mysql].symbolize_keys
@s3_config = config[:s3].symbolize_keys
@bucket = @s3_config.delete(:bucket)
@timeout = @s3_config.delete(:timeout)
end

def mysql
Expand All @@ -20,11 +21,11 @@ def bucket
end

def backup
MysqlS3Backup::Backup.new(mysql, bucket)
MysqlS3Backup::Backup.new(mysql, bucket, @timeout)
end

def self.from_yaml_file(file)
new YAML.load_file(file)
end
end
end
end
3 changes: 2 additions & 1 deletion mysql_s3_backup.gemspec
@@ -1,6 +1,6 @@
Gem::Specification.new do |s|
s.name = "airblade-mysql_s3_backup"
s.version = "0.0.2"
s.version = "0.0.3"

s.authors = ["Marc-Andre Cournoyer", "Andrew Stewart"]
s.email = "boss@airbladesoftware.com"
Expand All @@ -14,4 +14,5 @@ Gem::Specification.new do |s|

s.add_dependency "aws-s3"
s.add_dependency "lockfile"
s.add_dependency "terminator"
end

0 comments on commit 457d73e

Please sign in to comment.