redis_failover-rails 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +45 -0
- data/Gemfile +4 -0
- data/LICENSE +21 -0
- data/README.md +100 -0
- data/Rakefile +22 -0
- data/config/initializers/passenger.rb +12 -0
- data/config/redis.yml +33 -0
- data/lib/active_support/cache/redis_cache_store.rb +167 -0
- data/lib/redis_factory.rb +113 -0
- data/lib/redis_failover-rails/version.rb +3 -0
- data/redis_failover-rails.gemspec +38 -0
- data/test/dummy/README.rdoc +28 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/images/.keep +0 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/stylesheets/application.css +15 -0
- data/test/dummy/app/controllers/application_controller.rb +5 -0
- data/test/dummy/app/controllers/concerns/.keep +0 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/mailers/.keep +0 -0
- data/test/dummy/app/models/.keep +0 -0
- data/test/dummy/app/models/concerns/.keep +0 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +26 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +37 -0
- data/test/dummy/config/environments/production.rb +83 -0
- data/test/dummy/config/environments/test.rb +45 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +4 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/routes.rb +56 -0
- data/test/dummy/config/secrets.yml +22 -0
- data/test/dummy/lib/assets/.keep +0 -0
- data/test/dummy/log/.keep +0 -0
- data/test/dummy/public/404.html +67 -0
- data/test/dummy/public/422.html +67 -0
- data/test/dummy/public/500.html +66 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/test_helper.rb +62 -0
- data/test/unit/active_support/cache/redis_cache_store_test.rb +178 -0
- data/test/unit/redis_factory_test.rb +111 -0
- metadata +301 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 477b89feb234392eeeb44fb9dabd817f590bf5db
|
4
|
+
data.tar.gz: 3ef6dff5c7175ec11c21ae7fdee9220b77c18daf
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: edb014657c027a0f07d41026a6fe837ae9bcde3461eb7d9e80774be2548b8729dfc65080d8b5bdb848697df1fcb3775f93a5e4b6f3ceabfbe1240d6895d46218
|
7
|
+
data.tar.gz: 4e43aa4f71e251fcc9e799473bd54497062ce3dea4a4cc699f21e9802b8ce70c8be63a89f5b469d93296154675a722dd64b42fc8c8f5b1aa7ce7fdb8121de53b
|
data/.gitignore
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
/.config
|
4
|
+
/coverage/
|
5
|
+
/InstalledFiles
|
6
|
+
/pkg/
|
7
|
+
/spec/reports/
|
8
|
+
/test/tmp/
|
9
|
+
/test/version_tmp/
|
10
|
+
/tmp/
|
11
|
+
Gemfile.lock
|
12
|
+
|
13
|
+
## Specific to RubyMotion:
|
14
|
+
.dat*
|
15
|
+
.repl_history
|
16
|
+
build/
|
17
|
+
|
18
|
+
## Documentation cache and generated files:
|
19
|
+
/.yardoc/
|
20
|
+
/_yardoc/
|
21
|
+
/doc/
|
22
|
+
/rdoc/
|
23
|
+
|
24
|
+
## Environment normalisation:
|
25
|
+
/.bundle/
|
26
|
+
/lib/bundler/man/
|
27
|
+
|
28
|
+
# for a library or gem, you might want to ignore these files since the code is
|
29
|
+
# intended to run in multiple environments; otherwise, check them in:
|
30
|
+
|
31
|
+
# .ruby-version
|
32
|
+
# .ruby-gemset
|
33
|
+
|
34
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
35
|
+
.rvmrc
|
36
|
+
|
37
|
+
log/*.log
|
38
|
+
test/dummy/db/*.sqlite3
|
39
|
+
test/dummy/db/*.sqlite3-journal
|
40
|
+
test/dummy/log/*.log
|
41
|
+
test/dummy/tmp/
|
42
|
+
test/dummy/.sass-cache
|
43
|
+
|
44
|
+
dump.rdb
|
45
|
+
redis.log
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2014 Surfdome Shop Limited
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
# redis_failover-rails
|
2
|
+
|
3
|
+
[ ](https://codeship.io/projects/22198)
|
4
|
+
[](https://codeclimate.com/github/surfdome/redis_failover-rails)
|
5
|
+
|
6
|
+
An ActiveSupport::Cache store using redis_failover (a zookeeper based implementation of HA redis) for Rails apps.
|
7
|
+
|
8
|
+
This is based on the work done by [@wr0ngway](https://github.com/wr0ngway) (Matt Conway), available on [redis_failover_example](https://github.com/wr0ngway/redis_failover_example).
|
9
|
+
|
10
|
+
Also, this gem utilizes redis_failover, a gem that creates a Redis HA implementation, using zookeeper for mantaining the available nodes.
|
11
|
+
This can be found on [redis_failover](https://github.com/ryanlecompte/redis_failover).
|
12
|
+
|
13
|
+
## Requirements
|
14
|
+
In order to work, this requires a working [redis_failover](https://github.com/ryanlecompte/redis_failover) implementation. Please follow the instructions on the gem and ask your favourite Sysadmin/DevOps to implement in your environment.
|
15
|
+
|
16
|
+
## Considerations
|
17
|
+
In case you don't have a redis_failover implementation working, and for helping in the development process, this also works with a single node redis server.
|
18
|
+
Just don't specify zkservers in the config file.
|
19
|
+
|
20
|
+
## Installation
|
21
|
+
|
22
|
+
Just add the dependency to your Gemfile...
|
23
|
+
|
24
|
+
# Gemfile
|
25
|
+
gem 'redis_failover-rails', github: 'surfdome/redis_failover-rails' # Not in rubygems.org, yet...
|
26
|
+
|
27
|
+
and run bundle install.
|
28
|
+
|
29
|
+
bundle install
|
30
|
+
|
31
|
+
## Usage
|
32
|
+
In your application.rb (or environment), you should use something like:
|
33
|
+
|
34
|
+
config.cache_store = :redis_cache_store, :cache
|
35
|
+
config.cache_classes = true
|
36
|
+
config.action_controller.perform_caching = true
|
37
|
+
|
38
|
+
## Testing
|
39
|
+
In order to make your tests work, you need a working redis_failover installation, with Redis, Zookeeper and Node Manager running on the ports specified in the default config file.
|
40
|
+
|
41
|
+
Also you need a single redis server running on port 6379.
|
42
|
+
|
43
|
+
For running the tests, just:
|
44
|
+
|
45
|
+
bundle exec rake
|
46
|
+
|
47
|
+
## Configuration
|
48
|
+
In order to define your redis and redis_failover configurations, you just need to use the `redis.yml` config file.
|
49
|
+
|
50
|
+
This follows a format like this:
|
51
|
+
|
52
|
+
environment:
|
53
|
+
instance:
|
54
|
+
parameter1:
|
55
|
+
parameter2:
|
56
|
+
|
57
|
+
This gem automatically selects a redis_failover client if you define `:zkservers` in the config file. If not, it just uses the standard redis client.
|
58
|
+
|
59
|
+
This are the options available if you configure a redis_failover client:
|
60
|
+
|
61
|
+
:zk - an existing ZK client instance
|
62
|
+
:zkservers - comma-separated ZooKeeper host:port pairs
|
63
|
+
:znode_path - the Znode path override for redis server list (optional)
|
64
|
+
:password - password for redis nodes (optional)
|
65
|
+
:db - db to use for redis nodes (optional)
|
66
|
+
:namespace - namespace for redis nodes (optional)
|
67
|
+
:logger - logger override (optional)
|
68
|
+
:retry_failure - indicate if failures should be retried (default true)
|
69
|
+
:max_retries - max retries for a failure (default 3)
|
70
|
+
:safe_mode - indicates if safe mode is used or not (default true)
|
71
|
+
:master_only - indicates if only redis master is used (default false)
|
72
|
+
:verify_role - verify the actual role of a redis node before every command (default true)
|
73
|
+
|
74
|
+
Typical configuration parameters for standard redis clients are:
|
75
|
+
|
76
|
+
:host - Redis server host
|
77
|
+
:port - Redis server port
|
78
|
+
:db - Redis database to use
|
79
|
+
:password - Redis connection password
|
80
|
+
|
81
|
+
Please keep in mind that this options are not validated, just passed to the client configuration.
|
82
|
+
|
83
|
+
## License
|
84
|
+
This gem is released with MIT licensing. Please see [LICENSE](https://github.com/surfdome/redis_failover-rails/blob/master/LICENSE) for details.
|
85
|
+
|
86
|
+
## Author
|
87
|
+
Initially created by Jose Pettoruti - [@jepettoruti](https://github.com/jepettoruti) for Surfdome.com
|
88
|
+
|
89
|
+
## Acknowledgements
|
90
|
+
This couldn't have been achieved without the work of [@ryanlecompte](https://github.com/ryanlecompte/) for making the amazing redis_failover gem.
|
91
|
+
|
92
|
+
Special thanks to [@wr0ngway](https://github.com/wr0ngway) for his example on how to implement this on Rubber.
|
93
|
+
|
94
|
+
## Contributing
|
95
|
+
|
96
|
+
1. Fork it
|
97
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
98
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
99
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
100
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rake'
|
8
|
+
require 'bundler/gem_tasks'
|
9
|
+
|
10
|
+
Bundler::GemHelper.install_tasks
|
11
|
+
|
12
|
+
require 'rake/testtask'
|
13
|
+
|
14
|
+
Rake::TestTask.new(:test) do |t|
|
15
|
+
t.libs << 'lib'
|
16
|
+
t.libs << 'test'
|
17
|
+
t.pattern = 'test/**/*_test.rb'
|
18
|
+
t.verbose = true
|
19
|
+
end
|
20
|
+
|
21
|
+
desc 'Default: run unit tests.'
|
22
|
+
task :default => :test
|
@@ -0,0 +1,12 @@
|
|
1
|
+
if defined?(PhusionPassenger)
|
2
|
+
PhusionPassenger.on_event(:starting_worker_process) do |forked|
|
3
|
+
if forked
|
4
|
+
# We're in smart spawning mode.
|
5
|
+
|
6
|
+
# Reset redis failover clients
|
7
|
+
RedisFactory.reconnect
|
8
|
+
else
|
9
|
+
# We're in conservative spawning mode. We don't need to do anything.
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
data/config/redis.yml
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
development:
|
2
|
+
cache:
|
3
|
+
host: localhost
|
4
|
+
port: 6380
|
5
|
+
thread_safe: true
|
6
|
+
zkservers: localhost:2181, localhost:2182, localhost:2183
|
7
|
+
znode_path: /redis_failover/nodes
|
8
|
+
db: 1
|
9
|
+
|
10
|
+
production:
|
11
|
+
cache:
|
12
|
+
thread_safe: true
|
13
|
+
zkservers: localhost:2181, localhost:2182, localhost:2183
|
14
|
+
znode_path: /redis_failover
|
15
|
+
db: 0
|
16
|
+
|
17
|
+
test:
|
18
|
+
hacache:
|
19
|
+
zkservers: localhost:2181
|
20
|
+
db: 8
|
21
|
+
thread_safe: true
|
22
|
+
myredisdb:
|
23
|
+
db: 1
|
24
|
+
host: localhost
|
25
|
+
port: 6379
|
26
|
+
thread_safe: true
|
27
|
+
cache:
|
28
|
+
db: 2
|
29
|
+
host: localhost
|
30
|
+
port: 6379
|
31
|
+
thread_safe: true
|
32
|
+
|
33
|
+
|
@@ -0,0 +1,167 @@
|
|
1
|
+
# require "backupify/logger_support"
|
2
|
+
|
3
|
+
module ActiveSupport
|
4
|
+
module Cache
|
5
|
+
|
6
|
+
class RedisCacheStore < ActiveSupport::Cache::Store
|
7
|
+
|
8
|
+
# include Backupify::LoggerSupport
|
9
|
+
|
10
|
+
# Creates a new RedisStore object, with the given redis server
|
11
|
+
# address. Each address is a valid redis url string. For example:
|
12
|
+
#
|
13
|
+
# ActiveSupport::Cache::RedisStore.new("redis://127.0.0.1:6379/0")
|
14
|
+
#
|
15
|
+
# Instead of addresses one can pass in a redis-like object. For example:
|
16
|
+
#
|
17
|
+
# require 'redis' # gem install redis; uses C bindings to libredis
|
18
|
+
# ActiveSupport::Cache::RedisStore.new(Redis.connect("localhost"))
|
19
|
+
def initialize(*connections)
|
20
|
+
options = connections.extract_options!
|
21
|
+
super(options)
|
22
|
+
|
23
|
+
raise ArgumentError, "Only a single connection must be provided" if connections.size > 1
|
24
|
+
connection = connections.first || options
|
25
|
+
|
26
|
+
if connection.respond_to?(:get)
|
27
|
+
@data = connection
|
28
|
+
elsif connection.is_a?(Symbol)
|
29
|
+
require 'redis_factory'
|
30
|
+
@data = RedisFactory.connect(connection)
|
31
|
+
else
|
32
|
+
redis_options = {}
|
33
|
+
if connection.is_a?(String)
|
34
|
+
redis_options[:url] = connection
|
35
|
+
elsif connection.is_a?(Hash)
|
36
|
+
redis_options = connection
|
37
|
+
ActiveSupport::Cache::UNIVERSAL_OPTIONS.each{|name| redis_options.delete(name)}
|
38
|
+
else
|
39
|
+
raise ArgumentError, "Need a url or hash for a redis connection"
|
40
|
+
end
|
41
|
+
|
42
|
+
@data = ::Redis.connect(redis_options)
|
43
|
+
end
|
44
|
+
|
45
|
+
extend ActiveSupport::Cache::Strategy::LocalCache
|
46
|
+
end
|
47
|
+
|
48
|
+
# Reads multiple values from the cache using a single call to the
|
49
|
+
# servers for all keys. Options can be passed in the last argument.
|
50
|
+
def read_multi(*names)
|
51
|
+
options = names.extract_options!
|
52
|
+
options = merged_options(options)
|
53
|
+
keys_to_names = Hash[names.map{|name| [namespaced_key(name, options), name]}]
|
54
|
+
raw_values = @data.mget(keys_to_names.keys)
|
55
|
+
values = {}
|
56
|
+
raw_values.each do |key, value|
|
57
|
+
entry = deserialize_entry(value)
|
58
|
+
values[keys_to_names[key]] = entry.value unless entry.expired?
|
59
|
+
end
|
60
|
+
values
|
61
|
+
end
|
62
|
+
|
63
|
+
# Delete objects for matched keys.
|
64
|
+
#
|
65
|
+
# Example:
|
66
|
+
# cache.del_matched "rab*"
|
67
|
+
def delete_matched(matcher, options = nil) # :nodoc:
|
68
|
+
options = merged_options(options)
|
69
|
+
response = instrument(:delete_matched, matcher.inspect) do
|
70
|
+
matcher = key_matcher(matcher, options)
|
71
|
+
@data.keys(matcher).each { |key| @data.del key }
|
72
|
+
end
|
73
|
+
rescue => e
|
74
|
+
logger.error("Error calling delete_matched on redis: #{e}") if logger
|
75
|
+
nil
|
76
|
+
end
|
77
|
+
|
78
|
+
# Increment a cached value. This method uses the redis incrby atomic
|
79
|
+
# operator
|
80
|
+
def increment(name, amount = 1, options = nil) # :nodoc:
|
81
|
+
options = merged_options(options)
|
82
|
+
response = instrument(:increment, name, :amount => amount) do
|
83
|
+
@data.incrby(namespaced_key(name, options), amount)
|
84
|
+
end
|
85
|
+
rescue => e
|
86
|
+
logger.error("Error incrementing cache entry in redis: #{e}") if logger
|
87
|
+
nil
|
88
|
+
end
|
89
|
+
|
90
|
+
# Decrement a cached value. This method uses the redis decrby atomic
|
91
|
+
# operator
|
92
|
+
def decrement(name, amount = 1, options = nil) # :nodoc:
|
93
|
+
options = merged_options(options)
|
94
|
+
response = instrument(:decrement, name, :amount => amount) do
|
95
|
+
@data.decrby(namespaced_key(name, options), amount)
|
96
|
+
end
|
97
|
+
rescue => e
|
98
|
+
logger.error("Error decrementing cache entry in redis: #{e}") if logger
|
99
|
+
nil
|
100
|
+
end
|
101
|
+
|
102
|
+
# Clear the entire cache on all redis servers. This method should
|
103
|
+
# be used with care when shared cache is being used.
|
104
|
+
def clear(options = nil)
|
105
|
+
@data.flushdb
|
106
|
+
end
|
107
|
+
|
108
|
+
# Get the statistics from the redis servers.
|
109
|
+
def stats
|
110
|
+
@data.info
|
111
|
+
end
|
112
|
+
|
113
|
+
protected
|
114
|
+
|
115
|
+
# Read an entry from the cache.
|
116
|
+
def read_entry(key, options) # :nodoc:
|
117
|
+
deserialize_entry(@data.get(key))
|
118
|
+
rescue => e
|
119
|
+
logger.error("Error reading cache entry from redis: #{e}") if logger
|
120
|
+
nil
|
121
|
+
end
|
122
|
+
|
123
|
+
# Write an entry to the cache.
|
124
|
+
def write_entry(key, entry, options) # :nodoc:
|
125
|
+
value = serialize_entry(entry)
|
126
|
+
if (options && options[:expires_in])
|
127
|
+
expires_in = options[:expires_in].to_i
|
128
|
+
response = @data.setex(key, expires_in, value)
|
129
|
+
else
|
130
|
+
response = @data.set(key, value)
|
131
|
+
end
|
132
|
+
rescue => e
|
133
|
+
logger.error("Error writing cache entry to redis: #{e}") if logger
|
134
|
+
false
|
135
|
+
end
|
136
|
+
|
137
|
+
# Delete an entry from the cache.
|
138
|
+
def delete_entry(key, options) # :nodoc:
|
139
|
+
response = @data.del(key)
|
140
|
+
rescue => e
|
141
|
+
logger.error("Error deleting cache entry from redis: #{e}") if logger
|
142
|
+
false
|
143
|
+
end
|
144
|
+
|
145
|
+
private
|
146
|
+
|
147
|
+
def deserialize_entry(raw_value)
|
148
|
+
if raw_value
|
149
|
+
entry = Marshal.load(raw_value) rescue raw_value
|
150
|
+
entry.is_a?(ActiveSupport::Cache::Entry) ? entry : ActiveSupport::Cache::Entry.new(entry)
|
151
|
+
else
|
152
|
+
nil
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def serialize_entry(entry)
|
157
|
+
if entry
|
158
|
+
Marshal.dump(entry)
|
159
|
+
else
|
160
|
+
nil
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
end
|
165
|
+
|
166
|
+
end
|
167
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'redis_failover'
|
2
|
+
|
3
|
+
# A factory class for creating redis connections, and reconnecting them after a fork
|
4
|
+
#
|
5
|
+
# It uses RedisFailover as the client if config/redis.yml contains a
|
6
|
+
# zkservers setting for the named connection, otherwise vanilla redis client
|
7
|
+
class RedisFactory
|
8
|
+
extend MonitorMixin
|
9
|
+
|
10
|
+
@@configuration = nil
|
11
|
+
@@clients = {}
|
12
|
+
|
13
|
+
def self.logger
|
14
|
+
Rails.logger
|
15
|
+
end
|
16
|
+
|
17
|
+
# Creates a redis client for the given named configuration
|
18
|
+
#
|
19
|
+
# @param [String] name The name of the redis configuration
|
20
|
+
# (config/redis.yml) )to use
|
21
|
+
# @return [RedisClient] A redis client object
|
22
|
+
# (may be a failover capable proxy)
|
23
|
+
def self.connect(name)
|
24
|
+
conf = configuration[name].symbolize_keys!
|
25
|
+
raise "No redis configuration for #{Rails.env} environment in redis.yml for #{name}" unless conf
|
26
|
+
synchronize do
|
27
|
+
# if conf[:zkservers]
|
28
|
+
# conf[:logger] = logger
|
29
|
+
# @@clients[name] ||= ::RedisFailover::Client.new(
|
30
|
+
# :zkservers => 'localhost:2181,localhost:2182,localhost:2183',
|
31
|
+
# :znode_path => '/redis_failover',
|
32
|
+
# :db => '1')
|
33
|
+
# else
|
34
|
+
# @@clients[name] ||= ::Redis.new()
|
35
|
+
# end
|
36
|
+
if conf[:zkservers]
|
37
|
+
conf[:logger] = logger
|
38
|
+
@@clients[name] ||= ::RedisFailover::Client.new(conf)
|
39
|
+
else
|
40
|
+
@@clients[name] ||= ::Redis.new(conf)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
@@clients[name]
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.disconnect(key = nil)
|
47
|
+
logger.debug "RedisFactory.disconnect start"
|
48
|
+
synchronize do
|
49
|
+
@@clients.clone.each do |name, client|
|
50
|
+
next if key && name != key
|
51
|
+
client = @@clients.delete(name)
|
52
|
+
if client
|
53
|
+
begin
|
54
|
+
if client.instance_of?(::RedisFailover::Client)
|
55
|
+
logger.debug "Disconnecting RedisFailover client: #{client}"
|
56
|
+
client.shutdown
|
57
|
+
elsif client.instance_of?(::Redis)
|
58
|
+
logger.debug "Disconnecting Redis client: #{client}"
|
59
|
+
client.quit
|
60
|
+
else
|
61
|
+
logger.warn("Couldn't reconnect unknown redis client type: #{client.class}")
|
62
|
+
end
|
63
|
+
rescue => e
|
64
|
+
logger.warn("Exception while disconnecting: #{e}")
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
logger.debug "RedisFactory.disconnect complete"
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.reconnect(key = nil)
|
73
|
+
logger.debug "RedisFactory.reconnect start"
|
74
|
+
synchronize do
|
75
|
+
@@clients.each do |name, client|
|
76
|
+
next if key && name != key
|
77
|
+
if client.instance_of?(::RedisFailover::Client)
|
78
|
+
logger.debug "Reconnecting RedisFailover client: #{client}"
|
79
|
+
client.reconnect
|
80
|
+
elsif client.instance_of?(::Redis)
|
81
|
+
logger.debug "Reconnecting Redis client: #{client}"
|
82
|
+
client.client.reconnect
|
83
|
+
else
|
84
|
+
logger.warn("Couldn't reconnect unknown redis client type: #{client.class}")
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
logger.debug "RedisFactory.reconnect complete"
|
89
|
+
end
|
90
|
+
|
91
|
+
def self.configuration
|
92
|
+
synchronize do
|
93
|
+
@@configuration ||= begin
|
94
|
+
require 'erb'
|
95
|
+
# config = YAML::load(ERB.new(IO.read("../config/redis.yml")).result)
|
96
|
+
config = YAML.load(ERB.new(File.read('./config/redis.yml')).result)
|
97
|
+
# self.symbolize(config[ENV['RAILS_ENV']])
|
98
|
+
config = config[ENV['RAILS_ENV']].symbolize_keys!
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
private
|
104
|
+
|
105
|
+
def self.symbolize(hash)
|
106
|
+
hash.inject({}) do |options, (key, value)|
|
107
|
+
value = self.symbolize(value) if value.kind_of?(Hash)
|
108
|
+
options[key.to_sym || key] = value
|
109
|
+
options
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|