redis_ring 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
+ pkg/*
2
+ *.gem
3
+ .bundle
4
+ .rvmrc
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in redis_ring.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,34 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ redis_ring (0.0.1)
5
+ json
6
+ sinatra
7
+
8
+ GEM
9
+ remote: http://rubygems.org/
10
+ specs:
11
+ diff-lcs (1.1.2)
12
+ json (1.5.1)
13
+ mocha (0.9.12)
14
+ rack (1.2.1)
15
+ rspec (2.5.0)
16
+ rspec-core (~> 2.5.0)
17
+ rspec-expectations (~> 2.5.0)
18
+ rspec-mocks (~> 2.5.0)
19
+ rspec-core (2.5.1)
20
+ rspec-expectations (2.5.0)
21
+ diff-lcs (~> 1.1.2)
22
+ rspec-mocks (2.5.0)
23
+ sinatra (1.1.3)
24
+ rack (~> 1.1)
25
+ tilt (>= 1.2.2, < 2.0)
26
+ tilt (1.2.2)
27
+
28
+ PLATFORMS
29
+ ruby
30
+
31
+ DEPENDENCIES
32
+ mocha
33
+ redis_ring!
34
+ rspec
data/MIT-LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Adam Pohorecki, http://adam.pohorecki.pl/
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core'
5
+ require 'rspec/core/rake_task'
6
+
7
+ desc "Run all specs"
8
+ RSpec::Core::RakeTask.new(:spec) do |t|
9
+ t.pattern = "./spec/**/*_spec.rb"
10
+ t.rspec_opts = ["--profile --color"]
11
+ end
data/bin/redis-ring ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.push File.expand_path("../../lib", __FILE__)
4
+
5
+ require 'redis_ring'
6
+
7
+ RedisRing::CLI.new(ARGV).run
@@ -0,0 +1,32 @@
1
+ # By default RedisRing tries to guess the local IP address
2
+ # setting host_name should be necessary only if that is not possible
3
+ #host_name: localhost
4
+
5
+ # This is the port on which RedisRing publishes it's HTTP interface
6
+ # The Redis instances use ring_size next ports
7
+ base_port: 6400
8
+
9
+ # The number of Redis instances to start. Morte means more memory overhead (about 1MB per instance),
10
+ # but more means also easier moving around parts of the database
11
+ ring_size: 32
12
+
13
+ # By default which redis-server is used. Overwrite this setting if redis-server is not in PATH
14
+ #redis_path: /path/to/redis-server
15
+
16
+ # By default config/redis.conf.erb from the gem is used, but you can also supply your own.
17
+ # You can also change the redis server settings using the shared_config.conf file in base directory
18
+ #redis_config_template_path: /path/to/redis.conf.erb
19
+
20
+ # You can specify how much should Virtual Memory take in bytes (overall, not per Redis instance)
21
+ total_vm_size: 8589934592 #8GB
22
+ vm_page_size: 32
23
+
24
+ # This is the root directory under which all files will be stored
25
+ base_directory: /var/lib/redis
26
+
27
+ # Like with Virtual Memory, you can also specify how much memory all the Redis instances should take together
28
+ total_max_memory: 1073741824 # 1GB
29
+
30
+ # This is the password that will be used by all Redis instances. Remember that a huge number of passwords can be
31
+ # chacked in a second, so use a strong one. By default there is no password.
32
+ #password: letmein
@@ -0,0 +1,49 @@
1
+ daemonize no
2
+
3
+ port <%= port %>
4
+ logfile <%= log_file %>
5
+ dir <%= working_directory %>
6
+ vm-swap-file <%= vm_swap_file %>
7
+ vm-max-memory <%= vm_max_memory %>
8
+ vm-pages <%= vm_pages %>
9
+ vm-page-size <%= vm_page_size %>
10
+ dbfilename <%= db_file_name %>
11
+ appendfilename <%= aof_file_name %>
12
+ # slaveof <masterip> <masterport>
13
+ <% if password %>
14
+ requirepass <%= password %>
15
+ <% end %>
16
+
17
+ timeout 300
18
+
19
+ loglevel notice
20
+
21
+ databases 2048
22
+
23
+ save 900 1
24
+ save 300 10
25
+ save 60 10000
26
+
27
+ rdbcompression yes
28
+
29
+ # maxclients 128
30
+ # maxmemory <bytes>
31
+
32
+ appendonly no
33
+
34
+ # The name of the append only file (default: "appendonly.aof")
35
+
36
+ # appendfsync always
37
+ appendfsync everysec
38
+ # appendfsync no
39
+
40
+ vm-enabled yes
41
+ vm-max-threads 4
42
+
43
+ glueoutputbuf yes
44
+ hash-max-zipmap-entries 64
45
+ hash-max-zipmap-value 512
46
+
47
+ activerehashing yes
48
+
49
+ include <%= common_config_path %>
@@ -0,0 +1,47 @@
1
+ module RedisRing
2
+
3
+ class Application
4
+
5
+ attr_reader :shards, :configuration
6
+
7
+ def initialize(configuration)
8
+ @configuration = configuration
9
+ @shards = {}
10
+ end
11
+
12
+ def start
13
+ self.stop
14
+
15
+ @configuration.ring_size.times do |shard_number|
16
+ shard_conf = ShardConfig.new(shard_number, configuration)
17
+ @shards[shard_number] = Shard.new(shard_conf)
18
+ end
19
+
20
+ @shards.each do |shard_no, shard|
21
+ shard.start
22
+ end
23
+ end
24
+
25
+ def stop
26
+ @shards.each do |shard_no, shard|
27
+ shard.stop
28
+ end
29
+ @shards = {}
30
+ end
31
+
32
+ def shards_hash
33
+ shards_hash = {}
34
+ shards.each do |shard_no, shard|
35
+ shards_hash[shard_no] = { :host => shard.host, :port => shard.port, :status => shard.status }
36
+ end
37
+
38
+ return { :count => configuration.ring_size, :shards => shards_hash }
39
+ end
40
+
41
+ class << self
42
+ attr_accessor :instance
43
+ end
44
+
45
+ end
46
+
47
+ end
@@ -0,0 +1,53 @@
1
+ module RedisRing
2
+
3
+ class CLI
4
+
5
+ COMMANDS = [:help, :start]
6
+
7
+ attr_reader :argv
8
+
9
+ def initialize(argv)
10
+ @argv = argv
11
+ end
12
+
13
+ def run
14
+ command = argv[0]
15
+ if command.nil? || !COMMANDS.include?(command.to_sym)
16
+ usage
17
+ exit(1)
18
+ else
19
+ send(command, *argv[1..-1])
20
+ exit(0)
21
+ end
22
+ end
23
+
24
+ protected
25
+
26
+ def help
27
+ usage
28
+ end
29
+
30
+ def usage
31
+ puts <<USAGE
32
+ Usage:
33
+ #{$0} command [arguments]
34
+
35
+ Commands:
36
+ help - prints this message
37
+
38
+ start [config_file] - starts application
39
+ USAGE
40
+ end
41
+
42
+ def start(config_file = nil)
43
+ config = config_file ? Configuration.from_yml_file(config_file) : Configuration.new
44
+
45
+ Application.instance = Application.new(config)
46
+ Application.instance.start
47
+
48
+ WebInterface.run!(:port => config.base_port)
49
+ end
50
+
51
+ end
52
+
53
+ end
@@ -0,0 +1,79 @@
1
+ module RedisRing
2
+
3
+ class ConfigurationError < StandardError; end
4
+ class RedisNotFound < ConfigurationError; end
5
+ class UnknownConfigurationParameter < ConfigurationError; end
6
+
7
+ class Configuration
8
+
9
+ PARAMETERS = [:host_name, :base_port, :ring_size, :redis_path, :redis_config_template_path,
10
+ :total_vm_size, :base_directory, :password, :total_max_memory, :vm_page_size]
11
+
12
+ attr_reader *PARAMETERS
13
+
14
+ def initialize(params = {})
15
+ set_params(params)
16
+ set_defaults
17
+ validate!
18
+ end
19
+
20
+ def self.from_yml_file(file_name)
21
+ return from_yml(File.read(file_name))
22
+ end
23
+
24
+ def self.from_yml(string)
25
+ args = YAML::load(string)
26
+ return new(args)
27
+ end
28
+
29
+ protected
30
+
31
+ attr_writer *PARAMETERS
32
+
33
+ def set_params(params)
34
+ params.each do |param, value|
35
+ if PARAMETERS.include?(param.to_sym)
36
+ self.send("#{param}=", value)
37
+ else
38
+ raise UnknownConfigurationParameter.new("Unknown configuration parameter: #{param.inspect}")
39
+ end
40
+ end
41
+ end
42
+
43
+ def set_defaults
44
+ self.host_name ||= guess_host_name
45
+ self.base_port ||= 6400
46
+ self.ring_size ||= 32
47
+ self.redis_path ||= locate_redis
48
+ self.redis_config_template_path ||= default_redis_config_template_path
49
+ self.total_vm_size ||= 8 * 1024 * 1024 * 1024 # 8GB
50
+ self.base_directory ||= "/var/lib/redis"
51
+ self.total_max_memory ||= 1024 * 1024 * 1024 # 1GB
52
+ self.vm_page_size ||= 32
53
+ end
54
+
55
+ def validate!
56
+ raise RedisNotFound.new("redis_path is invalid (not found)") unless File.file?(redis_path)
57
+ end
58
+
59
+ def guess_host_name
60
+ orig, Socket.do_not_reverse_lookup = Socket.do_not_reverse_lookup, true # turn off reverse DNS resolution temporarily
61
+ UDPSocket.open do |s|
62
+ s.connect '64.233.187.99', 1
63
+ return s.addr.last
64
+ end
65
+ ensure
66
+ Socket.do_not_reverse_lookup = orig
67
+ end
68
+
69
+ def locate_redis
70
+ return %x[which redis-server].strip
71
+ end
72
+
73
+ def default_redis_config_template_path
74
+ File.expand_path('../../../config/redis.conf.erb', __FILE__)
75
+ end
76
+
77
+ end
78
+
79
+ end
@@ -0,0 +1,61 @@
1
+ module RedisRing
2
+
3
+ class Shard
4
+
5
+ attr_reader :shard_config, :pid
6
+
7
+ def initialize(shard_config)
8
+ @shard_config = shard_config
9
+ @status = :stopped
10
+ end
11
+
12
+ def shard_number
13
+ shard_config.shard_number
14
+ end
15
+
16
+ def host
17
+ shard_config.host
18
+ end
19
+
20
+ def port
21
+ shard_config.port
22
+ end
23
+
24
+ def status
25
+ if @status == :stopped
26
+ return alive? ? :stopping : :stopped
27
+ elsif @status == :started
28
+ return alive? ? :running : :dead
29
+ else
30
+ raise RuntimeException.new("Unknown status: #{@status.inspect}")
31
+ end
32
+ end
33
+
34
+ def start
35
+ shard_config.save
36
+ @pid = fork_redis_server
37
+ @status = :started
38
+ end
39
+
40
+ def stop
41
+ send_kill_signal
42
+ @status = :stopped
43
+ end
44
+
45
+ protected
46
+
47
+ def alive?
48
+ @pid && File.exist?("/proc/#{@pid}")
49
+ end
50
+
51
+ def fork_redis_server
52
+ spawn(shard_config.redis_path, shard_config.config_file_name)
53
+ end
54
+
55
+ def send_kill_signal
56
+ system("kill -QUIT #{pid}")
57
+ end
58
+
59
+ end
60
+
61
+ end
@@ -0,0 +1,93 @@
1
+ module RedisRing
2
+
3
+ class ShardConfig
4
+
5
+ attr_reader :shard_number, :configuration
6
+
7
+ def initialize(shard_number, configuration)
8
+ @shard_number = shard_number
9
+ @configuration = configuration
10
+ end
11
+
12
+ def render
13
+ template = ERB.new(File.read(configuration.redis_config_template_path))
14
+ return template.result(binding)
15
+ end
16
+
17
+ def save
18
+ FileUtils.mkdir_p(working_directory)
19
+
20
+ ['configs', 'logs', 'vm_files', 'db_files'].each do |dir_name|
21
+ FileUtils.mkdir_p(File.join(configuration.base_directory, dir_name))
22
+ end
23
+
24
+ FileUtils.touch(common_config_path) unless File.exist?(common_config_path)
25
+
26
+ File.open(config_file_name, 'w') { |f| f.write(render) }
27
+ end
28
+
29
+ def config_file_name
30
+ File.join(configuration.base_directory, 'configs', "shard-#{shard_number}.conf")
31
+ end
32
+
33
+ def host
34
+ configuration.host_name
35
+ end
36
+
37
+ def port
38
+ configuration.base_port + shard_number + 1
39
+ end
40
+
41
+ def redis_path
42
+ configuration.redis_path
43
+ end
44
+
45
+ def log_file
46
+ File.expand_path(file('logs', "shard-#{shard_number}.log"), working_directory)
47
+ end
48
+
49
+ def working_directory
50
+ "#{configuration.base_directory}/work/shard-#{shard_number}"
51
+ end
52
+
53
+ def vm_swap_file
54
+ file('vm_files', "shard-#{shard_number}.swap")
55
+ end
56
+
57
+ def vm_max_memory
58
+ configuration.total_max_memory / configuration.ring_size
59
+ end
60
+
61
+ def vm_pages
62
+ configuration.total_vm_size / configuration.vm_page_size / configuration.ring_size
63
+ end
64
+
65
+ def vm_page_size
66
+ configuration.vm_page_size
67
+ end
68
+
69
+ def db_file_name
70
+ file('db_files', "shard-#{shard_number}.rdb")
71
+ end
72
+
73
+ def aof_file_name
74
+ file('db_files', "shard-#{shard_number}.aof")
75
+ end
76
+
77
+ def password
78
+ configuration.password
79
+ end
80
+
81
+ def common_config_path
82
+ File.join(configuration.base_directory, "shared_config.conf")
83
+ end
84
+
85
+ protected
86
+
87
+ def file(*parts)
88
+ File.join('..', '..', *parts)
89
+ end
90
+
91
+ end
92
+
93
+ end
@@ -0,0 +1,3 @@
1
+ module RedisRing
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,16 @@
1
+ module RedisRing
2
+
3
+ class WebInterface < Sinatra::Base
4
+
5
+ get "/" do
6
+ "RedisRing is running"
7
+ end
8
+
9
+ get "/shards" do
10
+ content_type :json
11
+ Application.instance.shards_hash.to_json
12
+ end
13
+
14
+ end
15
+
16
+ end
data/lib/redis_ring.rb ADDED
@@ -0,0 +1,14 @@
1
+ require 'socket'
2
+ require 'yaml'
3
+ require 'erb'
4
+ require 'fileutils'
5
+
6
+ require 'sinatra'
7
+ require 'json'
8
+
9
+ require 'redis_ring/configuration'
10
+ require 'redis_ring/shard_config'
11
+ require 'redis_ring/shard'
12
+ require 'redis_ring/application'
13
+ require 'redis_ring/web_interface'
14
+ require 'redis_ring/cli'
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "redis_ring/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "redis_ring"
7
+ s.version = RedisRing::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Adam Pohorecki"]
10
+ s.email = ["adam@pohorecki.pl"]
11
+ s.homepage = "http://github.com/psyho/redis_ring"
12
+ s.summary = %q{A simplistic solution to redis sharding}
13
+ s.description = %q{RedisRing is a solution to run multiple small Redis instances intead of a single large one.}
14
+
15
+ s.rubyforge_project = "redis_ring"
16
+
17
+ s.add_dependency 'sinatra'
18
+ s.add_dependency 'json'
19
+
20
+ s.add_development_dependency 'rspec'
21
+ s.add_development_dependency 'mocha'
22
+
23
+ s.files = `git ls-files`.split("\n")
24
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
25
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
26
+ s.require_paths = ["lib"]
27
+ end
@@ -0,0 +1,23 @@
1
+ require File.expand_path("../../spec_helper", __FILE__)
2
+
3
+ describe RedisRing::Application do
4
+
5
+ describe "#shards_hash" do
6
+ before(:each) do
7
+ RedisRing::Shard.any_instance.stubs(:fork_redis_server => 123)
8
+ RedisRing::ShardConfig.any_instance.stubs(:save)
9
+ RedisRing::ShardConfig.any_instance.stubs(:alive? => true)
10
+
11
+ @application = RedisRing::Application.new(RedisRing::Configuration.new)
12
+ @application.start
13
+ end
14
+
15
+ it "should return all shards" do
16
+ shard_hash = @application.shards_hash
17
+
18
+ shard_hash[:count].should == @application.configuration.ring_size
19
+ shard_hash[:shards].size.should == @application.configuration.ring_size
20
+ end
21
+ end
22
+
23
+ end
@@ -0,0 +1,82 @@
1
+ require File.expand_path("../../spec_helper", __FILE__)
2
+
3
+ describe RedisRing::Configuration do
4
+ describe "defaults" do
5
+ before(:each) do
6
+ @config = RedisRing::Configuration.new
7
+ end
8
+
9
+ it "should have default port" do
10
+ @config.base_port.should_not be_nil
11
+ @config.base_port.should be_an_instance_of(Fixnum)
12
+ end
13
+
14
+ it "should have default host" do
15
+ @config.host_name.should_not be_nil
16
+ @config.host_name.should =~ /\d+\.\d+\.\d+.\d+/
17
+ end
18
+
19
+ it "should have default ring_size" do
20
+ @config.ring_size.should_not be_nil
21
+ @config.base_port.should be_an_instance_of(Fixnum)
22
+ @config.base_port.should > 0
23
+ end
24
+
25
+ it "should have default redis_path" do
26
+ @config.redis_path.should_not be_nil
27
+ File.exist?(@config.redis_path).should be_true
28
+ end
29
+
30
+ it "should have default redis_config_template_path" do
31
+ @config.redis_config_template_path.should_not be_nil
32
+ File.exist?(@config.redis_config_template_path).should be_true
33
+ end
34
+
35
+ it "should have default total_vm_size" do
36
+ @config.total_vm_size.should_not be_nil
37
+ @config.total_vm_size.should > 0
38
+ end
39
+
40
+ it "should have default base_directory" do
41
+ @config.base_directory.should_not be_nil
42
+ end
43
+
44
+ it "should have no password by default" do
45
+ @config.password.should be_nil
46
+ end
47
+
48
+ it "should have default total_memory" do
49
+ @config.total_max_memory.should_not be_nil
50
+ @config.total_max_memory.should > 0
51
+ end
52
+
53
+ it "should have default vm_page_size" do
54
+ @config.vm_page_size.should_not be_nil
55
+ @config.vm_page_size.should > 0
56
+ end
57
+ end
58
+
59
+ it "should rise RedisNotFound exception if redis-server not found" do
60
+ lambda {
61
+ RedisRing::Configuration.new(:redis_path => '/this/does/not/exist')
62
+ }.should raise_exception(RedisRing::RedisNotFound)
63
+ end
64
+
65
+ it "should rise UnknownConfigurationParameter exception if an unknown configuration parameter is given" do
66
+ lambda {
67
+ RedisRing::Configuration.new(:unknown_parameter => 'some value')
68
+ }.should raise_exception(RedisRing::UnknownConfigurationParameter)
69
+ end
70
+
71
+ it "should load yml config" do
72
+ yml_string = <<-YML
73
+ base_port: 666
74
+ base_directory: /home/psyho/redis
75
+ YML
76
+
77
+ config = RedisRing::Configuration.from_yml(yml_string)
78
+
79
+ config.base_port.should == 666
80
+ config.base_directory.should == '/home/psyho/redis'
81
+ end
82
+ end
@@ -0,0 +1,13 @@
1
+ require File.expand_path("../../spec_helper", __FILE__)
2
+
3
+ describe RedisRing::ShardConfig do
4
+ it "should render redis config with default config variables" do
5
+ config = RedisRing::Configuration.new
6
+ shard_config = RedisRing::ShardConfig.new(0, config)
7
+
8
+ redis_conf = shard_config.render
9
+
10
+ redis_conf.should include((config.base_port + 1).to_s)
11
+ redis_conf.should include(config.base_directory)
12
+ end
13
+ end
@@ -0,0 +1,49 @@
1
+ require File.expand_path("../../spec_helper", __FILE__)
2
+
3
+ describe RedisRing::Shard do
4
+
5
+ describe "possible statuses" do
6
+ before(:each) do
7
+ @shard = RedisRing::Shard.new(RedisRing::ShardConfig.new(0, RedisRing::Configuration.new))
8
+ @pid = 123
9
+ @shard.shard_config.stubs(:save)
10
+ @shard.stubs(:fork_redis_server => @pid)
11
+ @shard.stubs(:send_kill_signal)
12
+ end
13
+
14
+ it "should be stopped initially" do
15
+ @shard.status.should == :stopped
16
+ end
17
+
18
+ it "should be running if started and alive" do
19
+ @shard.stubs(:alive? => true)
20
+ @shard.start
21
+
22
+ @shard.status.should == :running
23
+ end
24
+
25
+ it "should be stopping if started then stopped but still alive" do
26
+ @shard.stubs(:alive? => true)
27
+ @shard.start
28
+ @shard.stop
29
+
30
+ @shard.status.should == :stopping
31
+ end
32
+
33
+ it "should be stopped if started then stopped and not alive" do
34
+ @shard.stubs(:alive? => false)
35
+ @shard.start
36
+ @shard.stop
37
+
38
+ @shard.status.should == :stopped
39
+ end
40
+
41
+ it "should be dead if started but not alive" do
42
+ @shard.stubs(:alive? => false)
43
+ @shard.start
44
+
45
+ @shard.status.should == :dead
46
+ end
47
+ end
48
+
49
+ end
@@ -0,0 +1,8 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+
3
+ require 'redis_ring'
4
+
5
+ RSpec.configure do |c|
6
+ c.color_enabled = true
7
+ c.mock_with :mocha
8
+ end
metadata ADDED
@@ -0,0 +1,137 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: redis_ring
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Adam Pohorecki
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-03-08 00:00:00 +01:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: sinatra
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 0
30
+ version: "0"
31
+ type: :runtime
32
+ version_requirements: *id001
33
+ - !ruby/object:Gem::Dependency
34
+ name: json
35
+ prerelease: false
36
+ requirement: &id002 !ruby/object:Gem::Requirement
37
+ none: false
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ segments:
42
+ - 0
43
+ version: "0"
44
+ type: :runtime
45
+ version_requirements: *id002
46
+ - !ruby/object:Gem::Dependency
47
+ name: rspec
48
+ prerelease: false
49
+ requirement: &id003 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ segments:
55
+ - 0
56
+ version: "0"
57
+ type: :development
58
+ version_requirements: *id003
59
+ - !ruby/object:Gem::Dependency
60
+ name: mocha
61
+ prerelease: false
62
+ requirement: &id004 !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ segments:
68
+ - 0
69
+ version: "0"
70
+ type: :development
71
+ version_requirements: *id004
72
+ description: RedisRing is a solution to run multiple small Redis instances intead of a single large one.
73
+ email:
74
+ - adam@pohorecki.pl
75
+ executables:
76
+ - redis-ring
77
+ extensions: []
78
+
79
+ extra_rdoc_files: []
80
+
81
+ files:
82
+ - .gitignore
83
+ - Gemfile
84
+ - Gemfile.lock
85
+ - MIT-LICENSE.txt
86
+ - Rakefile
87
+ - bin/redis-ring
88
+ - config/redis-ring.sample.yml
89
+ - config/redis.conf.erb
90
+ - lib/redis_ring.rb
91
+ - lib/redis_ring/application.rb
92
+ - lib/redis_ring/cli.rb
93
+ - lib/redis_ring/configuration.rb
94
+ - lib/redis_ring/shard.rb
95
+ - lib/redis_ring/shard_config.rb
96
+ - lib/redis_ring/version.rb
97
+ - lib/redis_ring/web_interface.rb
98
+ - redis_ring.gemspec
99
+ - spec/redis_ring/application_spec.rb
100
+ - spec/redis_ring/configuration_spec.rb
101
+ - spec/redis_ring/shard_config_spec.rb
102
+ - spec/redis_ring/shard_spec.rb
103
+ - spec/spec_helper.rb
104
+ has_rdoc: true
105
+ homepage: http://github.com/psyho/redis_ring
106
+ licenses: []
107
+
108
+ post_install_message:
109
+ rdoc_options: []
110
+
111
+ require_paths:
112
+ - lib
113
+ required_ruby_version: !ruby/object:Gem::Requirement
114
+ none: false
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ segments:
119
+ - 0
120
+ version: "0"
121
+ required_rubygems_version: !ruby/object:Gem::Requirement
122
+ none: false
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ segments:
127
+ - 0
128
+ version: "0"
129
+ requirements: []
130
+
131
+ rubyforge_project: redis_ring
132
+ rubygems_version: 1.3.7
133
+ signing_key:
134
+ specification_version: 3
135
+ summary: A simplistic solution to redis sharding
136
+ test_files: []
137
+