redis_selector 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in redis_selector/.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,79 @@
1
+ # MockRedis
2
+
3
+ A gem to make it easy to use different Redises for different things.
4
+
5
+ ## Getting Started
6
+
7
+ RedisSelector is a module that provides the `#with_redis` method.
8
+
9
+ `#with_redis` takes a string and a block, and calls the block with a
10
+ connected Redis object. The connection is closed after the block
11
+ exits.
12
+
13
+ The string is used to indicate what logical thing you're using Redis
14
+ for. This allows for easy addition of new Redis servers if your data
15
+ set starts getting too big.
16
+
17
+ Example:
18
+
19
+ class Competitor < ActiveRecord::Base
20
+ extend MockRedis
21
+
22
+ def self.top10
23
+ with_redis('leaderboards') do |redis|
24
+ redis.zrange(LEADERBOARD_KEY, 0, 9).map {|id| self.find(id)}
25
+ end
26
+ end
27
+ end
28
+
29
+ class BlogPostsController < ApplicationController
30
+
31
+ def create
32
+ # ...
33
+ with_redis('blog_posts') {|r| r.incr('blog_posts_created' }
34
+ render
35
+ end
36
+ end
37
+
38
+
39
+ By default, both these calls will connect to the same Redis. Now,
40
+ let's say your leaderboard data is getting really big, and it's taking
41
+ up too much space on your one little Redis machine. You spin up a new
42
+ one and tell `RedisSelector` about it:
43
+
44
+ RedisSelector.configure(
45
+ 'leaderboards' => {'host' => 'big-huge-redis-box'}
46
+ # default is localhost for things not mentioned here
47
+ )
48
+
49
+ Then, Marketing goes crazy and starts posting blogs all over the
50
+ place, and all your blog posts start taking up a ton of space.
51
+
52
+ RedisSelector.configure(
53
+ 'leaderboards' => {'host' => 'big-huge-redis-box'}
54
+ 'blog_posts' => {'host' => 'other-redis-box'}
55
+ # default is localhost for things not mentioned here
56
+ )
57
+
58
+ That's the only code change you have to make. Throw that in
59
+ `config/environments/production.rb` and you're done. In development,
60
+ you probably haven't bothered to set anything up, so everything will
61
+ just go to localhost.
62
+
63
+ You can get separation by using different Redis databases, too. For
64
+ example, if two different models use the same Redis keys and step on
65
+ each other, you can split them up like so:
66
+
67
+ RedisSelector.configure(
68
+ 'model1' => {'host' => 'redis-box', 'db' => 1}
69
+ 'model2' => {'host' => 'redis-box', 'db' => 2}
70
+ # default is localhost/0 for things not mentioned here
71
+ )
72
+
73
+ Since they're in different databases, they get their own keyspaces and
74
+ don't step on each other.
75
+
76
+ ## Testing
77
+
78
+ `RedisSelector` supports the use of `MockRedis` in test mode. Add
79
+ `mock_redis` to your `Gemfile`, and call `RedisSelector.mock!`.
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require 'bundler/gem_tasks'
@@ -0,0 +1,5 @@
1
+ require "redis_selector//version"
2
+
3
+ module RedisSelector/
4
+ # Your code goes here...
5
+ end
@@ -0,0 +1,3 @@
1
+ module RedisSelector
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,58 @@
1
+ require "redis_selector/version"
2
+
3
+ module RedisSelector
4
+ DEFAULT_REDIS = {
5
+ 'host' => 'localhost',
6
+ }.freeze
7
+
8
+ class << self
9
+ attr_accessor :mocking
10
+ attr_accessor :mock_redises
11
+ attr_accessor :config
12
+ end
13
+ self.mock_redises ||= {}
14
+
15
+ def self.mock!
16
+ require 'mock_redis'
17
+ self.mocking = true
18
+ end
19
+
20
+ def self.unmock!
21
+ self.mocking = false
22
+ end
23
+
24
+ def self.configure(config)
25
+ self.config = config
26
+ end
27
+
28
+ # Rather than have one big global Redis, we let you get a Redis for
29
+ # a specific purpose. That way, if thing X's data set gets too
30
+ # large, you can point Redis.for(X) at a different redis-server
31
+ # instance, thus allowing for sharding based on logical data
32
+ # grouping.
33
+ #
34
+ # This doesn't address the problem of data migration.
35
+ def with_redis(what)
36
+ redis_selector = Module.nesting[0]
37
+
38
+ config = redis_selector.config || {}
39
+ redis_info = config[what] || config['default'] || DEFAULT_REDIS
40
+
41
+ redis = if redis_selector.mocking
42
+ # A MockRedis instance doesn't persist anywhere once we
43
+ # drop a reference to it, while a real Redis
44
+ # does. That's why we hold onto this mock like this;
45
+ # otherwise, repeated calls to with_redis(:foo) each get
46
+ # a completely empty mock.
47
+ redis_selector.mock_redises[redis_info['host']] ||= MockRedis.new
48
+ else
49
+ Redis.new(:host => redis_info['host'])
50
+ end
51
+
52
+ redis.select(redis_info['db']) if redis_info['db']
53
+ result = yield redis
54
+ result
55
+ ensure
56
+ redis.quit if redis
57
+ end
58
+ end
@@ -0,0 +1,20 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "redis_selector//version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "redis_selector/"
7
+ s.version = RedisSelector/::VERSION
8
+ s.authors = ["Samuel Merritt"]
9
+ s.email = ["spam@andcheese.org"]
10
+ s.homepage = ""
11
+ s.summary = %q{TODO: Write a gem summary}
12
+ s.description = %q{TODO: Write a gem description}
13
+
14
+ s.rubyforge_project = "redis_selector/"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+ end
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "redis_selector/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "redis_selector"
7
+ s.version = RedisSelector::VERSION
8
+ s.authors = ["Samuel Merritt"]
9
+ s.email = ["spam@andcheese.org"]
10
+ s.homepage = ""
11
+ s.summary = %q{Easy way to select different Redis instances/databases based on purpose.}
12
+ s.description = %q{Lets you select different Redis instances/databases easily.
13
+ This way, you get logical grouping of different Redis datasets.
14
+
15
+ Also supports mocking in test mode (via mock_redis gem).
16
+ }
17
+
18
+ s.rubyforge_project = "redis_selector"
19
+
20
+ s.files = `git ls-files`.split("\n")
21
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
22
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
23
+ s.require_paths = ["lib"]
24
+ end
metadata ADDED
@@ -0,0 +1,76 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: redis_selector
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Samuel Merritt
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-09-08 00:00:00 -07:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: "Lets you select different Redis instances/databases easily.\n This way, you get logical grouping of different Redis datasets.\n\n Also supports mocking in test mode (via mock_redis gem).\n "
23
+ email:
24
+ - spam@andcheese.org
25
+ executables: []
26
+
27
+ extensions: []
28
+
29
+ extra_rdoc_files: []
30
+
31
+ files:
32
+ - .gitignore
33
+ - Gemfile
34
+ - README.md
35
+ - Rakefile
36
+ - lib/redis_selector.rb
37
+ - lib/redis_selector/.rb
38
+ - lib/redis_selector/version.rb
39
+ - redis_selector.gemspec
40
+ - redis_selector/.gemspec
41
+ has_rdoc: true
42
+ homepage: ""
43
+ licenses: []
44
+
45
+ post_install_message:
46
+ rdoc_options: []
47
+
48
+ require_paths:
49
+ - lib
50
+ required_ruby_version: !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ hash: 3
56
+ segments:
57
+ - 0
58
+ version: "0"
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ none: false
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ hash: 3
65
+ segments:
66
+ - 0
67
+ version: "0"
68
+ requirements: []
69
+
70
+ rubyforge_project: redis_selector
71
+ rubygems_version: 1.3.7
72
+ signing_key:
73
+ specification_version: 3
74
+ summary: Easy way to select different Redis instances/databases based on purpose.
75
+ test_files: []
76
+