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 +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
|