resque-ar-failover 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ZTc0MjhmMTZiZTQxODZiMWVhMzZjNGI2ZTk3NTc5Nzc0ZjAwMmE2Yw==
5
+ data.tar.gz: !binary |-
6
+ YzBkN2FlNDdlODBiYWNjNmMyN2NjNTQzMTEzMjFiNjQzM2Q2ODFhOA==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ NWM1NDc2ZWVlYjU4MmE3NWQzZWZiYWFiZjk4NDRhMWY3YzlmNWNmNDJiM2Uw
10
+ OWJiODk0NWI3NzUzZTFkNTY2ODRlMDEyNmUxN2JhMTU3N2Y2ZTBlNWIzYzY3
11
+ N2RhM2ZmMGE5MzgxZTcxZTEwZDFkNmVjNzQ2YTRjZjBjOWM2YmQ=
12
+ data.tar.gz: !binary |-
13
+ OGE3YWQ4MmNhNDg3NjM1ZmJhNjA1ZjM3ZjFkNDA0ZWI2NWNlNDkyNjdmMjkw
14
+ M2JmOGE4Yjk4NGIxNzYxYjcyZjBiNGUwNmMyYTE2M2U1NmZiODVkN2JjOWE2
15
+ ZWMwMjczNjdmMzJiODFiMDFkMGI4OGQyYWM3OTE2YWE0MDZmZDE=
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ spec/database.sqlite3
2
+ spec/dump.rdb
3
+ Gemfile.lock
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source 'http://rubygems.org'
2
+ gemspec
3
+
4
+ group :development do
5
+ gem 'debugger'
6
+ end
7
+
8
+ group :test do
9
+ gem "rake"
10
+ end
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Hotel Tonight Inc.
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,42 @@
1
+ <img src="https://raw.github.com/hoteltonight/HTDelegateProxy/master/ht-logo-black.png" alt="HotelTonight" title="HotelTonight" style="display:block; margin: 10px auto 30px auto;">
2
+
3
+ # resque-ar-failover
4
+
5
+ Resque plugin to fail over to ActiveRecord backend for Resque job storage, when Redis is unavailable.
6
+
7
+ ## Background
8
+
9
+ At HotelTonight we use Redis. We love it. We also love Resque. But every once in a while,
10
+ Redis goes away for a split second, causing issues in our app and making some jobs to
11
+ fall through the cracks.
12
+
13
+ ## resque-ar-failover
14
+
15
+ Resque-ar-failover deals with this issue by rescueing the exceptions that signal that `Resque.enqueue` has failed
16
+ before being able to contact redis. When that happens, we persist the job to our MySQL backend (which is HA ready).
17
+
18
+ We use MySQL; you don't have to. Any AR adapter will do.
19
+
20
+ ## Installation
21
+
22
+ Resque-AR-failover is distributed as a gem. Just drop it in your `Gemfile`
23
+
24
+ ```
25
+ gem 'resque-ar-failover'
26
+ ```
27
+
28
+ Then make sure you add [this migration][migration] to your project or run the following command to create the migration automatically.
29
+
30
+ ```
31
+ rails generate resque_ar_failover install
32
+ rake db:migrate
33
+ ```
34
+
35
+ And that's it! If redis goes down a new `ResqueBackup` entry will be added and it will automatically be picked up by your resque workers.
36
+
37
+ ## License
38
+
39
+ Check out the [LICENSE][license] file.
40
+
41
+ [migration]: https://github.com/hoteltonight/resque-ar-failover/blob/master/lib/generators/templates/migration.rb
42
+ [license]: https://github.com/hoteltonight/resque-ar-failover/blob/master/LICENSE
data/Rakefile ADDED
@@ -0,0 +1,33 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+
4
+ require 'active_record'
5
+ require 'yaml'
6
+
7
+ namespace :db do
8
+ desc "Migrate the db"
9
+ task :migrate do
10
+ connection_details = YAML::load(File.open('spec/database.yml'))
11
+ ActiveRecord::Base.establish_connection(connection_details)
12
+ ActiveRecord::Migrator.migrate("db/migrate/")
13
+ end
14
+ end
15
+
16
+ task :load_path do
17
+ %w(lib).each do |path|
18
+ $LOAD_PATH.unshift(File.expand_path("../#{path}", __FILE__))
19
+ end
20
+ end
21
+
22
+ task gem: :build
23
+ task :build do
24
+ system "gem build resque-ar-failover.gemspec"
25
+ end
26
+
27
+ task release: :build do
28
+ version = Resque::Plugins::ArFailover::VERSION
29
+ system "git tag -a v#{version} -m 'Tagging #{version}'"
30
+ system "git push --tags"
31
+ system "gem push resque-ar-failover-#{version}.gem"
32
+ system "rm resque-ar-failover-#{version}.gem"
33
+ end
@@ -0,0 +1,18 @@
1
+ require 'rails/generators'
2
+ require "rails/generators/active_record"
3
+
4
+ class ResqueArFailoverGenerator < ActiveRecord::Generators::Base
5
+ include Rails::Generators::Migration
6
+
7
+ source_root File.expand_path('../', __FILE__)
8
+
9
+ desc <<DESC
10
+ Description:
11
+ Copies over migrations for the resque AR failover.
12
+ DESC
13
+
14
+ # Copies the migration template to db/migrate.
15
+ def copy_migration
16
+ migration_template 'templates/migration.rb', 'db/migrate/create_resque_backup.rb'
17
+ end
18
+ end
@@ -0,0 +1,15 @@
1
+ class CreateResqueBackup < ActiveRecord::Migration
2
+ def up
3
+ create_table :resque_backups do |t|
4
+ t.column :queue, :string
5
+ t.column :klass, :string
6
+ t.column :payload, :string
7
+ end
8
+
9
+ add_index :resque_backups, :queue
10
+ end
11
+
12
+ def down
13
+ remove_table :resque_backups
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ require 'rubygems'
2
+ require 'resque'
3
+ require "active_record"
4
+ require 'resque-ar-failover/resque_backup'
5
+ require 'resque-ext/enqueue'
6
+ require 'resque-ext/size'
7
+ require 'resque-ext/pop'
8
+
9
+ module Resque
10
+ module Plugins
11
+ module ArFailover
12
+ THROTTLE = 1.0
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,14 @@
1
+ class ResqueBackup < ActiveRecord::Base
2
+ def self.pop(queue)
3
+ 3.times do
4
+ @job = where(queue: queue).first
5
+ break if !@job || delete_all(id: @job.id) == 1
6
+ end
7
+
8
+ @job.as_job if @job
9
+ end
10
+
11
+ def as_job
12
+ { "class" => klass, "args" => payload }
13
+ end
14
+ end
@@ -0,0 +1,7 @@
1
+ module Resque
2
+ module Plugins
3
+ module ArFailover
4
+ VERSION = '1.0.0'
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,12 @@
1
+ module Resque
2
+ def self.enqueue_to_with_failover(queue, klass, *args)
3
+ self.enqueue_to_without_failover queue, klass, *args
4
+ rescue Redis::CannotConnectError, Redis::TimeoutError
5
+ ResqueBackup.create!(queue: queue, klass: klass, payload: args.to_json)
6
+ end
7
+
8
+ class << self
9
+ alias_method :enqueue_to_without_failover, :enqueue_to
10
+ alias_method :enqueue_to, :enqueue_to_with_failover
11
+ end
12
+ end
@@ -0,0 +1,15 @@
1
+ module Resque
2
+ def self.pop_with_failover(queue)
3
+ should_check_backup = (rand <= Resque::Plugins::ArFailover::THROTTLE)
4
+
5
+ job = ResqueBackup.pop(queue) if should_check_backup
6
+ job || self.pop_without_failover(queue)
7
+ rescue Redis::CannotConnectError, Redis::TimeoutError
8
+ ResqueBackup.pop(queue) unless should_check_backup
9
+ end
10
+
11
+ class << self
12
+ alias_method :pop_without_failover, :pop
13
+ alias_method :pop, :pop_with_failover
14
+ end
15
+ end
@@ -0,0 +1,16 @@
1
+ module Resque
2
+ def self.size_with_failover(queue)
3
+ size_in_redis = begin
4
+ self.size_without_failover(:queue)
5
+ rescue Redis::CannotConnectError, Redis::TimeoutError
6
+ 0
7
+ end
8
+
9
+ size_in_redis + ResqueBackup.where(queue: queue).count
10
+ end
11
+
12
+ class << self
13
+ alias_method :size_without_failover, :size
14
+ alias_method :size, :size_with_failover
15
+ end
16
+ end
@@ -0,0 +1,28 @@
1
+ lib = File.expand_path('../lib/', __FILE__)
2
+ $:.unshift lib unless $:.include?(lib)
3
+
4
+ require 'resque-ar-failover/version'
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = 'resque-ar-failover'
8
+ s.version = Resque::Plugins::ArFailover::VERSION
9
+ s.platform = Gem::Platform::RUBY
10
+ s.authors = ['Pablo Fernandez']
11
+ s.email = ['heelhook@littleq.net']
12
+ s.homepage = 'http://github.com/hoteltonight/resque-ar-failover'
13
+ s.summary = 'Resque plugin to fail over to ActiveRecord backend for Resque job storage, when Redis is unavailable.'
14
+ s.has_rdoc = false
15
+
16
+ s.rubyforge_project = 'resque-ar-failover'
17
+
18
+ s.add_dependency 'resque', '~>1.0'
19
+ s.add_dependency 'activerecord', '~>3.2'
20
+ s.add_development_dependency 'rake'
21
+ s.add_development_dependency 'rspec'
22
+ s.add_development_dependency 'sqlite3'
23
+ s.add_development_dependency 'debugger'
24
+
25
+ s.files = `git ls-files`.split("\n")
26
+ s.test_files = `git ls-files -- spec/*`.split("\n")
27
+ s.require_paths = ["lib"]
28
+ end
@@ -0,0 +1,102 @@
1
+ require 'spec_helper'
2
+
3
+ class JobOnQueue
4
+ @queue = :queue
5
+
6
+ def self.perform(id=nil)
7
+ puts "Processing job #{id}" if id
8
+ end
9
+ end
10
+
11
+ describe 'Resque' do
12
+ let (:worker) { Resque::Worker.new(:queue) }
13
+
14
+ before :each do
15
+ make_redis_available
16
+ cleanup
17
+ end
18
+
19
+ context 'when redis is accessible' do
20
+ before do
21
+ start_redis
22
+ cleanup
23
+ end
24
+
25
+ describe '.enqueue' do
26
+ it 'enqueues successfully' do
27
+ expect { Resque.enqueue(JobOnQueue) }.to change { Resque.size(:queue) }.by(1)
28
+ end
29
+ end
30
+
31
+ describe '.pop' do
32
+ it 'pops queued items from redis' do
33
+ 2.times { Resque.enqueue(JobOnQueue) }
34
+ expect { Resque.pop(:queue) }.to change { Resque.size_without_failover(:queue) }.from(2).to(1)
35
+ end
36
+ end
37
+ end
38
+
39
+ context 'when redis is inaccessible' do
40
+ before do
41
+ ensure_redis_is_dead
42
+ end
43
+
44
+ describe '.enqueue' do
45
+ it 'enqueues successfully' do
46
+ expect { Resque.enqueue(JobOnQueue) }.to change { Resque.size(:queue) }.by(1)
47
+ end
48
+ end
49
+
50
+ describe '.pop' do
51
+ it 'pops queued items from redis' do
52
+ 2.times { Resque.enqueue(JobOnQueue) }
53
+ expect { Resque.pop(:queue) }.to change { Resque.size(:queue) }.from(2).to(1)
54
+ end
55
+ end
56
+ end
57
+
58
+ context 'when redis is unresponsive' do
59
+ before do
60
+ make_redis_unavailable
61
+ end
62
+
63
+ describe '.enqueue' do
64
+ it 'enqueues successfully' do
65
+ expect { Resque.enqueue(JobOnQueue) }.to change { Resque.size(:queue) }.by(1)
66
+ end
67
+ end
68
+
69
+ describe '.pop' do
70
+ end
71
+ end
72
+
73
+ it 'handles jobs that are in redis and the AR backend' do
74
+ ensure_redis_is_running
75
+ cleanup
76
+ Resque.enqueue(JobOnQueue, 'one')
77
+ make_redis_unavailable
78
+ Resque.enqueue(JobOnQueue, 'two')
79
+ make_redis_available
80
+ Resque.size(:queue).should == 2
81
+
82
+ job = Resque.pop(:queue)
83
+ job['args'].should include 'two'
84
+ Resque.size(:queue).should == 1
85
+
86
+ job = Resque.pop(:queue)
87
+ job['args'].should include 'one'
88
+ Resque.size(:queue).should == 0
89
+
90
+ Resque.pop(:queue).should be_nil
91
+ end
92
+ end
93
+
94
+ describe 'ResqueBackup' do
95
+ describe '#as_job' do
96
+ let(:job) { ResqueBackup.new(queue: 'queue', klass: 'MyClass', payload: ['one', 'two', 'three'])}
97
+
98
+ it 'converts an AR model into a Resque structure' do
99
+ job.as_job.should == { 'class' => 'MyClass', 'args' => %w(one two three) }
100
+ end
101
+ end
102
+ end
data/spec/database.yml ADDED
@@ -0,0 +1,2 @@
1
+ adapter: sqlite3
2
+ database: spec/database.sqlite3
@@ -0,0 +1,111 @@
1
+ # Redis configuration file example
2
+
3
+ # By default Redis does not run as a daemon. Use 'yes' if you need it.
4
+ # Note that Redis will write a pid file in /var/run/redis.pid when daemonized.
5
+ daemonize yes
6
+
7
+ # When run as a daemon, Redis write a pid file in /var/run/redis.pid by default.
8
+ # You can specify a custom pid file location here.
9
+ pidfile ./spec/redis-test.pid
10
+
11
+ # Accept connections on the specified port, default is 6379
12
+ port 9736
13
+
14
+ # If you want you can bind a single interface, if the bind option is not
15
+ # specified all the interfaces will listen for connections.
16
+ #
17
+ # bind 127.0.0.1
18
+
19
+ # Close the connection after a client is idle for N seconds (0 to disable)
20
+ timeout 300
21
+
22
+ # Save the DB on disk:
23
+ #
24
+ # save <seconds> <changes>
25
+ #
26
+ # Will save the DB if both the given number of seconds and the given
27
+ # number of write operations against the DB occurred.
28
+ #
29
+ # In the example below the behaviour will be to save:
30
+ # after 900 sec (15 min) if at least 1 key changed
31
+ # after 300 sec (5 min) if at least 10 keys changed
32
+ # after 60 sec if at least 10000 keys changed
33
+ save 900 1
34
+ save 300 10
35
+ save 60 10000
36
+
37
+ # The filename where to dump the DB
38
+ dbfilename dump.rdb
39
+
40
+ # For default save/load DB in/from the working directory
41
+ # Note that you must specify a directory not a file name.
42
+ dir ./spec/
43
+
44
+ # Set server verbosity to 'debug'
45
+ # it can be one of:
46
+ # debug (a lot of information, useful for development/testing)
47
+ # notice (moderately verbose, what you want in production probably)
48
+ # warning (only very important / critical messages are logged)
49
+ loglevel debug
50
+
51
+ # Specify the log file name. Also 'stdout' can be used to force
52
+ # the demon to log on the standard output. Note that if you use standard
53
+ # output for logging but daemonize, logs will be sent to /dev/null
54
+ logfile stdout
55
+
56
+ # Set the number of databases. The default database is DB 0, you can select
57
+ # a different one on a per-connection basis using SELECT <dbid> where
58
+ # dbid is a number between 0 and 'databases'-1
59
+ databases 16
60
+
61
+ ################################# REPLICATION #################################
62
+
63
+ # Master-Slave replication. Use slaveof to make a Redis instance a copy of
64
+ # another Redis server. Note that the configuration is local to the slave
65
+ # so for example it is possible to configure the slave to save the DB with a
66
+ # different interval, or to listen to another port, and so on.
67
+
68
+ # slaveof <masterip> <masterport>
69
+
70
+ ################################## SECURITY ###################################
71
+
72
+ # Require clients to issue AUTH <PASSWORD> before processing any other
73
+ # commands. This might be useful in environments in which you do not trust
74
+ # others with access to the host running redis-server.
75
+ #
76
+ # This should stay commented out for backward compatibility and because most
77
+ # people do not need auth (e.g. they run their own servers).
78
+
79
+ # requirepass foobared
80
+
81
+ ################################### LIMITS ####################################
82
+
83
+ # Set the max number of connected clients at the same time. By default there
84
+ # is no limit, and it's up to the number of file descriptors the Redis process
85
+ # is able to open. The special value '0' means no limts.
86
+ # Once the limit is reached Redis will close all the new connections sending
87
+ # an error 'max number of clients reached'.
88
+
89
+ # maxclients 128
90
+
91
+ # Don't use more memory than the specified amount of bytes.
92
+ # When the memory limit is reached Redis will try to remove keys with an
93
+ # EXPIRE set. It will try to start freeing keys that are going to expire
94
+ # in little time and preserve keys with a longer time to live.
95
+ # Redis will also try to remove objects from free lists if possible.
96
+ #
97
+ # If all this fails, Redis will start to reply with errors to commands
98
+ # that will use more memory, like SET, LPUSH, and so on, and will continue
99
+ # to reply to most read-only commands like GET.
100
+ #
101
+ # WARNING: maxmemory can be a good idea mainly if you want to use Redis as a
102
+ # 'state' server or cache, not as a real DB. When Redis is used as a real
103
+ # database the memory usage will grow over the weeks, it will be obvious if
104
+ # it is going to use too much memory in the long run, and you'll have the time
105
+ # to upgrade. With maxmemory after the limit is reached you'll start to get
106
+ # errors for write operations, and this may even lead to DB inconsistency.
107
+
108
+ # maxmemory <bytes>
109
+
110
+ ############################### ADVANCED CONFIG ###############################
111
+
@@ -0,0 +1,72 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'rspec'
4
+
5
+ require 'ruby-debug'
6
+ require 'resque'
7
+ require 'resque-ar-failover'
8
+
9
+ Bundler.require(:default, :test)
10
+
11
+ $TESTING = true
12
+
13
+ RSpec.configure do |config|
14
+ config.before(:suite) do
15
+ $redis_path = `which redis-server`.chomp
16
+ if $redis_path.empty?
17
+ abort "redis-server couldn't be found on your system. Check that redis is installed and available in your $PATH"
18
+ end
19
+
20
+ $base_path = File.dirname(File.expand_path(__FILE__))
21
+
22
+ Resque.redis = 'localhost:9736'
23
+
24
+ connection_details = YAML::load(File.open(File.join($base_path, 'database.yml')))
25
+ ActiveRecord::Base.establish_connection(connection_details)
26
+ end
27
+
28
+ config.after(:suite) do
29
+ kill_redis
30
+ end
31
+ end
32
+
33
+ def start_redis
34
+ system("#{$redis_path} #{File.join($base_path, 'redis-test.conf')}") or abort 'Unable to starte redis'
35
+ end
36
+
37
+ def cleanup
38
+ ResqueBackup.delete_all
39
+ Resque.redis.flushall if is_redis_alive?
40
+ end
41
+
42
+ def ensure_redis_is_running
43
+ return if is_redis_alive?
44
+
45
+ start_redis
46
+ end
47
+
48
+ def ensure_redis_is_dead
49
+ while is_redis_alive? do
50
+ kill_redis
51
+ end
52
+ end
53
+
54
+ def make_redis_unavailable
55
+ Resque.redis = 'google.com:9736'
56
+ end
57
+
58
+ def make_redis_available
59
+ Resque.redis = 'localhost:9736'
60
+ end
61
+
62
+ def redis_pid
63
+ pid = `ps -e -o pid,command | grep [r]edis-test`.split(" ")[0].to_i
64
+ end
65
+
66
+ def kill_redis(signal='KILL')
67
+ Process.kill(signal, redis_pid) if is_redis_alive?
68
+ end
69
+
70
+ def is_redis_alive?
71
+ redis_pid != 0
72
+ end
metadata ADDED
@@ -0,0 +1,151 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: resque-ar-failover
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Pablo Fernandez
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-10-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: resque
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activerecord
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '3.2'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '3.2'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: sqlite3
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ! '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ! '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: debugger
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ! '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ! '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description:
98
+ email:
99
+ - heelhook@littleq.net
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - .gitignore
105
+ - .rspec
106
+ - Gemfile
107
+ - LICENSE
108
+ - README.md
109
+ - Rakefile
110
+ - lib/generators/resque_ar_failover_generator.rb
111
+ - lib/generators/templates/migration.rb
112
+ - lib/resque-ar-failover.rb
113
+ - lib/resque-ar-failover/resque_backup.rb
114
+ - lib/resque-ar-failover/version.rb
115
+ - lib/resque-ext/enqueue.rb
116
+ - lib/resque-ext/pop.rb
117
+ - lib/resque-ext/size.rb
118
+ - resque-ar-failover.gemspec
119
+ - spec/ar-failover_spec.rb
120
+ - spec/database.yml
121
+ - spec/redis-test.conf
122
+ - spec/spec_helper.rb
123
+ homepage: http://github.com/hoteltonight/resque-ar-failover
124
+ licenses: []
125
+ metadata: {}
126
+ post_install_message:
127
+ rdoc_options: []
128
+ require_paths:
129
+ - lib
130
+ required_ruby_version: !ruby/object:Gem::Requirement
131
+ requirements:
132
+ - - ! '>='
133
+ - !ruby/object:Gem::Version
134
+ version: '0'
135
+ required_rubygems_version: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ! '>='
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
140
+ requirements: []
141
+ rubyforge_project: resque-ar-failover
142
+ rubygems_version: 2.0.4
143
+ signing_key:
144
+ specification_version: 4
145
+ summary: Resque plugin to fail over to ActiveRecord backend for Resque job storage,
146
+ when Redis is unavailable.
147
+ test_files:
148
+ - spec/ar-failover_spec.rb
149
+ - spec/database.yml
150
+ - spec/redis-test.conf
151
+ - spec/spec_helper.rb