kestrel-client 0.6.1 → 0.6.4

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.6.1
1
+ 0.7.0
@@ -1,75 +1,71 @@
1
1
  # Generated by jeweler
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
5
 
6
6
  Gem::Specification.new do |s|
7
- s.name = %q{kestrel-client}
8
- s.version = "0.6.1"
7
+ s.name = "kestrel-client"
8
+ s.version = "0.6.4"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Matt Freels", "Rael Dornfest"]
12
- s.date = %q{2011-01-19}
13
- s.description = %q{Ruby client for the Kestrel queue server}
14
- s.email = %q{rael@twitter.com}
12
+ s.date = "2011-09-15"
13
+ s.description = "Ruby client for the Kestrel queue server"
14
+ s.email = "rael@twitter.com"
15
15
  s.extra_rdoc_files = [
16
16
  "README.md"
17
17
  ]
18
18
  s.files = [
19
- ".gitignore",
20
- "README.md",
21
- "Rakefile",
22
- "VERSION",
23
- "kestrel-client.gemspec",
24
- "lib/kestrel-client.rb",
25
- "lib/kestrel.rb",
26
- "lib/kestrel/client.rb",
27
- "lib/kestrel/client/blocking.rb",
28
- "lib/kestrel/client/envelope.rb",
29
- "lib/kestrel/client/json.rb",
30
- "lib/kestrel/client/namespace.rb",
31
- "lib/kestrel/client/partitioning.rb",
32
- "lib/kestrel/client/proxy.rb",
33
- "lib/kestrel/client/retry_helper.rb",
34
- "lib/kestrel/client/stats_helper.rb",
35
- "lib/kestrel/client/transactional.rb",
36
- "lib/kestrel/client/unmarshal.rb",
37
- "lib/kestrel/config.rb",
38
- "spec/kestrel/client/blocking_spec.rb",
39
- "spec/kestrel/client/envelope_spec.rb",
40
- "spec/kestrel/client/json_spec.rb",
41
- "spec/kestrel/client/namespace_spec.rb",
42
- "spec/kestrel/client/partitioning_spec.rb",
43
- "spec/kestrel/client/transactional_spec.rb",
44
- "spec/kestrel/client/unmarshal_spec.rb",
45
- "spec/kestrel/client_spec.rb",
46
- "spec/kestrel/config/kestrel.yml",
47
- "spec/kestrel/config_spec.rb",
48
- "spec/kestrel_benchmark.rb",
49
- "spec/spec.opts",
50
- "spec/spec_helper.rb"
19
+ "README.md",
20
+ "Rakefile",
21
+ "VERSION",
22
+ "kestrel-client.gemspec",
23
+ "lib/kestrel-client.rb",
24
+ "lib/kestrel.rb",
25
+ "lib/kestrel/client.rb",
26
+ "lib/kestrel/client/blocking.rb",
27
+ "lib/kestrel/client/envelope.rb",
28
+ "lib/kestrel/client/json.rb",
29
+ "lib/kestrel/client/namespace.rb",
30
+ "lib/kestrel/client/partitioning.rb",
31
+ "lib/kestrel/client/proxy.rb",
32
+ "lib/kestrel/client/stats_helper.rb",
33
+ "lib/kestrel/client/transactional.rb",
34
+ "lib/kestrel/client/unmarshal.rb",
35
+ "lib/kestrel/config.rb",
36
+ "spec/kestrel/client/blocking_spec.rb",
37
+ "spec/kestrel/client/envelope_spec.rb",
38
+ "spec/kestrel/client/json_spec.rb",
39
+ "spec/kestrel/client/namespace_spec.rb",
40
+ "spec/kestrel/client/partitioning_spec.rb",
41
+ "spec/kestrel/client/transactional_spec.rb",
42
+ "spec/kestrel/client/unmarshal_spec.rb",
43
+ "spec/kestrel/client_spec.rb",
44
+ "spec/kestrel/config/kestrel.yml",
45
+ "spec/kestrel/config_spec.rb",
46
+ "spec/kestrel_benchmark.rb",
47
+ "spec/spec.opts",
48
+ "spec/spec_helper.rb"
51
49
  ]
