moneta 0.7.18 → 0.7.19
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +19 -19
- data/CHANGES +6 -0
- data/CONTRIBUTORS +1 -0
- data/Gemfile +9 -3
- data/SPEC.md +1 -1
- data/lib/action_dispatch/middleware/session/moneta_store.rb +1 -0
- data/lib/moneta.rb +0 -1
- data/lib/moneta/adapters/client.rb +26 -21
- data/lib/moneta/adapters/memcached/dalli.rb +1 -1
- data/lib/moneta/adapters/memcached/native.rb +1 -1
- data/lib/moneta/mixins.rb +0 -21
- data/lib/moneta/pool.rb +1 -1
- data/lib/moneta/server.rb +69 -38
- data/lib/moneta/shared.rb +21 -13
- data/lib/moneta/version.rb +1 -1
- data/lib/rack/session/moneta.rb +1 -1
- data/script/benchmarks +3 -1
- data/script/generate-specs +29 -20
- data/script/install-bundle +11 -1
- data/script/kill-travis +1 -1
- data/script/parallel-tests +95 -0
- data/script/upload-bundle +1 -1
- data/spec/helper.rb +43 -10
- data/spec/moneta/adapter_activerecord_spec.rb +1 -2
- data/spec/moneta/adapter_fog_spec.rb +1 -1
- data/spec/moneta/simple_fog_spec.rb +1 -1
- data/spec/moneta/simple_fog_with_expires_spec.rb +1 -1
- data/spec/moneta/weak_create_spec.rb +8 -3
- data/spec/moneta/weak_increment_spec.rb +8 -3
- data/spec/monetaspecs.rb +647 -647
- data/spec/quality_spec.rb +51 -0
- metadata +5 -3
- data/Rakefile +0 -99
data/lib/moneta/shared.rb
CHANGED
@@ -36,24 +36,32 @@ module Moneta
|
|
36
36
|
protected
|
37
37
|
|
38
38
|
def wrap(*args)
|
39
|
-
|
39
|
+
connect
|
40
40
|
yield
|
41
|
+
end
|
42
|
+
|
43
|
+
def connect
|
44
|
+
@adapter ||= Adapters::Client.new(@options)
|
41
45
|
rescue Errno::ECONNREFUSED, Errno::ENOENT => ex
|
46
|
+
start_server
|
42
47
|
tries ||= 0
|
43
48
|
warn "Moneta::Shared - Failed to connect: #{ex.message}" if tries > 0
|
44
|
-
begin
|
45
|
-
# TODO: Implement this using forking (MRI) and threading (JRuby)
|
46
|
-
# to get maximal performance
|
47
|
-
@adapter = Lock.new(@builder.build.last)
|
48
|
-
@server = Server.new(@adapter, @options)
|
49
|
-
@thread = Thread.new { @server.run }
|
50
|
-
sleep 0.1 until @server.running?
|
51
|
-
rescue Exception => ex
|
52
|
-
warn "Moneta::Shared - Failed to start server: #{ex.message}"
|
53
|
-
@adapter.close if @adapter
|
54
|
-
@adapter = nil
|
55
|
-
end
|
56
49
|
(tries += 1) < 3 ? retry : raise
|
57
50
|
end
|
51
|
+
|
52
|
+
# TODO: Implement this using forking (MRI) and threading (JRuby)
|
53
|
+
# to get maximal performance
|
54
|
+
def start_server
|
55
|
+
@adapter = Lock.new(@builder.build.last)
|
56
|
+
@server = Server.new(@adapter, @options)
|
57
|
+
@thread = Thread.new { @server.run }
|
58
|
+
sleep 0.1 until @server.running?
|
59
|
+
rescue Exception => ex
|
60
|
+
@adapter.close if @adapter
|
61
|
+
@adapter = nil
|
62
|
+
@server = nil
|
63
|
+
@thread = nil
|
64
|
+
warn "Moneta::Shared - Failed to start server: #{ex.message}"
|
65
|
+
end
|
58
66
|
end
|
59
67
|
end
|
data/lib/moneta/version.rb
CHANGED
data/lib/rack/session/moneta.rb
CHANGED
data/script/benchmarks
CHANGED
@@ -28,7 +28,6 @@ end
|
|
28
28
|
|
29
29
|
class MonetaBenchmarks
|
30
30
|
DIR = __FILE__ + '.tmp'
|
31
|
-
FileUtils.mkpath(DIR)
|
32
31
|
|
33
32
|
STORES = {
|
34
33
|
# SDBM accepts only very short key/value pairs (1k for both)
|
@@ -378,12 +377,15 @@ class MonetaBenchmarks
|
|
378
377
|
end
|
379
378
|
|
380
379
|
def run
|
380
|
+
FileUtils.rm_rf(DIR)
|
381
|
+
FileUtils.mkpath(DIR)
|
381
382
|
start_servers
|
382
383
|
test_stores
|
383
384
|
print_config
|
384
385
|
generate_data
|
385
386
|
run_benchmarks
|
386
387
|
print_summary
|
388
|
+
FileUtils.rm_rf(DIR)
|
387
389
|
end
|
388
390
|
end
|
389
391
|
|
data/script/generate-specs
CHANGED
@@ -479,7 +479,7 @@ end
|
|
479
479
|
:options => ":aws_access_key_id => 'fake_access_key_id',
|
480
480
|
:aws_secret_access_key => 'fake_secret_access_key',
|
481
481
|
:provider => 'AWS',
|
482
|
-
:dir => '
|
482
|
+
:dir => 'simple_fog'",
|
483
483
|
# Put Fog into testing mode
|
484
484
|
:preamble => "require 'fog'\nFog.mock!\n"
|
485
485
|
},
|
@@ -488,27 +488,37 @@ end
|
|
488
488
|
:options => ":aws_access_key_id => 'fake_access_key_id',
|
489
489
|
:aws_secret_access_key => 'fake_secret_access_key',
|
490
490
|
:provider => 'AWS',
|
491
|
-
:dir => '
|
491
|
+
:dir => 'simple_fog_with_expires',
|
492
492
|
:expires => true",
|
493
493
|
# Put Fog into testing mode
|
494
494
|
:preamble => "require 'fog'\nFog.mock!\n",
|
495
495
|
:specs => STANDARD_SPECS.without_increment.without_create.with_expires
|
496
496
|
},
|
497
497
|
'weak_create' => {
|
498
|
-
|
498
|
+
# Put Fog into testing mode
|
499
|
+
:preamble => "require 'fog'\nFog.mock!\n",
|
499
500
|
:build => %{Moneta.build do
|
500
501
|
use :WeakCreate
|
501
|
-
adapter :
|
502
|
+
adapter :Fog,
|
503
|
+
:aws_access_key_id => 'fake_access_key_id',
|
504
|
+
:aws_secret_access_key => 'fake_secret_access_key',
|
505
|
+
:provider => 'AWS',
|
506
|
+
:dir => 'weak_create'
|
502
507
|
end},
|
503
|
-
:specs => ADAPTER_SPECS.without_increment.without_concurrent
|
508
|
+
:specs => ADAPTER_SPECS.without_increment.without_concurrent.returnsame
|
504
509
|
},
|
505
510
|
'weak_increment' => {
|
506
|
-
|
511
|
+
# Put Fog into testing mode
|
512
|
+
:preamble => "require 'fog'\nFog.mock!\n",
|
507
513
|
:build => %{Moneta.build do
|
508
514
|
use :WeakIncrement
|
509
|
-
adapter :
|
515
|
+
adapter :Fog,
|
516
|
+
:aws_access_key_id => 'fake_access_key_id',
|
517
|
+
:aws_secret_access_key => 'fake_secret_access_key',
|
518
|
+
:provider => 'AWS',
|
519
|
+
:dir => 'weak_increment'
|
510
520
|
end},
|
511
|
-
:specs => ADAPTER_SPECS.without_create.without_concurrent
|
521
|
+
:specs => ADAPTER_SPECS.without_create.without_concurrent.returnsame
|
512
522
|
},
|
513
523
|
'expires_memory' => {
|
514
524
|
:build => %{Moneta.build do
|
@@ -1162,8 +1172,7 @@ end}
|
|
1162
1172
|
it 'updates an existing key/value' do
|
1163
1173
|
store['foo/bar'] = '1'
|
1164
1174
|
store['foo/bar'] = '2'
|
1165
|
-
|
1166
|
-
records.count.should == 1
|
1175
|
+
store.table.where(:k => 'foo/bar').count.should == 1
|
1167
1176
|
end
|
1168
1177
|
|
1169
1178
|
it 'supports different tables same database' do
|
@@ -1283,7 +1292,7 @@ end
|
|
1283
1292
|
:build => "Moneta::Adapters::Fog.new(:aws_access_key_id => 'fake_access_key_id',
|
1284
1293
|
:aws_secret_access_key => 'fake_secret_access_key',
|
1285
1294
|
:provider => 'AWS',
|
1286
|
-
:dir => '
|
1295
|
+
:dir => 'adapter_fog')",
|
1287
1296
|
# Put Fog into testing mode
|
1288
1297
|
:preamble => "require 'fog'\nFog.mock!\n",
|
1289
1298
|
# Fog returns same object in mocking mode (in-memory store)
|
@@ -1682,7 +1691,7 @@ it 'guarantees that the same value is returned when setting a key' do
|
|
1682
1691
|
(store[#{key1}] = value).should equal(value)
|
1683
1692
|
end
|
1684
1693
|
|
1685
|
-
it 'returns false from key? if a key is not available' do
|
1694
|
+
it 'returns false from #key? if a key is not available' do
|
1686
1695
|
store.key?(#{key1}).should be_false
|
1687
1696
|
end
|
1688
1697
|
|
@@ -1730,7 +1739,7 @@ end}
|
|
1730
1739
|
store.load(#{key1}).should == #{val1}
|
1731
1740
|
end
|
1732
1741
|
|
1733
|
-
it 'returns true from key? if a key is available' do
|
1742
|
+
it 'returns true from #key? if a key is available' do
|
1734
1743
|
store[#{key1}] = #{val1}
|
1735
1744
|
store.key?(#{key1}).should be_true
|
1736
1745
|
end
|
@@ -1908,7 +1917,7 @@ it 'supports strict expires on store and load' do
|
|
1908
1917
|
store.load('key1').should be_nil
|
1909
1918
|
end
|
1910
1919
|
|
1911
|
-
it 'supports expires on store and key?', :retry => 3 do
|
1920
|
+
it 'supports expires on store and #key?', :retry => 3 do
|
1912
1921
|
store.store('key1', 'val1', :expires => 3)
|
1913
1922
|
store.key?('key1').should be_true
|
1914
1923
|
sleep 1
|
@@ -1917,7 +1926,7 @@ it 'supports expires on store and key?', :retry => 3 do
|
|
1917
1926
|
store.key?('key1').should be_false
|
1918
1927
|
end
|
1919
1928
|
|
1920
|
-
it 'supports strict expires on store and key?' do
|
1929
|
+
it 'supports strict expires on store and #key?' do
|
1921
1930
|
store.store('key1', 'val1', :expires => 2)
|
1922
1931
|
store.key?('key1').should be_true
|
1923
1932
|
sleep 3 # Sleep 3 seconds because after 2 seconds the value can still exist!
|
@@ -1950,7 +1959,7 @@ it 'supports false as no-expires in load' do
|
|
1950
1959
|
store.load('key1').should == 'val1'
|
1951
1960
|
end
|
1952
1961
|
|
1953
|
-
it 'supports updating the expiration time in key?', :retry => 3 do
|
1962
|
+
it 'supports updating the expiration time in #key?', :retry => 3 do
|
1954
1963
|
store.store('key2', 'val2', :expires => 3)
|
1955
1964
|
store['key2'].should == 'val2'
|
1956
1965
|
sleep 1
|
@@ -1962,14 +1971,14 @@ it 'supports updating the expiration time in key?', :retry => 3 do
|
|
1962
1971
|
store['key2'].should be_nil
|
1963
1972
|
end
|
1964
1973
|
|
1965
|
-
it 'supports 0 as no-expires in key?' do
|
1974
|
+
it 'supports 0 as no-expires in #key?' do
|
1966
1975
|
store.store('key1', 'val1', :expires => 2)
|
1967
1976
|
store.key?('key1', :expires => 0).should be_true
|
1968
1977
|
sleep 3
|
1969
1978
|
store['key1'].should == 'val1'
|
1970
1979
|
end
|
1971
1980
|
|
1972
|
-
it 'supports false as no-expires in key?' do
|
1981
|
+
it 'supports false as no-expires in #key?' do
|
1973
1982
|
store.store('key1', 'val1', :expires => 2)
|
1974
1983
|
store.key?('key1', :expires => false ).should be_true
|
1975
1984
|
sleep 3
|
@@ -2034,7 +2043,7 @@ it 'supports false as no-expires on store and []' do
|
|
2034
2043
|
store['key1'].should == 'val1'
|
2035
2044
|
end
|
2036
2045
|
|
2037
|
-
it 'does not update the expiration time in key? when not asked to do so', :retry => 3 do
|
2046
|
+
it 'does not update the expiration time in #key? when not asked to do so', :retry => 3 do
|
2038
2047
|
store.store('key1', 'val1', :expires => 1)
|
2039
2048
|
store.key?('key1').should be_true
|
2040
2049
|
store.key?('key1', :expires => nil).should be_true
|
@@ -2307,7 +2316,7 @@ it 'refuses to store to keys that cannot be marshalled' do
|
|
2307
2316
|
end.to raise_error(marshal_error)
|
2308
2317
|
end
|
2309
2318
|
|
2310
|
-
it 'refuses to check for key? if the key cannot be marshalled' do
|
2319
|
+
it 'refuses to check for #key? if the key cannot be marshalled' do
|
2311
2320
|
expect do
|
2312
2321
|
store.key? Struct.new(:foo).new(:bar)
|
2313
2322
|
end.to raise_error(marshal_error)
|
data/script/install-bundle
CHANGED
@@ -16,10 +16,20 @@ end
|
|
16
16
|
|
17
17
|
BUNDLE_FILE = "moneta-bundle-#{RUBY_VERSION}-#{ruby}.tar.gz"
|
18
18
|
|
19
|
-
if system("curl -u moneta:#{ENV['DAV_PW']} -k -o #{BUNDLE_FILE} https://mendler.net/dav/#{BUNDLE_FILE}")
|
19
|
+
if system("curl -f -u moneta:#{ENV['DAV_PW']} -k -o #{BUNDLE_FILE} https://mendler.net/dav/#{BUNDLE_FILE}")
|
20
20
|
cmd 'rm -rf .bundle'
|
21
21
|
cmd "tar -xpf #{BUNDLE_FILE}"
|
22
22
|
cmd "rm -f #{BUNDLE_FILE}"
|
23
|
+
|
24
|
+
# Write newest moneta version in Gemfile.lock
|
25
|
+
require './lib/moneta/version'
|
26
|
+
File.open('Gemfile.lock', 'r+') do |fp|
|
27
|
+
content = fp.read
|
28
|
+
content.gsub!(/moneta\s*\(.*?\)/, "moneta (#{Moneta::VERSION})")
|
29
|
+
fp.truncate(0)
|
30
|
+
fp.pos = 0
|
31
|
+
fp.write(content)
|
32
|
+
end
|
23
33
|
else
|
24
34
|
cmd 'bundle install --path .bundle'
|
25
35
|
cmd 'bundle update'
|
data/script/kill-travis
CHANGED
@@ -0,0 +1,95 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
def rspec(spec)
|
4
|
+
if system("rspec #{spec}")
|
5
|
+
true
|
6
|
+
elsif sig = $?.termsig
|
7
|
+
found = Signal.list.to_a.select {|name, id| id == sig }.first
|
8
|
+
puts "\e[31m########## SIG#{found ? found.first : sig} rspec #{spec} ##########\e[0m"
|
9
|
+
false
|
10
|
+
else
|
11
|
+
puts "rspec terminated with #{$?.exitstatus}"
|
12
|
+
false
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
ENV['PARALLEL_TESTS'] = 'yes'
|
17
|
+
|
18
|
+
specs = Dir['spec/*/*_spec.rb'].sort
|
19
|
+
|
20
|
+
# Shuffle specs to ensure equal distribution over the test groups
|
21
|
+
# We have to shuffle with the same seed every time because rake is started
|
22
|
+
# multiple times!
|
23
|
+
old_seed = srand(43)
|
24
|
+
specs.shuffle!
|
25
|
+
srand(old_seed)
|
26
|
+
|
27
|
+
# FIXME:
|
28
|
+
#
|
29
|
+
# * QuickLZ segfaults because of an assertion
|
30
|
+
# QuickLZ is also not maintained on Github, but on Bitbucket
|
31
|
+
# and I don't know where the issue tracker is.
|
32
|
+
#
|
33
|
+
# * PStore increment/locking doesn't work correctly on JRuby
|
34
|
+
#
|
35
|
+
unstable = %w(quicklz riak cassandra)
|
36
|
+
unstable += %w(pstore) if defined?(JRUBY_VERSION)
|
37
|
+
|
38
|
+
unstable_re = /#{unstable.join('|')}/
|
39
|
+
unstable = specs.select {|s| s =~ unstable_re }
|
40
|
+
specs -= unstable
|
41
|
+
|
42
|
+
group = ARGV.first || '1/1'
|
43
|
+
case group
|
44
|
+
when /^(\d+)\/(\d+)$/
|
45
|
+
n = $1.to_i
|
46
|
+
max = $2.to_i
|
47
|
+
if n == max
|
48
|
+
specs = specs[(n-1)*(specs.size/max)..-1]
|
49
|
+
else
|
50
|
+
specs = specs[(n-1)*(specs.size/max), specs.size/max]
|
51
|
+
end
|
52
|
+
when 'unstable'
|
53
|
+
specs = unstable
|
54
|
+
else
|
55
|
+
puts "Invalid test group #{group}"
|
56
|
+
exit 1
|
57
|
+
end
|
58
|
+
|
59
|
+
puts "The following specs will be executed:\n\t#{specs.join "\n\t"}\n\n"
|
60
|
+
|
61
|
+
# Memcached and Redis specs cannot be used in parallel
|
62
|
+
# because of flushing and lacking namespaces
|
63
|
+
parallel = []
|
64
|
+
%w(memcached redis client shared riak tokyotyrant couch cassandra).each do |name|
|
65
|
+
serial = specs.select { |s| s.include?(name) }
|
66
|
+
unless serial.empty?
|
67
|
+
specs -= serial
|
68
|
+
parallel << serial
|
69
|
+
end
|
70
|
+
end
|
71
|
+
parallel += specs.map {|s| [s] }
|
72
|
+
|
73
|
+
threads = []
|
74
|
+
failed = false
|
75
|
+
parallel.each do |serial|
|
76
|
+
threads << Thread.new do
|
77
|
+
begin
|
78
|
+
serial.each do |spec|
|
79
|
+
failed = true unless rspec(spec)
|
80
|
+
end
|
81
|
+
ensure
|
82
|
+
threads.delete Thread.current
|
83
|
+
end
|
84
|
+
end
|
85
|
+
sleep 0.1
|
86
|
+
sleep 0.1 while threads.size >= 5
|
87
|
+
end
|
88
|
+
sleep 0.1 until threads.empty?
|
89
|
+
|
90
|
+
if failed
|
91
|
+
puts "\e[31m########## MONETA TESTSUITE FAILED ##########\e[0m"
|
92
|
+
exit 1
|
93
|
+
end
|
94
|
+
|
95
|
+
puts "\e[32m########## MONETA TESTSUITE SUCCEDED ##########\e[0m"
|
data/script/upload-bundle
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
#!/bin/bash
|
2
|
-
curl -u moneta:$DAV_PW -k -T moneta-bundle-*.tar.gz https://mendler.net/dav/ || echo 'Nothing uploaded'
|
2
|
+
curl -f -u moneta:$DAV_PW -k -T moneta-bundle-*.tar.gz https://mendler.net/dav/ || echo 'Nothing uploaded'
|
data/spec/helper.rb
CHANGED
@@ -1,23 +1,57 @@
|
|
1
1
|
require 'rspec'
|
2
|
-
require 'rspec/core/formatters/
|
2
|
+
require 'rspec/core/formatters/base_text_formatter'
|
3
3
|
require 'rspec/retry'
|
4
4
|
require 'moneta'
|
5
5
|
require 'fileutils'
|
6
6
|
require 'monetaspecs'
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
class MonetaParallelFormatter < RSpec::Core::Formatters::BaseTextFormatter
|
9
|
+
def start(*args)
|
10
|
+
|
11
|
+
output.puts colorise_summary("STARTING #{ARGV.join(' ')}")
|
12
|
+
@stopped = false
|
13
|
+
@passed_count = 0
|
14
|
+
@heartbeat = Thread.new do
|
15
|
+
count = 0
|
16
|
+
until @stopped
|
17
|
+
if (count += 1) % 60 == 0
|
18
|
+
output.puts(color("RUNNING #{ARGV.join(' ')} - #{@passed_count} passed, #{failed_examples.size} failures",
|
19
|
+
failed_examples.empty? ? RSpec.configuration.success_color : RSpec.configuration.failure_color))
|
20
|
+
end
|
21
|
+
sleep 0.5
|
22
|
+
end
|
12
23
|
end
|
13
24
|
end
|
25
|
+
|
26
|
+
def example_passed(example)
|
27
|
+
super
|
28
|
+
@passed_count += 1
|
29
|
+
end
|
30
|
+
|
31
|
+
def stop
|
32
|
+
@stopped = true
|
33
|
+
@heartbeat.join
|
34
|
+
end
|
35
|
+
|
36
|
+
def dump_summary(duration, example_count, failure_count, pending_count)
|
37
|
+
@duration = duration
|
38
|
+
@example_count = example_count
|
39
|
+
@failure_count = failure_count
|
40
|
+
@pending_count = pending_count
|
41
|
+
output.puts colorise_summary(summary_line(example_count, failure_count, pending_count))
|
42
|
+
dump_commands_to_rerun_failed_examples
|
43
|
+
end
|
44
|
+
|
45
|
+
def summary_line(example_count, failure_count, pending_count)
|
46
|
+
"FINISHED #{ARGV.join(' ')} in #{format_duration(duration)} - #{super}"
|
47
|
+
end
|
14
48
|
end
|
15
49
|
|
16
50
|
RSpec.configure do |config|
|
17
51
|
config.verbose_retry = true
|
18
52
|
config.color_enabled = true
|
19
53
|
config.tty = true
|
20
|
-
config.formatter = :progress
|
54
|
+
config.formatter = ENV['PARALLEL_TESTS'] ? MonetaParallelFormatter : :progress
|
21
55
|
end
|
22
56
|
|
23
57
|
# Disable jruby stdout pollution by memcached
|
@@ -135,10 +169,9 @@ shared_context 'setup_store' do
|
|
135
169
|
end
|
136
170
|
|
137
171
|
after do
|
138
|
-
|
139
|
-
|
140
|
-
@
|
141
|
-
@log = nil
|
172
|
+
if store
|
173
|
+
store.close.should == nil
|
174
|
+
@store = nil
|
142
175
|
end
|
143
176
|
end
|
144
177
|
end
|