moneta 0.7.18 → 0.7.19

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 40e5bf4f97796468cef521c2b103f72d7be29811
4
- data.tar.gz: d9ab4368e38146049f4e92a0cf2337b2148fcf10
3
+ metadata.gz: 54ab5446cbb72cf10100e2e72680c4624113aaa0
4
+ data.tar.gz: c3337a129506fdeab6624542b37ada15a9c16c20
5
5
  SHA512:
6
- metadata.gz: 2fadbaee29f91f2259b44cf7140d64e3ab12196ee2e29c6c9ccc5db2518b0a06a4db0d81f654e7625dceaa3ead6a7636aeb2240d9cff0bd17161b2f1865a6f19
7
- data.tar.gz: f1751faff2cef9302fa0b3125e421e6632fa580978ab548fb13afd53f7dc37fe0e586821a657b3c79298a44b9ba66ccf68edacbf6efcc89e3b134176dfa2b7c9
6
+ metadata.gz: dc94d4af7c904ad023cee82ee3ec408e9685273362a94a6cf620ba0d108ea69b660ea8a737bd91491faacd10c09d0e5b1942f429b19fb010df806980e9f1f88b
7
+ data.tar.gz: 50a2df5e71906df99c2954ed1efb8ca2986234db51f21565c53bbbbdf93e2b07f123d041c6c165a0b24e9876852cbc23d2b4877e94261cf0f8b4bda946da53c1
data/.travis.yml CHANGED
@@ -24,31 +24,31 @@ env:
24
24
  global:
25
25
  - secure: "dtM4n7FP8P0UI9Iq+nsvQ7/yfDqsxhfCO9i8zMxm/f9Kxj5Z/4C7jsXsLA+e\n/7FZ9+ld2QjPSPU0LUiDpj/z81bxyZHwqocQ7Nb0DVvO3JRHpr4/iBQQQHd3\n0jvou3mRbu5mBlUjf1/ALaZA+b+vcnsF9fd86UnkY+ChriylGnM="
26
26
  matrix:
27
- - "TASK=test TEST_GROUP=1/10"
28
- - "TASK=test TEST_GROUP=2/10"
29
- - "TASK=test TEST_GROUP=3/10"
30
- - "TASK=test TEST_GROUP=4/10"
31
- - "TASK=test TEST_GROUP=5/10"
32
- - "TASK=test TEST_GROUP=6/10"
33
- - "TASK=test TEST_GROUP=7/10"
34
- - "TASK=test TEST_GROUP=8/10"
35
- - "TASK=test TEST_GROUP=9/10"
36
- - "TASK=test TEST_GROUP=10/10"
37
- - "TASK=test TEST_GROUP=unstable"
38
- - "TASK=benchmarks CONFIG=uniform_small"
39
- - "TASK=benchmarks CONFIG=uniform_medium"
40
- - "TASK=benchmarks CONFIG=uniform_large"
41
- - "TASK=benchmarks CONFIG=normal_small"
42
- - "TASK=benchmarks CONFIG=normal_medium"
43
- - "TASK=benchmarks CONFIG=normal_large"
27
+ - "SCRIPT='parallel-tests 1/10'"
28
+ - "SCRIPT='parallel-tests 2/10'"
29
+ - "SCRIPT='parallel-tests 3/10'"
30
+ - "SCRIPT='parallel-tests 4/10'"
31
+ - "SCRIPT='parallel-tests 5/10'"
32
+ - "SCRIPT='parallel-tests 6/10'"
33
+ - "SCRIPT='parallel-tests 7/10'"
34
+ - "SCRIPT='parallel-tests 8/10'"
35
+ - "SCRIPT='parallel-tests 9/10'"
36
+ - "SCRIPT='parallel-tests 10/10'"
37
+ - "SCRIPT='parallel-tests unstable'"
38
+ - "SCRIPT='benchmarks uniform_small'"
39
+ - "SCRIPT='benchmarks uniform_medium'"
40
+ - "SCRIPT='benchmarks uniform_large'"
41
+ - "SCRIPT='benchmarks normal_small'"
42
+ - "SCRIPT='benchmarks normal_medium'"
43
+ - "SCRIPT='benchmarks normal_large'"
44
44
  matrix:
45
45
  allow_failures:
46
46
  - rvm: jruby-18mode
47
47
  - rvm: jruby-19mode
48
48
  - rvm: rbx-18mode
49
49
  - rvm: rbx-19mode
50
- - env: "TASK=test TEST_GROUP=unstable"
51
- script: "bundle exec rake $TASK"
50
+ - env: "SCRIPT='parallel-tests unstable'"
51
+ script: "eval bundle exec ruby script/$SCRIPT"
52
52
  branches:
53
53
  only:
54
54
  - master
