redis_pipeline 0.0.5 → 1.0.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.
data/README.md CHANGED
@@ -22,7 +22,7 @@ Create the configuration yaml file
22
22
 
23
23
  rails generate redis_pipeline
24
24
 
25
- Populate the configuration file with the redis uri and batch size.
25
+ Populate the configuration file with the redis uri and batch size. The configuration file is stored at `config/redis_pipeline.yml`
26
26
 
27
27
  * uri defaults to `redis://localhost:6379` if you don't have a configuration file
28
28
  * batch size defaults to 1000 if you don't have a configuration file
@@ -32,28 +32,37 @@ Populate the configuration file with the redis uri and batch size.
32
32
  Create a new pipeline
33
33
 
34
34
  ```ruby
35
- pipeline = RedisPipeline::RedisPineline.new('redis_uri')
35
+ pipeline = RedisPipeline::RedisPineline.new
36
36
  ```
37
37
 
38
- Queue up commands with add_commands either as a single string
38
+ Queue up commands by adding them. You can add a single command as a string. Within a command the | character is used to separate the parts of the command.
39
39
 
40
40
  ```ruby
41
- pipeline.add_commands('set|hello|world')
41
+ pipeline.add_command('set|hello|world')
42
42
  ```
43
43
 
44
- or an array
44
+ Or pass an array of commands.
45
45
 
46
46
  ```ruby
47
47
  array = ['hset|gem|first_name|redis', '|hset|gem|last_name|pipeline']
48
- pipeline.add_commands(array)
48
+ pipeline.add_command(array)
49
49
  ```
50
50
 
51
- Send them with execute_commands. Commands are sent using redis-rb's pipelined mode in batches, the size of which are controlled by your configuration. Returns false if there is an error
51
+ The shovel operator works as well.
52
52
 
53
53
  ```ruby
54
- pipeline.execute_commands
54
+ pipeline << 'set|hello|world'
55
+ pipeline << ['hset|gem|first_name|redis', '|hset|gem|last_name|pipeline']
55
56
  ```
56
57
 
58
+ Send the commands to redis with <tt>execute</tt>. Commands are sent using redis-rb's pipelined mode in batches, the size of which are controlled by your configuration. Returns false if there is an error, true if all commands succeed.
59
+
60
+ ```ruby
61
+ pipeline.execute
62
+ ```
63
+
64
+ See the pipeline errors by iterating through `pipeline.errors`.
65
+
57
66
  ## Contributing
58
67
 
59
68
  1. Fork it
@@ -0,0 +1,4 @@
1
+ module RedisPipeline
2
+ class Commands < Array
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module RedisPipeline
2
+ class Errors < Array
3
+ end
4
+ end
@@ -7,39 +7,50 @@ module RedisPipeline
7
7
 
8
8
  attr_reader :errors
9
9
 
10
+ # Instantiates and configures a redis pipeline.
10
11
  def initialize()
11
12
  configure
12
- @redis = open_redis_connection
13
- @commands = []
14
- @errors = []
13
+ self.redis = open_redis_connection
14
+ self.commands = Commands.new
15
+ self.errors = Errors.new
15
16
  end
16
17
 
17
- def add_commands(new_commands)
18
- new_commands = [new_commands] if new_commands.class == String
19
- @commands.concat(new_commands)
20
- end
21
-
22
- def execute_commands
23
- response = true
18
+ # Sends each command to the redis pipline, where it is processed.
19
+ # Commands are removed from the command collection when sent to the pipeline.
20
+ # Returns <tt>true</tt> if all commands succeed. Returns <tt>false</tt> if any command fails.
21
+ def execute
24
22
  begin
25
- while @commands.length > 0
23
+ while commands.length > 0
26
24
  pipeline_commands(command_batch)
27
25
  end
28
26
  rescue => error
29
- @errors << error.message
30
- response = false
27
+ errors << error.message
31
28
  end
32
- response
29
+
30
+ errors.empty?
33
31
  end
34
32
 
33
+ # Adds commands to the piplined. Pass either a single command in a string or an array of commands
34
+ # pipeline.add_command('set|hello|world') => [all_commands]
35
+ # pipeline.add_command(['hset|gem|first_name|redis', '|hset|gem|last_name|pipeline']) => [all_commands]
36
+ # Within a command the | character is used to separate the parts of the command.
37
+ # Returns an array of all commands that have been added.
38
+ # commands are removed from the array when they are executed
39
+ def <<(new_commands)
40
+ new_commands = [new_commands] if !new_commands.respond_to?(:each)
41
+ commands.concat(new_commands)
42
+ end
43
+ alias_method :add_command, :<<
44
+
35
45
  private
36
46
 
37
- attr_accessor :commands, :redis
47
+ attr_writer :errors
48
+ attr_accessor :redis, :commands
38
49
 