52
- s.homepage = %q{http://github.com/freels/kestrel-client}
53
- s.rdoc_options = ["--charset=UTF-8"]
50
+ s.homepage = "http://github.com/freels/kestrel-client"
54
51
  s.require_paths = ["lib"]
55
- s.rubygems_version = %q{1.3.7}
56
- s.summary = %q{Ruby Kestrel client}
52
+ s.rubygems_version = "1.8.10"
53
+ s.summary = "Ruby Kestrel client"
57
54
  s.test_files = [
58
55
  "spec/kestrel/client/blocking_spec.rb",
59
- "spec/kestrel/client/envelope_spec.rb",
60
- "spec/kestrel/client/json_spec.rb",
61
- "spec/kestrel/client/namespace_spec.rb",
62
- "spec/kestrel/client/partitioning_spec.rb",
63
- "spec/kestrel/client/transactional_spec.rb",
64
- "spec/kestrel/client/unmarshal_spec.rb",
65
- "spec/kestrel/client_spec.rb",
66
- "spec/kestrel/config_spec.rb",
67
- "spec/kestrel_benchmark.rb",
68
- "spec/spec_helper.rb"
56
+ "spec/kestrel/client/envelope_spec.rb",
57
+ "spec/kestrel/client/json_spec.rb",
58
+ "spec/kestrel/client/namespace_spec.rb",
59
+ "spec/kestrel/client/partitioning_spec.rb",
60
+ "spec/kestrel/client/transactional_spec.rb",
61
+ "spec/kestrel/client/unmarshal_spec.rb",
62
+ "spec/kestrel/client_spec.rb",
63
+ "spec/kestrel/config_spec.rb",
64
+ "spec/kestrel_benchmark.rb",
65
+ "spec/spec_helper.rb"
69
66
  ]
70
67
 
71
68
  if s.respond_to? :specification_version then
72
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
73
69
  s.specification_version = 3
74
70
 
75
71
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
@@ -1,7 +1,8 @@
1
+ require 'forwardable'
2
+
1
3
  module Kestrel
2
- class Client < Memcached
4
+ class Client
3
5
  require 'kestrel/client/stats_helper'
4
- require 'kestrel/client/retry_helper'
5
6
 
6
7
  autoload :Proxy, 'kestrel/client/proxy'
7
8
  autoload :Envelope, 'kestrel/client/envelope'
@@ -35,12 +36,17 @@ module Kestrel
35
36
  Memcached::ServerError,
36
37
  Memcached::SystemError,
37
38
  Memcached::UnknownReadFailure,
38
- Memcached::WriteFailure
39
+ Memcached::WriteFailure,
40
+ Memcached::NotFound
39
41
  ]
40
42
 
43
+ extend Forwardable
41
44
  include StatsHelper
42
- include RetryHelper
43
45
 
46
+ attr_accessor :servers, :options
47
+ attr_reader :current_queue, :kestrel_options, :current_server
48
+
49
+ def_delegators :@write_client, :add, :append, :cas, :decr, :incr, :get_orig, :prepend
44
50
 
45
51
  def initialize(*servers)
46
52
  opts = servers.last.is_a?(Hash) ? servers.pop : {}
@@ -51,64 +57,44 @@ module Kestrel
51
57
  @gets_per_server = kestrel_options[:gets_per_server]
52
58
  @exception_retry_limit = kestrel_options[:exception_retry_limit]
53
59
  @counter = 0
60
+ @shuffle = true
54
61
 
55
62
  # we handle our own retries so that we can apply different
56
63
  # policies to sets and gets, so set memcached limit to 0
57
64
  opts[:exception_retry_limit] = 0
58
65
  opts[:distribution] = :random # force random distribution
59
66
 
60
- super Array(servers).flatten.compact, opts
61
- end
62
-
63
-
64
- attr_reader :current_queue, :kestrel_options
65
-
67
+ self.servers = Array(servers).flatten.compact
68
+ self.options = opts
66
69
 
67
- # Memcached overrides
68
-
69
- %w(add append cas decr incr get_orig prepend).each do |m|
70
- undef_method m
71
- end
72
-
73
- alias _super_get_from_random get
74
- private :_super_get_from_random
75
-
76
- def get_from_random(key, raw=false)
77
- _super_get_from_random key, !raw
78
- rescue Memcached::NotFound
70
+ @server_count = self.servers.size # Minor optimization.
71
+ @read_client = Memcached.new(self.servers[rand(@server_count)], opts)
72
+ @write_client = Memcached.new(self.servers[rand(@server_count)], opts)
79
73
  end