data/CHANGES CHANGED
@@ -1,3 +1,9 @@
1
+ 0.7.19
2
+
3
+ * ActionDispatch::Session::MonetaStore fixed for Rails 4
4
+ * Moneta::Server: Tries now to remove stale unix socket
5
+ * Moneta::Server: More robust and better performance
6
+
1
7
  0.7.18
2
8
 
3
9
  * Adapters::File#increment and #create fixed on JRuby
data/CONTRIBUTORS CHANGED
@@ -16,6 +16,7 @@ lakshan <lakshan@web2media.net>
16
16
  Piotr Murach <pmurach@gmail.com>
17
17
  Potapov Sergey <blake131313@gmail.com>
18
18
  Quin Hoxie <quin@aboutus.org>
19
+ Ryan T. Hosford <tad.hosford@gmail.com>
19
20
  Scott Wadden <scott.wadden@gmail.com>
20
21
  Tom Meier <ozmeier@yahoo.co.uk>
21
22
  Xavier Shay <xavier@rhnh.net>
data/Gemfile CHANGED
@@ -1,8 +1,14 @@
1
+ # Rails 4 requires Ruby >= 1.9
2
+ def rails_version
3
+ v = ['>= 3.2.11']
4
+ v << '< 4.0.0' unless RUBY_VERSION >= '1.9'
5
+ v
6
+ end
7
+
1
8
  source 'https://rubygems.org'
2
9
  gemspec
3
10
 
4
11
  # Testing
5
- gem 'rake'
6
12
  gem 'rspec'
7
13
  gem 'rspec-retry'
8
14
 
@@ -38,7 +44,7 @@ gem 'dm-migrations'
38
44
  gem 'dm-mysql-adapter'
39
45
  # FIXME: Use fog master because of failing tests, fixed after 1.11.1
40
46
  gem 'fog', :github => 'fog/fog'
41
- gem 'activerecord', '>= 3.2.11'
47
+ gem 'activerecord', *rails_version
42
48
  gem 'redis'
43
49
  gem 'mongo'
44
50
  gem 'sequel'
@@ -74,5 +80,5 @@ gem 'rack'
74
80
  gem 'rack-cache'
75
81
 
76
82
  # Rails integration testing
77
- gem 'actionpack', '>= 3.2.11'
83
+ gem 'actionpack', *rails_version
78
84
  gem 'minitest', '~> 4.7.4'
data/SPEC.md CHANGED
@@ -65,7 +65,7 @@ Closes the store
65
65
 
66
66
  ### <code>features => Array&lt;Symbol&gt;</code> and <code>supports?(Symbol) => [TrueClass, FalseClass]</code>
67
67
 
68
- Feature detection. Adapters MUST return <code>:create</code> and <code>:increment</code> if these methods are supported.
68
+ Feature detection. Adapters MUST return <code>:create</code> and <code>:increment</code> if these methods are supported.
69
69
 
70
70
  ## Additional Options Hashes
71
71
 
@@ -6,6 +6,7 @@ module ActionDispatch
6
6
  class MonetaStore < Rack::Session::Moneta
7
7
  include Compatibility
8
8
  include StaleSessionCheck
9
+ include SessionObject if defined?(SessionObject)
9
10
  end
10
11
  end
11
12
  end
data/lib/moneta.rb CHANGED
@@ -10,7 +10,6 @@ module Moneta
10
10
  autoload :Lock, 'moneta/lock'
11
11
  autoload :Logger, 'moneta/logger'
12
12
  autoload :Mutex, 'moneta/synchronize'
13
- autoload :Net, 'moneta/mixins'
14
13
  autoload :OptionMerger, 'moneta/optionmerger'
15
14
  autoload :OptionSupport, 'moneta/mixins'
16
15
  autoload :Pool, 'moneta/pool'
@@ -5,7 +5,6 @@ module Moneta
5
5
  # Moneta client backend
6
6
  # @api public
7
7
  class Client
8
- include Net
9
8
  include Defaults
10
9
 
11
10
  # @param [Hash] options
@@ -14,50 +13,50 @@ module Moneta
14
13
  # @option options [String] :socket Unix socket file name as alternative to `:port` and `:host`
15
14
  def initialize(options = {})
16
15
  @socket = options[:socket] ? UNIXSocket.open(options[:socket]) :
17
- TCPSocket.open(options[:host] || '127.0.0.1', options[:port] || DEFAULT_PORT)
16
+ TCPSocket.open(options[:host] || '127.0.0.1', options[:port] || 9000)
18
17
  end
19
18
 
20
19
  # (see Proxy#key?)
21
20
  def key?(key, options = {})
22
- write(@socket, [:key?, key, options])
23
- read_result
21
+ write(:key?, key, options)
22
+ read
24
23
  end