39
50
  def command_batch
40
51
  command_batch = []
41
- @commands.first(@settings[:batch_size]).count.times do
42
- command_batch << @commands.shift
52
+ commands.first(@settings[:batch_size]).count.times do
53
+ command_batch << commands.shift
43
54
  end
44
55
  command_batch
45
56
  end
@@ -54,10 +65,10 @@ module RedisPipeline
54
65
  end
55
66
 
56
67
  def pipeline_commands(command_batch)
57
- @redis.pipelined do
68
+ redis.pipelined do
58
69
  command_batch.each do |command|
59
70
  redis_args = command.split("|")
60
- @redis.send(*redis_args)
71
+ redis.send(*redis_args)
61
72
  end
62
73
  end
63
74
  end
@@ -1,3 +1,3 @@
1
1
  module RedisPipeline
2
- VERSION = "0.0.5"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -3,6 +3,8 @@ require 'redis'
3
3
  require 'active_support/inflector'
4
4
  require 'gem_configurator'
5
5
  require_relative 'redis_pipeline/redis_pipeline'
6
+ require_relative 'redis_pipeline/commands'
7
+ require_relative 'redis_pipeline/errors'
6
8
 
7
9
  require 'bundler'
8
10
  Bundler.require
@@ -14,7 +14,7 @@ Gem::Specification.new do |gem|
14
14
  gem.name = "redis_pipeline"
15
15
  gem.require_paths = ["lib"]
16
16
  gem.version = RedisPipeline::VERSION
17
- gem.add_dependency('gem_configurator')
17
+ gem.add_dependency('gem_configurator', '~> 1.0.0')
18
18
  gem.add_dependency 'redis'
19
19
  gem.add_development_dependency 'rake'
20
20
  end
@@ -23,28 +23,40 @@ class TestRedisPipeline < Test::Unit::TestCase
23
23
 
24
24
  def test_add_commands_adds_array_of_commands_as_seperate_commands
25
25
  commands = ["hset|person:0|first_name|joe", "hest|person:0|last_name|smith"]
26
- @pipeline.add_commands(commands)
26
+ @pipeline.add_command(commands)
27
+ assert_equal commands.length, @pipeline.send(:commands).length
28
+ end
29
+
30
+ def test_shovel_command_adds_array_of_commands_as_seperate_commands
31
+ commands = ["hset|person:0|first_name|joe", "hest|person:0|last_name|smith"]
32
+ @pipeline << commands
27
33
  assert_equal commands.length, @pipeline.send(:commands).length
28
34
  end
29
35
 
30
36
  def test_add_commands_adds_string_as_single_command
31
37
  commands = "hset|person:0 first_name joe"
32
- @pipeline.add_commands(commands)
38
+ @pipeline.add_command(commands)
39
+ assert_equal 1, @pipeline.send(:commands).length
40
+ end
41
+
42
+ def test_shovel_command_adds_string_as_single_command
43
+ commands = "hset|person:0 first_name joe"
44
+ @pipeline << commands
33
45
  assert_equal 1, @pipeline.send(:commands).length
34
46
  end
35
47
 
36
48
  def test_add_commands_queues_commands_at_end
37
49
  commands = ["hset|person:0|first_name|joe", "hest|person:0|last_name|smith"]
38
- @pipeline.add_commands(commands)
50
+ @pipeline.add_command(commands)
39
51
  last_command = "hset|person:1|first_name|jane"
40
- @pipeline.add_commands(last_command)
52
+ @pipeline.add_command(last_command)
41
53
  assert_equal commands[0], @pipeline.send(:commands).first
42
54
  assert_equal last_command, @pipeline.send(:commands).last
43
55
  end
44
56
 
45
57
  def test_command_batch_returns_batch_size_number_of_items
46
58
  full_command_set = three_batches_of_commands
47
- @pipeline.add_commands(full_command_set)
59
+ @pipeline.add_command(full_command_set)
48
60
  single_batch = @pipeline.send(:command_batch)
49
61
 
50
62
  upper_limit = (@pipeline.settings[:batch_size] - 1)
@@ -52,7 +64,7 @@ class TestRedisPipeline < Test::Unit::TestCase
52
64
  end
53
65
 
54
66
  def test_command_batch_takes_batch_size_items_out_of_commands
55
- @pipeline.add_commands(three_batches_of_commands)
67
+ @pipeline.add_command(three_batches_of_commands)
56
68
  count = @pipeline.send(:commands).length
57
69
  @pipeline.send(:command_batch)
58
70
  assert_equal (count - @pipeline.settings[:batch_size]), @pipeline.send(:commands).length
@@ -61,39 +73,39 @@ class TestRedisPipeline < Test::Unit::TestCase
61
73
  def test_execute_sends_commands_to_redis
62
74
  uri_parsed = URI.parse(@uri)
63
75
  redis = Redis.new(:host => uri_parsed.host, :port => uri_parsed.port, :password => uri_parsed.password)
64
- @pipeline.add_commands(three_batches_of_commands)
76
+ @pipeline.add_command(three_batches_of_commands)
65
77
 
66
78
  first_command = @pipeline.send(:commands).first.split("|")
67
79
  last_command = @pipeline.send(:commands).last.split("|")
68
80
  assert_equal Hash.new(), redis.send("hgetall", first_command[1])
69
81
  assert_equal Hash.new(), redis.send("hgetall", last_command[1])
70
82
 
71
- @pipeline.execute_commands
83
+ @pipeline.execute
72
84
  assert_equal first_command.last, redis.send("hget", *first_command[1..-2])
73
85
  assert_equal last_command.last, redis.send("hget", *last_command[1..-2])
74
86
  end
75
87
 
76
88
  def test_after_execute_no_items_in_command
77
- @pipeline.add_commands(three_batches_of_commands)
78
- @pipeline.execute_commands
89
+ @pipeline.add_command(three_batches_of_commands)
90
+ @pipeline.execute
79
91
  assert_equal 0, @pipeline.send(:commands).length
80
92
  end
81
93
 
82
94
  def test_execute_commands_returns_true_if_successful
83
- @pipeline.add_commands(three_batches_of_commands)
84
- assert @pipeline.execute_commands
95
+ @pipeline.add_command(three_batches_of_commands)
96
+ assert @pipeline.execute
85
97
  end
86
98
 
87
99
  def test_execute_commands_returns_false_if_error
88
100
  mismatched_commands = ['set|"string_key"|"string_value"', 'hget|"string_key"|"string_not_a_hash"']
89
- @pipeline.add_commands(mismatched_commands)
90
- assert_equal false, @pipeline.execute_commands
101
+ @pipeline.add_command(mismatched_commands)
102
+ assert_equal false, @pipeline.execute
91
103
  end
92
104
 
93
105
  def test_execute_commands_populates_errors_if_error
94
106
  mismatched_commands = ['set|"string_key"|"string_value"', 'hget|"string_key"|"string_not_a_hash"']
95
- @pipeline.add_commands(mismatched_commands)
96
- @pipeline.execute_commands
107
+ @pipeline.add_command(mismatched_commands)
108
+ @pipeline.execute
97
109
  assert_equal 1, @pipeline.errors.count, "#{@pipeline.errors.inspect}"
98
110
  assert_equal 'ERR Operation against a key holding the wrong kind of value', @pipeline.errors[0]
99
111
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redis_pipeline
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 1.0.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,22 +10,22 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-08-31 00:00:00.000000000Z
13
+ date: 2012-09-05 00:00:00.000000000Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: gem_configurator
17
- requirement: &2161477740 !ruby/object:Gem::Requirement
17
+ requirement: &2169692560 !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
- - - ! '>='
20
+ - - ~>
21
21
  - !ruby/object:Gem::Version
22
- version: '0'
22
+ version: 1.0.0
23
23
  type: :runtime
24
24
  prerelease: false
25
- version_requirements: *2161477740
25
+ version_requirements: *2169692560
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: redis
28
- requirement: &2161477320 !ruby/object:Gem::Requirement
28
+ requirement: &2169692140 !ruby/object:Gem::Requirement
29
29
  none: false
30
30
  requirements:
31
31
  - - ! '>='
@@ -33,10 +33,10 @@ dependencies:
33
33
  version: '0'
34
34
  type: :runtime
35
35
  prerelease: false
36
- version_requirements: *2161477320
36
+ version_requirements: *2169692140
37
37
  - !ruby/object:Gem::Dependency
38
38
  name: rake
39
- requirement: &2161476900 !ruby/object:Gem::Requirement
39
+ requirement: &2169691680 !ruby/object:Gem::Requirement
40
40
  none: false
41
41
  requirements:
42
42
  - - ! '>='
@@ -44,7 +44,7 @@ dependencies:
44
44
  version: '0'
45
45
  type: :development
46
46
  prerelease: false
47
- version_requirements: *2161476900
47
+ version_requirements: *2169691680
48
48
  description: Send commands to a redis server in pipelined batches
49
49
  email:
50
50
  - iwhitney@ssa-i.org
@@ -62,6 +62,8 @@ files:
62
62
  - lib/generators/redis_pipeline/install/install_generator.rb
63
63
  - lib/generators/redis_pipeline/install/templates/redis_pipeline.example.yml
64
64
  - lib/redis_pipeline.rb
65
+ - lib/redis_pipeline/commands.rb
66
+ - lib/redis_pipeline/errors.rb
65
67
  - lib/redis_pipeline/redis_pipeline.rb
66
68
  - lib/redis_pipeline/version.rb
67
69
  - redis_pipeline.gemspec