80
74
 
81
- # use get_from_last if available, otherwise redefine to point to
82
- # plain old get
83
- if method_defined? :get_from_last
84
-
85
- def get_from_last(key, raw=false)
86
- super key, !raw
87
- rescue Memcached::NotFound
88
- end
89
-
90
- else
91
-
92
- $stderr.puts "You have an older version of memcached.gem. Please upgrade to 0.19.6 or later for sticky get behavior."
93
- def get_from_last(key, raw=false)
94
- _super_get_from_random key, !raw
95
- rescue Memcached::NotFound
96
- end
97
-
98
- end # end ifdef :)
99
-
100
75
  def delete(key, expiry=0)
101
- with_retries { super key }
76
+ with_retries { @write_client.delete key }
102
77
  rescue Memcached::NotFound, Memcached::ServerEnd
103
78
  end
104
79
 
105
80
  def set(key, value, ttl=0, raw=false)
106
- with_retries { super key, value, ttl, !raw }
81
+ with_retries { @write_client.set key, value, ttl, !raw }
107
82
  true
108
83
  rescue Memcached::NotStored
109
84
  false
110
85
  end
111
86
 
87
+ # This provides the necessary semantic to support transactionality
88
+ # in the Transactional client. It temporarily disables server
89
+ # shuffling to allow the client to close any open transactions on
90
+ # the current server before jumping.
91
+ #
92
+ def get_from_last(*args)
93
+ @shuffle = false
94
+ get *args
95
+ ensure
96
+ @shuffle = true
97
+ end
112
98
 
113
99
  # ==== Parameters
114
100
  # key<String>:: Queue name
@@ -125,12 +111,13 @@ module Kestrel
125
111
  # style" second argument.
126
112
  #
127
113
  def get(key, opts = {})
128
- raw = opts.delete(:raw) || false
114
+ raw = opts[:raw] || false
129
115
  commands = extract_queue_commands(opts)
130
116
 
131
117
  val =
132
118
  begin
133
- send(select_get_method(key), key + commands, raw)
119
+ shuffle_if_necessary! key
120
+ @read_client.get key + commands, !raw
134
121
  rescue *RECOVERABLE_ERRORS
135
122
  # we can't tell the difference between a server being down
136
123
  # and an empty queue, so just return nil. our sticky server
@@ -167,14 +154,18 @@ module Kestrel
167
154
  kestrel_opts
168
155
  end
169
156
 
170
- def select_get_method(key)
171
- if key != @current_queue || @counter >= @gets_per_server
157
+ def shuffle_if_necessary!(key)
158
+ # Don't reset servers on the first request:
159
+ # i.e. @counter == 0 && @current_queue == nil
160
+ if @shuffle &&
161
+ (@counter > 0 && key != @current_queue) ||
162
+ @counter >= @gets_per_server
172
163
  @counter = 0
173
164
  @current_queue = key
174
- :get_from_random
165
+ @read_client.quit
166
+ @read_client.set_servers(servers[rand(@server_count)])
175
167
  else
176
168
  @counter +=1
177
- :get_from_last
178
169
  end
179
170
  end
180
171
 
@@ -189,5 +180,20 @@ module Kestrel
189
180
 
190
181
  commands.map { |c| "/#{c}" }.join('')
191
182
  end
183
+
184
+ def with_retries #:nodoc:
185
+ yield
186
+ rescue *RECOVERABLE_ERRORS
187
+ tries ||= @exception_retry_limit + 1
188
+ tries -= 1
189
+ if tries > 0
190
+ retry
191
+ else
192
+ @write_client.quit
193
+ @write_client.set_servers(servers[rand(@server_count)])
194
+ raise
195
+ end
196
+ end
197
+
192
198
  end
193
199
  end
@@ -18,26 +18,30 @@ describe Kestrel::Client do
18
18
  end
19
19
 
20
20
  it "gets from the same server :gets_per_server times" do
21
- mock(@kestrel).get_from_last("a_queue/t=10", false).times(100) { 'item' }
22
- mock(@kestrel).get_from_random("a_queue/t=10", false).times(2) { 'item' }
21
+ client = @kestrel.instance_variable_get(:@read_client)
22
+ mock(client).get("a_queue/t=10", true).times(102).returns('item')
23
+ mock(client).quit.once
24
+ mock(client).set_servers.with(anything).once
23
25
 
