siberite-client 0.8.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.
@@ -0,0 +1,175 @@
1
+ require 'spec_helper'
2
+
3
+ describe Siberite::Client do
4
+ describe "Instance Methods" do
5
+ before do
6
+ @client = Siberite::Client.new('localhost:22133')
7
+ end
8
+
9
+ describe "#get and #set" do
10
+ it "basic operation" do
11
+ @client.flush(queue = "test_queue")
12
+ @client.set(queue, value = "russell's reserve")
13
+ @client.get(queue).should == value
14
+ end
15
+
16
+ it "returns nil when getting from a queue that does not exist" do
17
+ @client.get('nonexistent_queue').should == nil
18
+ end
19
+
20
+ it "gets from the same server :gets_per_server times" do
21
+ client = @client.instance_variable_get(:@read_client)
22
+ mock(client).get("a_queue/t=10", true).times(102).returns('item')
23
+
24
+ 102.times { @client.get("a_queue") }
25
+ end
26
+
27
+ it "gets from a different server when the last result was nil" do
28
+ client = @client.instance_variable_get(:@read_client)
29
+ mock(client).get("a_queue/t=10", true).returns(nil).twice
30
+
31
+ 2.times { @client.get("a_queue") }
32
+ end
33
+
34
+ it "returns nil if there is a recoverable exception" do
35
+ mock(@client).shuffle_if_necessary!(@queue) { raise Memcached::SystemError }
36
+ @client.get(@queue).should == nil
37
+ end
38
+
39
+ it "raises the exception if the exception is not recoverable" do
40
+ mock(@client).shuffle_if_necessary!(@queue) { raise ArgumentError }
41
+ lambda { @client.get(@queue) }.should raise_error(ArgumentError)
42
+ end
43
+ end
44
+
45
+ describe "retry behavior" do
46
+ it "does not retry gets" do
47
+ mock(@client).with_retries.never
48
+ @client.get("a_queue")
49
+ end
50
+
51
+ it "retries sets" do
52
+ mock(@client).with_retries
53
+ @client.set("a_queue", "value")
54
+ end
55
+ end
56
+
57
+ describe "#flush" do
58
+ before do
59
+ @queue = "some_random_queue_#{Time.now.to_i}_#{rand(10000)}"
60
+ end
61
+
62
+ it "counts the number of items flushed and passes each of them to a given block" do
63
+ %w{A B C}.each { |item| @client.set(@queue, item) }
64
+ @client.flush(@queue).should == 3
65
+ end
66
+
67
+ it "does not attempt to Marshal load the data being flushed" do
68
+ @client.set(@queue, "some_stuff", 0, true)
69
+ mock(Marshal).load.never
70
+ @client.flush(@queue).should == 1
71
+ end
72
+ end
73
+
74
+ describe "#peek" do
75
+ it "should return first item from the queue and reenqueue" do
76
+ @queue = "some_random_queue_#{Time.now.to_i}_#{rand(10000)}"
77
+ @client.set(@queue, "item_1")
78
+ @client.set(@queue, "item_2")
79
+ @client.peek(@queue).should == "item_1"
80
+ @client.sizeof(@queue).should == 2
81
+ end
82
+ end
83
+
84
+ describe "#with_retries" do
85
+ it "retries a specified number of times" do
86
+ mock(@client).set(anything, anything) { raise Memcached::SystemError }.times(6)
87
+
88
+ lambda do
89
+ @client.send(:with_retries) { @client.set("a_queue", "foo") }
90
+ end.should raise_error(Memcached::SystemError)
91
+ end
92
+
93
+ it "does not raise if within the retry limit" do
94
+ mock(@client).set(anything, anything) { raise Memcached::SystemError }.times(5).
95
+ then.set(anything, anything) { true }
96
+
97
+ lambda do
98
+ @client.send(:with_retries) { @client.set("a_queue", "foo") }
99
+ end.should_not raise_error
100
+ end
101
+
102
+ it "does not catch unknown errors" do
103
+ mock(@client).set(anything, anything) { raise ArgumentError }
104
+
105
+ lambda do
106
+ @client.send(:with_retries) { @client.set("a_queue", "foo") }
107
+ end.should raise_error(ArgumentError)
108
+ end
109
+ end
110
+
111
+ describe "#stats" do
112
+ it "retrieves stats" do
113
+ @client.set("test-queue-name", 97)
114
+
115
+ stats = @client.stats
116
+ %w{uptime time version curr_items total_items bytes curr_connections total_connections
117
+ cmd_get cmd_set get_hits get_misses bytes_read bytes_written queues}.each do |stat|
118
+ stats[stat].should_not be_nil
119
+ end
120
+
121
+ stats['queues']["test-queue-name"].should_not be_nil
122
+ Siberite::Client::QUEUE_STAT_NAMES.each do |queue_stat|
123
+ stats['queues']['test-queue-name'][queue_stat].should_not be_nil
124
+ end
125
+ end
126
+
127
+ it "merge in stats from all the servers" do
128
+ server = @client.servers.first
129
+ stub(@client).servers { [server] }
130
+ stats_for_one_server = @client.stats
131
+
132
+ server = @client.servers.first
133
+ stub(@client).servers { [server] * 2 }
134
+ stats_for_two_servers = @client.stats
135
+
136
+ stats_for_two_servers['bytes'].should == 2*stats_for_one_server['bytes']
137
+ end
138
+ end
139
+
140
+ describe "#stat" do
141
+ it "get stats for single queue" do
142
+ @client.set(queue = "test-queue-name", 97)
143
+ all_stats = @client.stats
144
+ single_queue_stats = @client.stat(queue).except("age")
145
+
146
+ expect(single_queue_stats).to eq all_stats['queues'][queue].except("age")
147
+ end
148
+ end
149
+
150
+ describe "#sizeof" do
151
+ before do
152
+ @queue = "some_random_queue_#{Time.now.to_i}_#{rand(10000)}"
153
+ end
154
+
155
+ it "reports the size of the queue" do
156
+ 100.times { @client.set(@queue, true) }
157
+ @client.sizeof(@queue).should == 100
158
+ end
159
+
160
+ it "reports the size of a non-existant queue as 0" do
161
+ queue = "some_random_queue_#{Time.now.to_i}_#{rand(10000)}"
162
+ @client.sizeof(queue).should == 0
163
+ end
164
+ end
165
+
166
+ describe "#available_queues" do
167
+ it "returns all the queue names" do
168
+ @client.set("test-queue-name1", 97)
169
+ @client.set("test-queue-name2", 155)
170
+ @client.available_queues.should include('test-queue-name1')
171
+ @client.available_queues.should include('test-queue-name2')
172
+ end
173
+ end
174
+ end
175
+ end
@@ -0,0 +1,42 @@
1
+ defaults: &defaults
2
+ distribution: :random
3
+ timeout: 0.1
4
+ connect_timeout: 0.5
5
+ server_failure_limit: 10
6
+ auto_eject_hosts: false
7
+
8
+ production: &production
9
+ <<: *defaults
10
+ auto_eject_hosts: true
11
+ server_failure_limit: 4
12
+ servers:
13
+ - localhost:22133
14
+
15
+ staging:
16
+ <<: *production
17
+ servers:
18
+ - localhost:22133
19
+
20
+ development: &development
21
+ <<: *defaults
22
+ show_backtraces: true
23
+ servers:
24
+ - localhost:22133
25
+
26
+ benchmark:
27
+ <<: *development
28
+
29
+ test:
30
+ <<: *development
31
+
32
+ replication_lag:
33
+ <<: *development
34
+
35
+ selenium:
36
+ <<: *development
37
+
38
+ foo_space:
39
+ production:
40
+ <<: *production
41
+ development:
42
+ <<: *development
@@ -0,0 +1,72 @@
1
+ require 'spec_helper'
2
+
3
+ describe Siberite::Config do
4
+ before do
5
+ # to sniff namespace foo_space
6
+ Siberite::Config.config['foo_space']['development']['connect_timeout'] = 8
7
+ end
8
+
9
+ describe "load" do
10
+ it "loads a yaml file" do
11
+ Siberite::Config.config = nil
12
+ lambda { Siberite::Config.default }.should raise_error
13
+
14
+ Siberite::Config.load TEST_CONFIG_FILE
15
+ lambda { Siberite::Config.default }.should_not raise_error
16
+ end
17
+ end
18
+
19
+ shared_examples_for "config getters" do
20
+ it "returns a tuple of [servers, options]" do
21
+ config = @configurer.call
22
+ config.should be_a(Array)
23
+
24
+ [String, Array].should include(config.first.class)
25
+ config.last.should be_a(Hash)
26
+
27
+ config.last.keys.map{|k| k.class }.uniq.should == [Symbol]
28
+ end
29
+
30
+ it "defaults to development enviroment" do
31
+ @configurer.call.last[:server_failure_limit].should == 10 # development options should pull 10 from defaults
32
+ end
33
+
34
+ it "returns config for the specified environment" do
35
+ Siberite::Config.environment = :production
36
+ @configurer.call.last[:server_failure_limit].should == 4 # production is set to 4
37
+ end
38
+ end
39
+
40
+ describe "namespace" do
41
+ before { @configurer = lambda { Siberite::Config.namespace(:foo_space) } }
42
+
43
+ it_should_behave_like "config getters"
44
+
45
+ it "returns args for Siberite::Client.new for the appropriate namespace" do
46
+ Siberite::Config.foo_space.last[:connect_timeout].should == 8
47
+ end
48
+
49
+ it "is aliased to method_missing" do
50
+ Siberite::Config.foo_space.should == Siberite::Config.namespace(:foo_space)
51
+ end
52
+ end
53
+
54
+ describe "default" do
55
+ before { @configurer = lambda { Siberite::Config.default } }
56
+
57
+ it_should_behave_like "config getters"
58
+ end
59
+
60
+ describe "new_client" do
61
+ it "returns a Siberite::Client instance" do
62
+ client = Siberite::Config.new_client
63
+ client.should be_a(Siberite::Client)
64
+ end
65
+
66
+ it "can take a namespace" do
67
+ client = Siberite::Config.new_client(:foo_space)
68
+ client.should be_a(Siberite::Client)
69
+ client.options[:connect_timeout].should == 8
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+ require 'benchmark'
3
+
4
+ describe Siberite::Client do
5
+ before do
6
+ @queue = "a_queue"
7
+ @client = Siberite::Client.new(*Siberite::Config.default)
8
+
9
+ @client.delete(@queue) rescue nil # Memcache::ServerEnd bug
10
+ end
11
+
12
+ it "is fast" do
13
+ @client.flush(@queue)
14
+ @value = { :value => "a value" }
15
+ @raw_value = Marshal.dump(@value)
16
+
17
+ times = 10_000
18
+
19
+ Benchmark.bm do |x|
20
+ x.report("set:") { for i in 1..times; @client.set(@queue, @value); end }
21
+ x.report("get:") { for i in 1..times; @client.get(@queue); end }
22
+ x.report("set (raw):") { for i in 1..times; @client.set(@queue, @raw_value, 0, true); end }
23
+ x.report("get (raw):") { for i in 1..times; @client.get(@queue, :raw => true); end }
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,3 @@
1
+ --colour
2
+ --format progress
3
+ --backtrace
@@ -0,0 +1,33 @@
1
+ require 'rspec'
2
+ require 'pry'
3
+ require 'pry-byebug'
4
+ require "active_support/core_ext/hash"
5
+
6
+ spec_dir = File.dirname(__FILE__)
7
+
8
+ # make sure we load local libs rather than gems first
9
+ $: << File.expand_path("#{spec_dir}/../lib")
10
+
11
+ require 'siberite'
12
+
13
+ TEST_CONFIG_FILE = File.expand_path("#{spec_dir}/siberite/config/siberite.yml")
14
+
15
+ RSpec.configure do |config|
16
+ config.mock_with :rr
17
+
18
+ config.expect_with :rspec do |c|
19
+ c.syntax = [:should, :expect]
20
+ end
21
+
22
+ config.before do
23
+ Siberite::Config.environment = nil
24
+ Siberite::Config.load TEST_CONFIG_FILE
25
+ end
26
+
27
+ config.after do
28
+ c = Siberite::Client.new(*Siberite::Config.default)
29
+ c.available_queues.uniq.each do |q|
30
+ c.delete(q) rescue nil
31
+ end
32
+ end
33
+ end
metadata ADDED
@@ -0,0 +1,205 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: siberite-client
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.8.0
5
+ platform: ruby
6
+ authors:
7
+ - Matt Freels
8
+ - Rael Dornfest
9
+ - Anton Bogdanovich
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2015-11-23 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: memcached
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 0.19.6
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - '>='
27
+ - !ruby/object:Gem::Version
28
+ version: 0.19.6
29
+ - !ruby/object:Gem::Dependency
30
+ name: pry
31
+ requirement: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - ~>
34
+ - !ruby/object:Gem::Version
35
+ version: '0.10'
36
+ type: :development
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ~>
41
+ - !ruby/object:Gem::Version
42
+ version: '0.10'
43
+ - !ruby/object:Gem::Dependency
44
+ name: pry-byebug
45
+ requirement: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ~>
48
+ - !ruby/object:Gem::Version
49
+ version: '2.0'
50
+ type: :development
51
+ prerelease: false
52
+ version_requirements: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ~>
55
+ - !ruby/object:Gem::Version
56
+ version: '2.0'
57
+ - !ruby/object:Gem::Dependency
58
+ name: rspec
59
+ requirement: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ~>
62
+ - !ruby/object:Gem::Version
63
+ version: '3.2'
64
+ type: :development
65
+ prerelease: false
66
+ version_requirements: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ~>
69
+ - !ruby/object:Gem::Version
70
+ version: '3.2'
71
+ - !ruby/object:Gem::Dependency
72
+ name: rr
73
+ requirement: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: '1.1'
78
+ type: :development
79
+ prerelease: false
80
+ version_requirements: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ~>
83
+ - !ruby/object:Gem::Version
84
+ version: '1.1'
85
+ - !ruby/object:Gem::Dependency
86
+ name: activesupport
87
+ requirement: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - '>'
90
+ - !ruby/object:Gem::Version
91
+ version: '3.1'
92
+ type: :development
93
+ prerelease: false
94
+ version_requirements: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - '>'
97
+ - !ruby/object:Gem::Version
98
+ version: '3.1'
99
+ - !ruby/object:Gem::Dependency
100
+ name: bundler
101
+ requirement: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ~>
104
+ - !ruby/object:Gem::Version
105
+ version: '1.7'
106
+ type: :development
107
+ prerelease: false
108
+ version_requirements: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - ~>
111
+ - !ruby/object:Gem::Version
112
+ version: '1.7'
113
+ - !ruby/object:Gem::Dependency
114
+ name: rake
115
+ requirement: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - ~>
118
+ - !ruby/object:Gem::Version
119
+ version: '10.0'
120
+ type: :development
121
+ prerelease: false
122
+ version_requirements: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ~>
125
+ - !ruby/object:Gem::Version
126
+ version: '10.0'
127
+ description: Ruby client for the Siberite queue server
128
+ email: anton@bogdanovich.co
129
+ executables: []
130
+ extensions: []
131
+ extra_rdoc_files:
132
+ - README.md
133
+ files:
134
+ - .gitignore
135
+ - Gemfile
136
+ - LICENSE
137
+ - README.md
138
+ - Rakefile
139
+ - lib/siberite-client.rb
140
+ - lib/siberite.rb
141
+ - lib/siberite/client.rb
142
+ - lib/siberite/client/blocking.rb
143
+ - lib/siberite/client/envelope.rb
144
+ - lib/siberite/client/json.rb
145
+ - lib/siberite/client/namespace.rb
146
+ - lib/siberite/client/partitioning.rb
147
+ - lib/siberite/client/proxy.rb
148
+ - lib/siberite/client/stats_helper.rb
149
+ - lib/siberite/client/transactional.rb
150
+ - lib/siberite/client/unmarshal.rb
151
+ - lib/siberite/client/version.rb
152
+ - lib/siberite/config.rb
153
+ - siberite-client.gemspec
154
+ - spec/siberite/client/blocking_spec.rb
155
+ - spec/siberite/client/envelope_spec.rb
156
+ - spec/siberite/client/json_spec.rb
157
+ - spec/siberite/client/namespace_spec.rb
158
+ - spec/siberite/client/partitioning_spec.rb
159
+ - spec/siberite/client/transactional_spec.rb
160
+ - spec/siberite/client/unmarshal_spec.rb
161
+ - spec/siberite/client_spec.rb
162
+ - spec/siberite/config/siberite.yml
163
+ - spec/siberite/config_spec.rb
164
+ - spec/siberite_benchmark.rb
165
+ - spec/spec.opts
166
+ - spec/spec_helper.rb
167
+ homepage: http://github.com/bogdanovich/siberite-ruby
168
+ licenses:
169
+ - Apache-2
170
+ metadata: {}
171
+ post_install_message:
172
+ rdoc_options: []
173
+ require_paths:
174
+ - lib
175
+ required_ruby_version: !ruby/object:Gem::Requirement
176
+ requirements:
177
+ - - '>='
178
+ - !ruby/object:Gem::Version
179
+ version: '0'
180
+ required_rubygems_version: !ruby/object:Gem::Requirement
181
+ requirements:
182
+ - - '>='
183
+ - !ruby/object:Gem::Version
184
+ version: '0'
185
+ requirements: []
186
+ rubyforge_project:
187
+ rubygems_version: 2.2.2
188
+ signing_key:
189
+ specification_version: 4
190
+ summary: Ruby Siberite client
191
+ test_files:
192
+ - spec/siberite/client/blocking_spec.rb
193
+ - spec/siberite/client/envelope_spec.rb
194
+ - spec/siberite/client/json_spec.rb
195
+ - spec/siberite/client/namespace_spec.rb
196
+ - spec/siberite/client/partitioning_spec.rb
197
+ - spec/siberite/client/transactional_spec.rb
198
+ - spec/siberite/client/unmarshal_spec.rb
199
+ - spec/siberite/client_spec.rb
200
+ - spec/siberite/config/siberite.yml
201
+ - spec/siberite/config_spec.rb
202
+ - spec/siberite_benchmark.rb
203
+ - spec/spec.opts
204
+ - spec/spec_helper.rb
205
+ has_rdoc: