moneta 1.2.1 → 1.3.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.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.rubocop.yml +1 -1
- data/.travis.yml +10 -4
- data/CHANGES +9 -0
- data/Gemfile +7 -5
- data/README.md +9 -6
- data/feature_matrix.yaml +2 -1
- data/lib/moneta/adapters/client.rb +56 -19
- data/lib/moneta/adapters/couch.rb +5 -0
- data/lib/moneta/adapters/mongo/moped.rb +4 -1
- data/lib/moneta/builder.rb +2 -2
- data/lib/moneta/lock.rb +6 -1
- data/lib/moneta/pool.rb +12 -0
- data/lib/moneta/proxy.rb +1 -1
- data/lib/moneta/server.rb +215 -61
- data/lib/moneta/shared.rb +13 -7
- data/lib/moneta/transformer.rb +50 -8
- data/lib/moneta/transformer/config.rb +59 -40
- data/lib/moneta/version.rb +1 -1
- data/moneta.gemspec +2 -2
- data/script/benchmarks +6 -1
- data/script/contributors +1 -2
- data/script/start-couchdb +27 -0
- data/script/start-hbase +2 -2
- data/script/start-services +3 -3
- data/spec/features/store.rb +3 -3
- data/spec/features/transform_value.rb +27 -21
- data/spec/helper.rb +52 -53
- data/spec/moneta/adapters/activerecord/standard_activerecord_spec.rb +1 -1
- data/spec/moneta/adapters/activerecord/standard_activerecord_with_expires_spec.rb +1 -1
- data/spec/moneta/adapters/cassandra/standard_cassandra_spec.rb +1 -1
- data/spec/moneta/adapters/client/adapter_client_spec.rb +6 -6
- data/spec/moneta/adapters/client/client_helper.rb +24 -0
- data/spec/moneta/adapters/client/standard_client_tcp_spec.rb +8 -8
- data/spec/moneta/adapters/client/standard_client_unix_spec.rb +23 -7
- data/spec/moneta/adapters/couch/adapter_couch_spec.rb +1 -1
- data/spec/moneta/adapters/couch/standard_couch_spec.rb +2 -2
- data/spec/moneta/adapters/couch/standard_couch_with_expires_spec.rb +2 -2
- data/spec/moneta/adapters/daybreak/standard_daybreak_spec.rb +1 -1
- data/spec/moneta/adapters/daybreak/standard_daybreak_with_expires_spec.rb +1 -1
- data/spec/moneta/adapters/dbm/standard_dbm_spec.rb +1 -1
- data/spec/moneta/adapters/dbm/standard_dbm_with_expires_spec.rb +1 -1
- data/spec/moneta/adapters/file/standard_file_spec.rb +2 -2
- data/spec/moneta/adapters/file/standard_file_with_expires_spec.rb +1 -1
- data/spec/moneta/adapters/gdbm/standard_gdbm_spec.rb +1 -1
- data/spec/moneta/adapters/gdbm/standard_gdbm_with_expires_spec.rb +1 -1
- data/spec/moneta/adapters/kyotocabinet/adapter_kyotocabinet_spec.rb +1 -1
- data/spec/moneta/adapters/kyotocabinet/standard_kyotocabinet_spec.rb +2 -2
- data/spec/moneta/adapters/kyotocabinet/standard_kyotocabinet_with_expires_spec.rb +2 -2
- data/spec/moneta/adapters/leveldb/standard_leveldb_spec.rb +1 -1
- data/spec/moneta/adapters/leveldb/standard_leveldb_with_expires_spec.rb +1 -1
- data/spec/moneta/adapters/lmdb/standard_lmdb_spec.rb +1 -1
- data/spec/moneta/adapters/lmdb/standard_lmdb_with_expires_spec.rb +1 -1
- data/spec/moneta/adapters/lruhash/standard_lruhash_spec.rb +1 -1
- data/spec/moneta/adapters/lruhash/standard_lruhash_with_expires_spec.rb +1 -1
- data/spec/moneta/adapters/memory/standard_memory_spec.rb +1 -1
- data/spec/moneta/adapters/memory/standard_memory_with_compress_spec.rb +1 -1
- data/spec/moneta/adapters/memory/standard_memory_with_expires_spec.rb +1 -1
- data/spec/moneta/adapters/memory/standard_memory_with_json_key_serializer_spec.rb +1 -1
- data/spec/moneta/adapters/memory/standard_memory_with_json_serializer_spec.rb +1 -1
- data/spec/moneta/adapters/memory/standard_memory_with_json_value_serializer_spec.rb +2 -2
- data/spec/moneta/adapters/memory/standard_memory_with_prefix_spec.rb +39 -2
- data/spec/moneta/adapters/memory/standard_memory_with_snappy_compress_spec.rb +2 -2
- data/spec/moneta/adapters/mongo/adapter_mongo_moped_spec.rb +4 -3
- data/spec/moneta/adapters/mongo/adapter_mongo_moped_with_default_expires_spec.rb +5 -3
- data/spec/moneta/adapters/mongo/adapter_mongo_official_spec.rb +4 -2
- data/spec/moneta/adapters/mongo/adapter_mongo_official_with_default_expires_spec.rb +5 -3
- data/spec/moneta/adapters/mongo/adapter_mongo_spec.rb +3 -2
- data/spec/moneta/adapters/mongo/adapter_mongo_with_default_expires_spec.rb +5 -3
- data/spec/moneta/adapters/mongo/standard_mongo_moped_spec.rb +2 -2
- data/spec/moneta/adapters/mongo/standard_mongo_official_spec.rb +2 -2
- data/spec/moneta/adapters/mongo/standard_mongo_spec.rb +2 -2
- data/spec/moneta/adapters/pstore/standard_pstore_spec.rb +1 -1
- data/spec/moneta/adapters/pstore/standard_pstore_with_expires_spec.rb +1 -1
- data/spec/moneta/adapters/redis/standard_redis_spec.rb +1 -1
- data/spec/moneta/adapters/sdbm/standard_sdbm_spec.rb +1 -1
- data/spec/moneta/adapters/sdbm/standard_sdbm_with_expires_spec.rb +1 -1
- data/spec/moneta/adapters/sequel/standard_sequel_spec.rb +1 -1
- data/spec/moneta/adapters/sequel/standard_sequel_with_expires_spec.rb +1 -1
- data/spec/moneta/adapters/sqlite/standard_sqlite_spec.rb +1 -1
- data/spec/moneta/adapters/sqlite/standard_sqlite_with_expires_spec.rb +1 -1
- data/spec/moneta/adapters/tdb/standard_tdb_spec.rb +1 -1
- data/spec/moneta/adapters/tdb/standard_tdb_with_expires_spec.rb +1 -1
- data/spec/moneta/adapters/tokyocabinet/standard_tokyocabinet_spec.rb +1 -1
- data/spec/moneta/adapters/tokyocabinet/standard_tokyocabinet_with_expires_spec.rb +1 -1
- data/spec/moneta/adapters/yaml/standard_yaml_spec.rb +1 -1
- data/spec/moneta/adapters/yaml/standard_yaml_with_expires_spec.rb +1 -1
- data/spec/moneta/builder_spec.rb +22 -0
- data/spec/moneta/proxies/expires/expires_file_spec.rb +1 -1
- data/spec/moneta/proxies/shared/shared_tcp_spec.rb +14 -4
- data/spec/moneta/proxies/shared/shared_unix_spec.rb +4 -4
- data/spec/moneta/proxies/transformer/transformer_bencode_spec.rb +1 -1
- data/spec/moneta/proxies/transformer/transformer_bert_spec.rb +3 -3
- data/spec/moneta/proxies/transformer/transformer_bson_spec.rb +2 -2
- data/spec/moneta/proxies/transformer/transformer_json_spec.rb +1 -1
- data/spec/moneta/proxies/transformer/transformer_key_marshal_spec.rb +1 -1
- data/spec/moneta/proxies/transformer/transformer_key_yaml_spec.rb +1 -1
- data/spec/moneta/proxies/transformer/transformer_marshal_base64_spec.rb +1 -1
- data/spec/moneta/proxies/transformer/transformer_marshal_escape_spec.rb +1 -1
- data/spec/moneta/proxies/transformer/transformer_marshal_hex_spec.rb +1 -1
- data/spec/moneta/proxies/transformer/transformer_marshal_hmac_spec.rb +1 -1
- data/spec/moneta/proxies/transformer/transformer_marshal_prefix_base64_spec.rb +33 -0
- data/spec/moneta/proxies/transformer/transformer_marshal_prefix_spec.rb +1 -1
- data/spec/moneta/proxies/transformer/transformer_marshal_qp_spec.rb +1 -1
- data/spec/moneta/proxies/transformer/transformer_marshal_spec.rb +1 -1
- data/spec/moneta/proxies/transformer/transformer_marshal_urlsafe_base64_spec.rb +1 -1
- data/spec/moneta/proxies/transformer/transformer_marshal_uuencode_spec.rb +1 -1
- data/spec/moneta/proxies/transformer/transformer_msgpack_spec.rb +1 -1
- data/spec/moneta/proxies/transformer/transformer_ox_spec.rb +1 -1
- data/spec/moneta/proxies/transformer/transformer_php_spec.rb +1 -1
- data/spec/moneta/proxies/transformer/transformer_tnet_spec.rb +1 -1
- data/spec/moneta/proxies/transformer/transformer_yaml_spec.rb +2 -2
- data/spec/moneta/proxies/weak_each_key/weak_each_key_spec.rb +0 -2
- data/spec/support/mongo_helper.rb +12 -0
- metadata +18 -12
- data/script/reconfigure-couchdb +0 -13
data/lib/moneta/shared.rb
CHANGED
@@ -11,8 +11,6 @@ module Moneta
|
|
11
11
|
#
|
12
12
|
# @api public
|
13
13
|
class Shared < Wrapper
|
14
|
-
not_supports :each_key
|
15
|
-
|
16
14
|
# @param [Hash] options
|
17
15
|
# @option options [Integer] :port (9000) TCP port
|
18
16
|
# @option options [String] :host Server hostname
|
@@ -25,7 +23,7 @@ module Moneta
|
|
25
23
|
|
26
24
|
# (see Proxy#close)
|
27
25
|
def close
|
28
|
-
if
|
26
|
+
if server?
|
29
27
|
@server.stop
|
30
28
|
@thread.join
|
31
29
|
@server = @thread = nil
|
@@ -36,13 +34,20 @@ module Moneta
|
|
36
34
|
end
|
37
35
|
end
|
38
36
|
|
37
|
+
# Returns true if this wrapper is running as the server
|
38
|
+
#
|
39
|
+
# @return [Boolean] wrapper is a server
|
40
|
+
def server?
|
41
|
+
@server != nil
|
42
|
+
end
|
43
|
+
|
39
44
|
protected
|
40
45
|
|
41
46
|
def wrap(*args)
|
42
47
|
connect
|
43
48
|
yield
|
44
49
|
rescue Errno::ECONNRESET, Errno::EPIPE, IOError, SystemCallError
|
45
|
-
@connect_lock.synchronize { close unless
|
50
|
+
@connect_lock.synchronize { close unless server? }
|
46
51
|
tries ||= 0
|
47
52
|
(tries += 1) < 3 ? retry : raise
|
48
53
|
end
|
@@ -52,21 +57,22 @@ module Moneta
|
|
52
57
|
@connect_lock.synchronize do
|
53
58
|
@adapter ||= Adapters::Client.new(@options)
|
54
59
|
end
|
55
|
-
rescue Errno::ECONNREFUSED, Errno::ENOENT => ex
|
60
|
+
rescue Errno::ECONNREFUSED, Errno::ENOENT, IOError => ex
|
56
61
|
start_server
|
57
62
|
tries ||= 0
|
58
63
|
warn "Moneta::Shared - Failed to connect: #{ex.message}" if tries > 0
|
59
|
-
(tries += 1) <
|
64
|
+
(tries += 1) < 10 ? retry : raise
|
60
65
|
end
|
61
66
|
|
62
67
|
# TODO: Implement this using forking (MRI) and threading (JRuby)
|
63
68
|
# to get maximal performance
|
64
69
|
def start_server
|
65
70
|
@connect_lock.synchronize do
|
71
|
+
return if server?
|
66
72
|
begin
|
67
73
|
raise "Adapter already set" if @adapter
|
68
74
|
@adapter = Lock.new(@builder.build.last)
|
69
|
-
raise "Server already set" if
|
75
|
+
raise "Server already set" if server?
|
70
76
|
@server = Server.new(@adapter, @options)
|
71
77
|
@thread = Thread.new { @server.run }
|
72
78
|
sleep 0.1 until @server.running?
|
data/lib/moneta/transformer.rb
CHANGED
@@ -43,12 +43,15 @@ module Moneta
|
|
43
43
|
|
44
44
|
def compile(keys, values)
|
45
45
|
@key_validator ||= compile_validator(KEY_TRANSFORMER)
|
46
|
+
@load_key_validator ||= compile_validator(LOAD_KEY_TRANSFORMER)
|
47
|
+
@test_key_validator ||= compile_validator(TEST_KEY_TRANSFORMER)
|
46
48
|
@value_validator ||= compile_validator(VALUE_TRANSFORMER)
|
47
49
|
|
48
50
|
raise ArgumentError, 'Invalid key transformer chain' if @key_validator !~ keys.map(&:inspect).join
|
49
51
|
raise ArgumentError, 'Invalid value transformer chain' if @value_validator !~ values.map(&:inspect).join
|
50
52
|
|
51
53
|
klass = Class.new(self)
|
54
|
+
compile_each_key_support_clause(klass, keys)
|
52
55
|
klass.class_eval <<-END_EVAL, __FILE__, __LINE__ + 1
|
53
56
|
def initialize(adapter, options = {})
|
54
57
|
super
|
@@ -58,15 +61,17 @@ module Moneta
|
|
58
61
|
END_EVAL
|
59
62
|
|
60
63
|
key, key_opts = compile_transformer(keys, 'key')
|
64
|
+
key_load, key_load_opts = compile_transformer(keys.reverse, 'key', 1) if @load_key_validator =~ keys.map(&:inspect).join
|
65
|
+
key_test, key_test_opts = compile_transformer(keys.reverse, 'key', 4) if @test_key_validator =~ keys.map(&:inspect).join
|
61
66
|
dump, dump_opts = compile_transformer(values, 'value')
|
62
67
|
load, load_opts = compile_transformer(values.reverse, 'value', 1)
|
63
68
|
|
64
69
|
if values.empty?
|
65
|
-
compile_key_transformer(klass, key, key_opts)
|
70
|
+
compile_key_transformer(klass, key, key_opts, key_load, key_load_opts, key_test, key_test_opts)
|
66
71
|
elsif keys.empty?
|
67
72
|
compile_value_transformer(klass, load, load_opts, dump, dump_opts)
|
68
73
|
else
|
69
|
-
compile_key_value_transformer(klass, key, key_opts, load, load_opts, dump, dump_opts)
|
74
|
+
compile_key_value_transformer(klass, key, key_opts, key_load, key_load_opts, key_test, key_test_opts, load, load_opts, dump, dump_opts)
|
70
75
|
end
|
71
76
|
|
72
77
|
klass
|
@@ -77,13 +82,28 @@ module Moneta
|
|
77
82
|
options.empty? ? 'options' : "Utils.without(options, #{options.map(&:to_sym).map(&:inspect).join(', ')})"
|
78
83
|
end
|
79
84
|
|
80
|
-
def
|
85
|
+
def compile_each_key_support_clause(klass, keys)
|
81
86
|
klass.class_eval <<-END_EVAL, __FILE__, __LINE__ + 1
|
82
|
-
not_supports :each_key
|
87
|
+
#{'not_supports :each_key' if @load_key_validator !~ keys.map(&:inspect).join}
|
88
|
+
END_EVAL
|
89
|
+
end
|
90
|
+
|
91
|
+
def compile_key_transformer(klass, key, key_opts, key_load, key_load_opts, key_test, key_test_opts)
|
92
|
+
if_key_test = key_load && key_test ? "if #{key_test}" : ''
|
83
93
|
|
94
|
+
klass.class_eval <<-END_EVAL, __FILE__, __LINE__ + 1
|
84
95
|
def key?(key, options = {})
|
85
96
|
@adapter.key?(#{key}, #{without key_opts})
|
86
97
|
end
|
98
|
+
def each_key(&block)
|
99
|
+
raise NotImplementedError, "each_key is not supported on this transformer" \
|
100
|
+
unless supports? :each_key
|
101
|
+
|
102
|
+
return enum_for(:each_key) unless block_given?
|
103
|
+
@adapter.each_key.lazy.map{ |key| #{key_load} #{if_key_test} }.reject(&:nil?).each(&block)
|
104
|
+
|
105
|
+
self
|
106
|
+
end
|
87
107
|
def increment(key, amount = 1, options = {})
|
88
108
|
@adapter.increment(#{key}, amount, #{without key_opts})
|
89
109
|
end
|
@@ -200,13 +220,22 @@ module Moneta
|
|
200
220
|
END_EVAL
|
201
221
|
end
|
202
222
|
|
203
|
-
def compile_key_value_transformer(klass, key, key_opts, load, load_opts, dump, dump_opts)
|
204
|
-
|
205
|
-
not_supports :each_key
|
223
|
+
def compile_key_value_transformer(klass, key, key_opts, key_load, key_load_opts, key_test, key_test_opts, load, load_opts, dump, dump_opts)
|
224
|
+
if_key_test = key_load && key_test ? "if #{key_test}" : ''
|
206
225
|
|
226
|
+
klass.class_eval <<-END_EVAL, __FILE__, __LINE__ + 1
|
207
227
|
def key?(key, options = {})
|
208
228
|
@adapter.key?(#{key}, #{without key_opts})
|
209
229
|
end
|
230
|
+
def each_key(&block)
|
231
|
+
raise NotImplementedError, "each_key is not supported on this transformer" \
|
232
|
+
unless supports? :each_key
|
233
|
+
|
234
|
+
return enum_for(:each_key) { @adapter.each_key.size } unless block_given?
|
235
|
+
@adapter.each_key.lazy.map{ |key| #{key_load} #{if_key_test} }.reject(&:nil?).each(&block)
|
236
|
+
|
237
|
+
self
|
238
|
+
end
|
210
239
|
def increment(key, amount = 1, options = {})
|
211
240
|
@adapter.increment(#{key}, amount, #{without key_opts})
|
212
241
|
end
|
@@ -320,9 +349,15 @@ module Moneta
|
|
320
349
|
raise ArgumentError, "Unknown transformer #{name}" unless t = TRANSFORMER[name]
|
321
350
|
require t[3] if t[3]
|
322
351
|
code = t[idx]
|
352
|
+
code ||= compile_prefix(name: name, transformer: t, value: value) if idx == 4 && var == 'key'
|
353
|
+
|
354
|
+
raise "Undefined command for transformer #{name}" unless code
|
355
|
+
|
323
356
|
options += code.scan(/options\[:(\w+)\]/).flatten
|
324
357
|
value =
|
325
|
-
if t[0] == :serialize && var == 'key'
|
358
|
+
if t[0] == :serialize && var == 'key' && idx == 4
|
359
|
+
"(tmp = #{value}; (false === tmp || '' === tmp) ? false : #{code % 'tmp'})"
|
360
|
+
elsif t[0] == :serialize && var == 'key'
|
326
361
|
"(tmp = #{value}; String === tmp ? tmp : #{code % 'tmp'})"
|
327
362
|
else
|
328
363
|
code % value
|
@@ -336,6 +371,13 @@ module Moneta
|
|
336
371
|
(keys.empty? ? '' : keys.map(&camel_case).join + 'Key') +
|
337
372
|
(values.empty? ? '' : values.map(&camel_case).join + 'Value')
|
338
373
|
end
|
374
|
+
|
375
|
+
def compile_prefix(name:, transformer:, value:)
|
376
|
+
return unless [:encode, :serialize].include?(transformer[0])
|
377
|
+
|
378
|
+
load_val, = compile_transformer([name], value, 1)
|
379
|
+
"(#{load_val} rescue '')"
|
380
|
+
end
|
339
381
|
end
|
340
382
|
end
|
341
383
|
end
|
@@ -2,48 +2,61 @@ module Moneta
|
|
2
2
|
class Transformer
|
3
3
|
# Available key/value transformers
|
4
4
|
TRANSFORMER = {
|
5
|
-
# Name: [ Type, Load, Dump, Library
|
6
|
-
bencode: [ :serialize, '::BEncode.load(%s)', '::BEncode.dump(%s)', 'bencode'
|
7
|
-
bert: [ :serialize, '::BERT.decode(%s)', '::BERT.encode(%s)', 'bert'
|
8
|
-
bson: [ :serialize, 'Helper::BSON.load(%s)', 'Helper::BSON.dump(%s)', 'bson'
|
9
|
-
json: [ :serialize, '::MultiJson.load(%s)', '::MultiJson.dump(%s)', 'multi_json'
|
10
|
-
marshal: [ :serialize, '::Marshal.load(%s)', '::Marshal.dump(%s)'
|
11
|
-
msgpack: [ :serialize, '::MessagePack.unpack(%s)', '::MessagePack.pack(%s)', 'msgpack'
|
12
|
-
ox: [ :serialize, '::Ox.parse_obj(%s)', '::Ox.dump(%s)', 'ox'
|
13
|
-
php: [ :serialize, '::PHP.unserialize(%s)', '::PHP.serialize(%s)',
|
14
|
-
tnet: [ :serialize, '::TNetstring.parse(%s).first', '::TNetstring.dump(%s)', 'tnetstring'
|
15
|
-
yaml: [ :serialize, '::YAML.load(%s)', '::YAML.dump(%s)', 'yaml'
|
16
|
-
bzip2: [ :compress, 'Helper.bunzip2(%s)', 'Helper.bzip2(%s)', 'rbzip2'
|
17
|
-
lz4: [ :compress, '::LZ4.uncompress(%s)', '::LZ4.compress(%s)', 'lz4-ruby'
|
18
|
-
lzma: [ :compress, '::LZMA.decompress(%s)', '::LZMA.compress(%s)', 'lzma'
|
19
|
-
lzo: [ :compress, '::LZO.decompress(%s)', '::LZO.compress(%s)', 'lzoruby'
|
20
|
-
snappy: [ :compress, '::Snappy.inflate(%s)', '::Snappy.deflate(%s)', 'snappy'
|
21
|
-
quicklz: [ :compress, '::QuickLZ.decompress(%s)', '::QuickLZ.compress(%s)', 'qlzruby'
|
22
|
-
zlib: [ :compress, '::Zlib::Inflate.inflate(%s)', '::Zlib::Deflate.deflate(%s)', 'zlib'
|
23
|
-
base64: [ :encode, "%s.unpack('m0').first", "[%s].pack('m0')"
|
5
|
+
# Name: [ Type, Load, Dump, Library Test ],
|
6
|
+
bencode: [ :serialize, '::BEncode.load(%s)', '::BEncode.dump(%s)', 'bencode' ],
|
7
|
+
bert: [ :serialize, '::BERT.decode(%s)', '::BERT.encode(%s)', 'bert' ],
|
8
|
+
bson: [ :serialize, 'Helper::BSON.load(%s)', 'Helper::BSON.dump(%s)', 'bson' ],
|
9
|
+
json: [ :serialize, '::MultiJson.load(%s)', '::MultiJson.dump(%s)', 'multi_json' ],
|
10
|
+
marshal: [ :serialize, '::Marshal.load(%s)', '::Marshal.dump(%s)', nil ],
|
11
|
+
msgpack: [ :serialize, '::MessagePack.unpack(%s)', '::MessagePack.pack(%s)', 'msgpack' ],
|
12
|
+
ox: [ :serialize, '::Ox.parse_obj(%s)', '::Ox.dump(%s)', 'ox' ],
|
13
|
+
php: [ :serialize, '::PHP.unserialize(%s)', '::PHP.serialize(%s)', 'php_serialize'],
|
14
|
+
tnet: [ :serialize, '::TNetstring.parse(%s).first', '::TNetstring.dump(%s)', 'tnetstring' ],
|
15
|
+
yaml: [ :serialize, '::YAML.load(%s)', '::YAML.dump(%s)', 'yaml' ],
|
16
|
+
bzip2: [ :compress, 'Helper.bunzip2(%s)', 'Helper.bzip2(%s)', 'rbzip2' ],
|
17
|
+
lz4: [ :compress, '::LZ4.uncompress(%s)', '::LZ4.compress(%s)', 'lz4-ruby' ],
|
18
|
+
lzma: [ :compress, '::LZMA.decompress(%s)', '::LZMA.compress(%s)', 'lzma' ],
|
19
|
+
lzo: [ :compress, '::LZO.decompress(%s)', '::LZO.compress(%s)', 'lzoruby' ],
|
20
|
+
snappy: [ :compress, '::Snappy.inflate(%s)', '::Snappy.deflate(%s)', 'snappy' ],
|
21
|
+
quicklz: [ :compress, '::QuickLZ.decompress(%s)', '::QuickLZ.compress(%s)', 'qlzruby' ],
|
22
|
+
zlib: [ :compress, '::Zlib::Inflate.inflate(%s)', '::Zlib::Deflate.deflate(%s)', 'zlib' ],
|
23
|
+
base64: [ :encode, "%s.unpack('m0').first", "[%s].pack('m0')" ],
|
24
24
|
urlsafe_base64: [
|
25
|
-
:encode,
|
25
|
+
:encode,
|
26
|
+
'Base64.urlsafe_decode64(%s)',
|
27
|
+
'Base64.urlsafe_encode64(%s)',
|
28
|
+
'base64'
|
26
29
|
],
|
27
|
-
escape: [ :encode, 'Helper.unescape(%s)', 'Helper.escape(%s)'
|
28
|
-
hex: [ :encode, "[%s].pack('H*')", "%s.unpack('H*').first"
|
29
|
-
qp: [ :encode, "%s.unpack('M').first", "[%s].pack('M')"
|
30
|
-
uuencode: [ :encode, "%s.unpack('u').first", "[%s].pack('u')"
|
31
|
-
hmac: [
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
30
|
+
escape: [ :encode, 'Helper.unescape(%s)', 'Helper.escape(%s)' ],
|
31
|
+
hex: [ :encode, "[%s].pack('H*')", "%s.unpack('H*').first" ],
|
32
|
+
qp: [ :encode, "%s.unpack('M').first", "[%s].pack('M')" ],
|
33
|
+
uuencode: [ :encode, "%s.unpack('u').first", "[%s].pack('u')" ],
|
34
|
+
hmac: [
|
35
|
+
:hmac,
|
36
|
+
'Helper.hmacverify(%s, options[:secret] || @secret)',
|
37
|
+
'Helper.hmacsign(%s, options[:secret] || @secret)',
|
38
|
+
'openssl'
|
39
|
+
],
|
40
|
+
prefix: [
|
41
|
+
:prefix,
|
42
|
+
"%s.sub(@prefix, '')",
|
43
|
+
'(options[:prefix] || @prefix)+%s',
|
44
|
+
nil,
|
45
|
+
"%s.start_with?(@prefix)"
|
46
|
+
],
|
47
|
+
truncate: [ :truncate, nil, 'Helper.truncate(%s, @maxlen)', 'digest/md5' ],
|
48
|
+
md5: [ :digest, nil, '::Digest::MD5.hexdigest(%s)', 'digest/md5' ],
|
49
|
+
rmd160: [ :digest, nil, '::Digest::RMD160.hexdigest(%s)', 'digest/rmd160'],
|
50
|
+
sha1: [ :digest, nil, '::Digest::SHA1.hexdigest(%s)', 'digest/sha1' ],
|
51
|
+
sha256: [ :digest, nil, '::Digest::SHA256.hexdigest(%s)', 'digest/sha2' ],
|
52
|
+
sha384: [ :digest, nil, '::Digest::SHA384.hexdigest(%s)', 'digest/sha2' ],
|
53
|
+
sha512: [ :digest, nil, '::Digest::SHA512.hexdigest(%s)', 'digest/sha2' ],
|
54
|
+
city32: [ :digest, nil, '::CityHash.hash32(%s).to_s(16)', 'cityhash' ],
|
55
|
+
city64: [ :digest, nil, '::CityHash.hash64(%s).to_s(16)', 'cityhash' ],
|
56
|
+
city128: [ :digest, nil, '::CityHash.hash128(%s).to_s(16)', 'cityhash' ],
|
57
|
+
spread: [ :spread, nil, 'Helper.spread(%s)' ],
|
58
|
+
to_s: [ :string, nil, '%s.to_s' ],
|
59
|
+
inspect: [ :string, nil, '%s.inspect' ]
|
47
60
|
}.freeze
|
48
61
|
|
49
62
|
# Allowed value transformers (Read it like a regular expression!)
|
@@ -51,5 +64,11 @@ module Moneta
|
|
51
64
|
|
52
65
|
# Allowed key transformers (Read it like a regular expression!)
|
53
66
|
KEY_TRANSFORMER = '(serialize | string)? prefix? ((encode? truncate?) | (digest spread?))?'.freeze
|
67
|
+
|
68
|
+
# Key transformers that can be "loaded" (e.g. reversed) and can be used by the key enumeration feature
|
69
|
+
LOAD_KEY_TRANSFORMER = 'serialize? prefix? encode?'.freeze
|
70
|
+
|
71
|
+
# Key transformers that can be "tested for success" with a dumped key and can be used by the key enumeration feature
|
72
|
+
TEST_KEY_TRANSFORMER = 'serialize? prefix? encode?'.freeze
|
54
73
|
end
|
55
74
|
end
|
data/lib/moneta/version.rb
CHANGED
data/moneta.gemspec
CHANGED
@@ -25,7 +25,7 @@ Gem::Specification.new do |s|
|
|
25
25
|
'source_code_uri' => "https://github.com/moneta-rb/moneta/tree/v#{s.version}",
|
26
26
|
}
|
27
27
|
|
28
|
-
s.required_ruby_version = '>= 2.
|
28
|
+
s.required_ruby_version = '>= 2.3.0'
|
29
29
|
|
30
30
|
s.add_development_dependency 'rspec', '~> 3.0'
|
31
31
|
s.add_development_dependency 'rspec-retry', '~> 0.6.1'
|
@@ -33,5 +33,5 @@ Gem::Specification.new do |s|
|
|
33
33
|
s.add_development_dependency 'parallel_tests', '~> 2.29.2'
|
34
34
|
s.add_development_dependency 'timecop', '~> 0.9.1'
|
35
35
|
s.add_development_dependency 'rubocop', '~> 0.67.2'
|
36
|
-
s.add_development_dependency 'irb', '
|
36
|
+
s.add_development_dependency 'irb', '1.2.1'
|
37
37
|
end
|
data/script/benchmarks
CHANGED
@@ -36,6 +36,9 @@ class MonetaBenchmarks
|
|
36
36
|
postgres_database1 = ENV['MONETA_POSTGRES_DATABSASE1'] || 'moneta1'
|
37
37
|
postgres_database2 = ENV['MONETA_POSTGRES_DATABSASE1'] || 'moneta2'
|
38
38
|
|
39
|
+
couch_login = ENV['COUCH_LOGIN'] || 'admin'
|
40
|
+
couch_password = ENV['COUCH_PASSWORD'] || 'password'
|
41
|
+
|
39
42
|
STORES = [
|
40
43
|
# SDBM accepts only very short key/value pairs (1k for both)
|
41
44
|
{name: "SDBM", sizes: [:small], options: {file: "#{DIR}/sdbm"}},
|
@@ -112,7 +115,9 @@ class MonetaBenchmarks
|
|
112
115
|
backend: if defined?(JRUBY_VERSION)
|
113
116
|
require 'faraday/adapter/manticore'
|
114
117
|
::Faraday.new("http://127.0.0.1:5984/moneta") { |f| f.adapter :manticore }
|
115
|
-
end
|
118
|
+
end,
|
119
|
+
login: couch_login,
|
120
|
+
password: couch_password
|
116
121
|
},
|
117
122
|
clear_options: { compact: true, await_compact: true },
|
118
123
|
},
|
data/script/contributors
CHANGED
@@ -2,7 +2,6 @@
|
|
2
2
|
git log --format='%aN <%aE>' |\
|
3
3
|
sed -e 's/hiddenbek/Scott Wadden/g' |\
|
4
4
|
sed -e 's/Asmod4n/Hendrik Beskow/' |\
|
5
|
-
|
6
|
-
grep -v 'hannes.georg@xing.com\|spotapov\|yehuda-katzs-mac\|wycats ' |\
|
5
|
+
grep -v 'asppsa@gmail.com\|hannes.georg@xing.com\|spotapov\|yehuda-katzs-mac\|wycats ' |\
|
7
6
|
sort -u | sort > CONTRIBUTORS
|
8
7
|
|
@@ -0,0 +1,27 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
set -e
|
3
|
+
|
4
|
+
# Copied from https://github.com/apache/couchdb-pkg/blob/master/debian/README.Debian
|
5
|
+
COUCHDB_PASSWORD=password
|
6
|
+
echo "couchdb couchdb/mode select standalone
|
7
|
+
couchdb couchdb/mode seen true
|
8
|
+
couchdb couchdb/bindaddress string 127.0.0.1
|
9
|
+
couchdb couchdb/bindaddress seen true
|
10
|
+
couchdb couchdb/adminpass password ${COUCHDB_PASSWORD}
|
11
|
+
couchdb couchdb/adminpass seen true
|
12
|
+
couchdb couchdb/adminpass_again password ${COUCHDB_PASSWORD}
|
13
|
+
couchdb couchdb/adminpass_again seen true" | sudo debconf-set-selections
|
14
|
+
DEBIAN_FRONTEND=noninteractive sudo apt-get install -y --force-yes couchdb
|
15
|
+
|
16
|
+
# Reconfigure CouchDB to use delayed commits for speed: http://guide.couchdb.org/draft/performance.html
|
17
|
+
sudo sed -i '/\[couchdb\]/a delayed_commits = true' /etc/couchdb/local.ini
|
18
|
+
|
19
|
+
# (Re)start couchdb
|
20
|
+
sudo systemctl restart couchdb
|
21
|
+
|
22
|
+
# Display some info about CouchDB
|
23
|
+
sudo systemctl status couchdb
|
24
|
+
until curl http://localhost:5984/; do
|
25
|
+
sleep 1
|
26
|
+
done
|
27
|
+
|
data/script/start-hbase
CHANGED
@@ -8,13 +8,13 @@ mkdir -p zookeeper
|
|
8
8
|
mkdir -p downloads
|
9
9
|
root=$(pwd)
|
10
10
|
|
11
|
-
version=$(curl -sS https://
|
11
|
+
version=$(curl -sS https://downloads.apache.org/hbase/stable/RELEASENOTES.md | grep -oP '(?<=# HBASE\s\s)(\d+\.?)+' | head -n1)
|
12
12
|
|
13
13
|
echo HBase stable version is $version
|
14
14
|
|
15
15
|
if [ ! -f downloads/hbase-$version-bin.tar.gz ]; then
|
16
16
|
echo Downloading HBase ...
|
17
|
-
wget -P downloads
|
17
|
+
wget -P downloads https://downloads.apache.org/hbase/stable/hbase-$version-bin.tar.gz
|
18
18
|
fi
|
19
19
|
|
20
20
|
echo Extracting HBase ...
|
data/script/start-services
CHANGED
data/spec/features/store.rb
CHANGED
@@ -178,7 +178,7 @@ shared_examples :store do
|
|
178
178
|
shared_examples :merge! do
|
179
179
|
it 'stores values' do
|
180
180
|
moneta_property_of(keys: 3, values: 3).check do |keys:, values:|
|
181
|
-
expect(store.public_send(method, pairs.call(keys[0] => values[0], keys[1] => values[1], keys[2] => values[2]))).to be store
|
181
|
+
expect(store.public_send(method, pairs.call({ keys[0] => values[0], keys[1] => values[1], keys[2] => values[2] }))).to be store
|
182
182
|
expect(store.key?(keys[0])).to be true
|
183
183
|
expect(store[keys[0]]).to eq values[0]
|
184
184
|
expect(store.key?(keys[1])).to be true
|
@@ -192,7 +192,7 @@ shared_examples :store do
|
|
192
192
|
it 'overwrites existing values' do
|
193
193
|
moneta_property_of(keys: 2, values: 3).check do |keys:, values:|
|
194
194
|
expect(store[keys[0]] = values[0]).to eq values[0]
|
195
|
-
expect(store.public_send(method, pairs.call(keys[0] => values[1], keys[1] => values[2]))).to be store
|
195
|
+
expect(store.public_send(method, pairs.call({ keys[0] => values[1], keys[1] => values[2] }))).to be store
|
196
196
|
expect(store.key?(keys[0])).to be true
|
197
197
|
expect(store[keys[0]]).to eq values[1]
|
198
198
|
expect(store.key?(keys[1])).to be true
|
@@ -204,7 +204,7 @@ shared_examples :store do
|
|
204
204
|
it 'stores the return value of the block, if given, for keys that will be overwritten' do
|
205
205
|
moneta_property_of(keys: 2, values: 4).check do |keys:, values:|
|
206
206
|
expect(store[keys[0]] = values[0]).to eq values[0]
|
207
|
-
expect(store.public_send(method, pairs.call(keys[0] => values[1], keys[1] => values[2])) do |key, old_val, new_val|
|
207
|
+
expect(store.public_send(method, pairs.call({ keys[0] => values[1], keys[1] => values[2] })) do |key, old_val, new_val|
|
208
208
|
expect(key).to eq keys[0]
|
209
209
|
expect(old_val).to eq values[0]
|
210
210
|
expect(new_val).to eq values[1]
|
@@ -1,26 +1,11 @@
|
|
1
1
|
shared_examples :transform_value do
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
store['key'] = values[0]
|
6
|
-
load_value(store.load('key', raw: true)).should == values[0]
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
|
-
it 'can store without transforming the value' do
|
11
|
-
moneta_property_of(values: 1).check do |values:|
|
12
|
-
store['key'] = values[0]
|
13
|
-
store.store('key', store.load('key', raw: true), raw: true)
|
14
|
-
store.load('key').should == values[0]
|
15
|
-
end
|
16
|
-
end
|
2
|
+
it 'allows to bypass transformer with :raw' do
|
3
|
+
store['key'] = 'value'
|
4
|
+
load_value(store.load('key', raw: true)).should == 'value'
|
17
5
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
load_value(store.delete('key', raw: true)).should == values[0]
|
22
|
-
end
|
23
|
-
end
|
6
|
+
store.store('key', 'value', raw: true)
|
7
|
+
store.load('key', raw: true).should == 'value'
|
8
|
+
store.delete('key', raw: true).should == 'value'
|
24
9
|
end
|
25
10
|
|
26
11
|
it 'allows to bypass transformer with raw syntactic sugar' do
|
@@ -35,4 +20,25 @@ shared_examples :transform_value do
|
|
35
20
|
store.raw['key'] = 'value2'
|
36
21
|
store.raw['key'].should == 'value2'
|
37
22
|
end
|
23
|
+
|
24
|
+
it 'returns unmarshalled value' do
|
25
|
+
store.store('key', 'unmarshalled value', raw: true)
|
26
|
+
store.load('key', raw: true).should == 'unmarshalled value'
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'might raise exception on invalid value' do
|
30
|
+
store.store('key', 'unmarshalled value', raw: true)
|
31
|
+
|
32
|
+
begin
|
33
|
+
store['key'].should == load_value('unmarshalled value')
|
34
|
+
store.delete('key').should == load_value('unmarshalled value')
|
35
|
+
rescue Exception => ex
|
36
|
+
expect do
|
37
|
+
store['key']
|
38
|
+
end.to raise_error
|
39
|
+
expect do
|
40
|
+
store.delete('key')
|
41
|
+
end.to raise_error
|
42
|
+
end
|
43
|
+
end
|
38
44
|
end
|