25
24
 
26
25
  # (see Proxy#load)
27
26
  def load(key, options = {})
28
- write(@socket, [:load, key, options])
29
- read_result
27
+ write(:load, key, options)
28
+ read
30
29
  end
31
30
 
32
31
  # (see Proxy#store)
33
32
  def store(key, value, options = {})
34
- write(@socket, [:store, key, value, options])
35
- read_result
33
+ write(:store, key, value, options)
34
+ read
36
35
  value
37
36
  end
38
37
 
39
38
  # (see Proxy#delete)
40
39
  def delete(key, options = {})
41
- write(@socket, [:delete, key, options])
42
- read_result
40
+ write(:delete, key, options)
41
+ read
43
42
  end
44
43
 
45
44
  # (see Proxy#increment)
46
45
  def increment(key, amount = 1, options = {})
47
- write(@socket, [:increment, key, amount, options])
48
- read_result
46
+ write(:increment, key, amount, options)
47
+ read
49
48
  end
50
49
 
51
50
  # (see Proxy#create)
52
51
  def create(key, value, options = {})
53
- write(@socket, [:create, key, value, options])
54
- read_result
52
+ write(:create, key, value, options)
53
+ read
55
54
  end
56
55
 
57
56
  # (see Proxy#clear)
58
57
  def clear(options = {})
59
- write(@socket, [:clear, options])
60
- read_result
58
+ write(:clear, options)
59
+ read
61
60
  self
62
61
  end
63
62
 
@@ -71,16 +70,22 @@ module Moneta
71
70
  def features
72
71
  @features ||=
73
72
  begin
74
- write(@socket, [:features])
75
- read_result.freeze
73
+ write(:features)
74
+ read.freeze
76
75
  end
77
76
  end
78
77
 
79
78
  private
80
79
 
81
- def read_result
82
- result = read(@socket)
83
- raise result if Error === result
80
+ def write(*args)
81
+ s = Marshal.dump(args)
82
+ @socket.write([s.bytesize].pack('N') << s)
83
+ end
84
+
85
+ def read
86
+ size = @socket.read(4).unpack('N').first
87
+ result = Marshal.load(@socket.read(size))
88
+ raise result if Exception === result
84
89
  result
85
90
  end
86
91
  end
@@ -52,7 +52,7 @@ module Moneta
52
52
  def increment(key, amount = 1, options = {})
53
53
  # FIXME: There is a Dalli bug, load(key) returns a wrong value after increment
54
54
  # therefore we set default = nil and create the counter manually
55
- # See https://github.com/mperham/dalli/issues/309
55
+ # See https://github.com/mperham/dalli/issues/309
56
56
  result =
57
57
  if amount >= 0
58
58
  @backend.incr(key, amount, expires_value(options) || nil, nil)
@@ -64,7 +64,7 @@ module Moneta
64
64
  @backend.decrement(key, -amount)
65
65
  end
66
66
  # HACK: Throw error if applied to invalid value
67
- # see https://github.com/evan/memcached/issues/110
67
+ # see https://github.com/evan/memcached/issues/110
68
68
  Utils.to_int((@backend.get(key, false) rescue nil)) if result == 0
69
69
  result
70
70
  rescue ::Memcached::NotFound => ex
data/lib/moneta/mixins.rb CHANGED
@@ -284,27 +284,6 @@ module Moneta
284
284
  end
285
285
  end
286
286
 
287
- # @api private
288
- module Net
289
- DEFAULT_PORT = 9000
290
-
291
- class Error < RuntimeError; end
292
-
293
- def pack(o)
294
- s = Marshal.dump(o)
295
- [s.bytesize].pack('N') << s
296
- end
297
-
298
- def read(io)
299
- size = io.read(4).unpack('N').first
300
- Marshal.load(io.read(size))
301
- end
302
-
303
- def write(io, o)
304
- io.write(pack(o))
305
- end
306
- end
307
-
308
287
  # This mixin handles the calculation of expiration times.
309
288
  #
310
289
  #
data/lib/moneta/pool.rb CHANGED
@@ -27,7 +27,7 @@ module Moneta
27
27
 
28
28
  def close
29
29
  @mutex.synchronize do
30
- raise '#close can only when no thread is using the pool' if @all.size != @pool.size
30
+ raise '#close can only be called when no thread is using the pool' if @all.size != @pool.size
31
31
  @all.each(&:close)
32
32
  @all = @pool = nil
33
33
  end
data/lib/moneta/server.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  require 'socket'
2
2
 
3
3
  module Moneta
4
- # Moneta server
4
+ # Moneta server to be used together with Moneta::Adapters::Client
5
5
  # @api public
6
6
  class Server
7
7
  # @param [Hash] options
