redis_selector 0.0.1

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.
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
+