24
26
  102.times { @kestrel.get("a_queue") }
25
27
  end
26
28
 
27
29
  it "gets from a different server when the last result was nil" do
28
- mock(@kestrel).get_from_last("a_queue/t=10", false).never { nil }
29
- mock(@kestrel).get_from_random("a_queue/t=10", false).times(3) { nil }
30
+ client = @kestrel.instance_variable_get(:@read_client)
31
+ mock(client).get("a_queue/t=10", true).returns(nil).twice
32
+ mock(client).quit.once
33
+ mock(client).set_servers.with(anything).once
30
34
 
31
- 3.times { @kestrel.get("a_queue") }
35
+ 2.times { @kestrel.get("a_queue") }
32
36
  end
33
37
 
34
38
  it "returns nil if there is a recoverable exception" do
35
- mock(@kestrel).select_get_method(@queue) { raise Memcached::SystemError }
39
+ mock(@kestrel).shuffle_if_necessary!(@queue) { raise Memcached::SystemError }
36
40
  @kestrel.get(@queue).should == nil
37
41
  end
38
42
 
39
43
  it "raises the exception if the exception is not recoverable" do
40
- mock(@kestrel).select_get_method(@queue) { raise ArgumentError }
44
+ mock(@kestrel).shuffle_if_necessary!(@queue) { raise ArgumentError }
41
45
  lambda { @kestrel.get(@queue) }.should raise_error(ArgumentError)
42
46
  end
43
47
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kestrel-client
3
3
  version: !ruby/object:Gem::Version
4
- hash: 5
5
- prerelease: false
4
+ hash: 15
5
+ prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 6
9
- - 1
10
- version: 0.6.1
9
+ - 4
10
+ version: 0.6.4
11
11
  platform: ruby
12
12
  authors:
13
13
  - Matt Freels
@@ -16,8 +16,7 @@ autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
18
 
19
- date: 2011-01-19 00:00:00 -08:00
20
- default_executable:
19
+ date: 2011-09-15 00:00:00 Z
21
20
  dependencies:
22
21
  - !ruby/object:Gem::Dependency
23
22
  name: memcached
@@ -44,7 +43,6 @@ extensions: []
44
43
  extra_rdoc_files:
45
44
  - README.md
46
45
  files:
47
- - .gitignore
48
46
  - README.md
49
47
  - Rakefile
50
48
  - VERSION
@@ -58,7 +56,6 @@ files:
58
56
  - lib/kestrel/client/namespace.rb
59
57
  - lib/kestrel/client/partitioning.rb
60
58
  - lib/kestrel/client/proxy.rb
61
- - lib/kestrel/client/retry_helper.rb
62
59
  - lib/kestrel/client/stats_helper.rb
63
60
  - lib/kestrel/client/transactional.rb
64
61
  - lib/kestrel/client/unmarshal.rb
@@ -76,13 +73,12 @@ files:
76
73
  - spec/kestrel_benchmark.rb
77
74
  - spec/spec.opts
78
75
  - spec/spec_helper.rb
79
- has_rdoc: true
80
76
  homepage: http://github.com/freels/kestrel-client
81
77
  licenses: []
82
78
 
83
79
  post_install_message:
84
- rdoc_options:
85
- - --charset=UTF-8
80
+ rdoc_options: []
81
+
86
82
  require_paths:
87
83
  - lib
88
84
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -106,7 +102,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
106
102
  requirements: []
107
103
 
108
104
  rubyforge_project:
109
- rubygems_version: 1.3.7
105
+ rubygems_version: 1.8.10
110
106
  signing_key:
111
107
  specification_version: 3
112
108
  summary: Ruby Kestrel client
data/.gitignore DELETED
@@ -1 +0,0 @@
1
- pkg/*
@@ -1,12 +0,0 @@
1
- module Kestrel::Client::RetryHelper
2
-
3
- private
4
-
5
- def with_retries #:nodoc:
6
- yield
7
- rescue *Kestrel::Client::RECOVERABLE_ERRORS
8
- tries ||= @exception_retry_limit + 1
9
- tries -= 1
10
- tries > 0 ? retry : raise
11
- end
12
- end