@@ -9,13 +9,9 @@ module Moneta
9
9
  # @option options [String] :socket Alternative Unix socket file name
10
10
  def initialize(store, options = {})
11
11
  @store = store
12
- @server =
13
- if @socket = options[:socket]
14
- UNIXServer.open(@socket)
15
- else
16
- TCPServer.open(options[:port] || DEFAULT_PORT)
17
- end
18
- @clients = [@server]
12
+ @server = start(options)
13
+ @ios = [@server]
14
+ @clients = {}
19
15
  @running = false
20
16
  end
21
17
 
@@ -52,54 +48,89 @@ module Moneta
52
48
 
53
49
  private
54
50
 
55
- include Net
56
51
  TIMEOUT = 1
52
+ MAXSIZE = 0x100000
57
53
 
58
54
  def mainloop
59
- client = accept
60
- handle(client) if client
55
+ if ios = IO.select(@ios, nil, @ios, TIMEOUT)
56
+ ios[2].each do |io|
57
+ io.close
58
+ delete_client(io)
59
+ end
60
+ ios[0].each do |io|
61
+ if io == @server
62
+ if client = @server.accept
63
+ @ios << client
64
+ @clients[client] = ''
65
+ end
66
+ elsif io.closed? || io.eof?
67
+ delete_client(io)
68
+ else
69
+ handle(io, @clients[io] << io.readpartial(0xFFFF))
70
+ end
71
+ end
72
+ end
61
73
  rescue SignalException => ex
62
74
  warn "Moneta::Server - #{ex.message}"
63
- raise if ex.signo == 15 # SIGTERM
64
- rescue IOError => ex
65
- warn "Moneta::Server - #{ex.message}" unless ex.message =~ /closed/
66
- @clients.delete(client) if client
67
- @clients.reject!(&:closed?)
75
+ raise if ex.signo == 15 || ex.signo == 2 # SIGTERM or SIGINT
68
76
  rescue Exception => ex
69
77
  warn "Moneta::Server - #{ex.message}"
70
- write(client, Error.new(ex.message)) if client
71
78
  end
72
79
 
73
- def accept
74
- ios = IO.select(@clients, nil, @clients, TIMEOUT)
75
- return nil unless ios
76
- ios[2].each do |io|
77
- io.close
78
- @clients.delete(io)
79
- end
80
- ios[0].each do |io|
81
- if io == @server
82
- client = @server.accept
83
- @clients << client if client
84
- else
85
- return io unless io.eof?
86
- @clients.delete(io)
87
- end
88
- end
89
- nil
80
+ def delete_client(io)
81
+ @ios.delete(io)
82
+ @clients.delete(io)
83
+ end
84
+
85
+ def pack(o)
86
+ s = Marshal.dump(o)
87
+ [s.bytesize].pack('N') << s
90
88
  end
91
89
 
92
- def handle(client)
93
- method, *args = read(client)
90
+ def handle(io, buffer)
91
+ buffer = @clients[io]
92
+ return if buffer.bytesize < 8 # At least 4 bytes for the marshalled array
93
+ size = buffer[0,4].unpack('N').first
94
+ if size > MAXSIZE
95
+ delete_client(io)
96
+ return
97
+ end
98
+ return if buffer.bytesize < 4 + size
99
+ buffer.slice!(0, 4)
100
+ method, *args = Marshal.load(buffer.slice!(0, size))
94
101
  case method
95
102
  when :key?, :load, :delete, :increment, :create, :features
96
- write(client, @store.send(method, *args))
103
+ io.write(pack @store.send(method, *args))
97
104
  when :store, :clear
98
105
  @store.send(method, *args)
99
- client.write(@nil ||= pack(nil))
106
+ io.write(@nil ||= pack(nil))
100
107
  else
101
108
  raise 'Invalid method call'
102
109
  end
110
+ rescue IOError => ex
111
+ warn "Moneta::Server - #{ex.message}" unless ex.message =~ /closed/
112
+ delete_client(io)
113
+ rescue Exception => ex
114
+ warn "Moneta::Server - #{ex.message}"
115
+ io.write(pack Exception.new(ex.message))
116
+ end
117
+
118
+ def start(options)
119
+ if @socket = options[:socket]
120
+ begin
121
+ UNIXServer.open(@socket)
122
+ rescue Errno::EADDRINUSE
123
+ if client = (UNIXSocket.open(@socket) rescue nil)
124
+ client.close
125
+ raise
126
+ end
127
+ File.unlink(@socket)
128
+ tries ||= 0
129
+ (tries += 1) < 3 ? retry : raise
130
+ end
131
+ else
132
+ TCPServer.open(options[:host] || '127.0.0.1', options[:port] || 9000)
133
+ end
103
134
  end
104
135
  end
105
136
  end