moneta 0.7.6 → 0.7.8
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +15 -0
- data/README.md +160 -50
- data/Rakefile +11 -2
- data/SPEC.md +7 -2
- data/lib/moneta.rb +7 -1
- data/lib/moneta/adapters/activerecord.rb +27 -3
- data/lib/moneta/adapters/cassandra.rb +1 -1
- data/lib/moneta/adapters/client.rb +8 -2
- data/lib/moneta/adapters/cookie.rb +1 -1
- data/lib/moneta/adapters/couch.rb +2 -1
- data/lib/moneta/adapters/datamapper.rb +16 -0
- data/lib/moneta/adapters/daybreak.rb +19 -1
- data/lib/moneta/adapters/file.rb +12 -0
- data/lib/moneta/adapters/hbase.rb +1 -2
- data/lib/moneta/adapters/lruhash.rb +4 -1
- data/lib/moneta/adapters/memcached.rb +7 -3
- data/lib/moneta/adapters/memcached/dalli.rb +8 -2
- data/lib/moneta/adapters/memcached/native.rb +10 -3
- data/lib/moneta/adapters/memory.rb +1 -0
- data/lib/moneta/adapters/mongo.rb +32 -5
- data/lib/moneta/adapters/pstore.rb +13 -2
- data/lib/moneta/adapters/redis.rb +19 -0
- data/lib/moneta/adapters/restclient.rb +1 -1
- data/lib/moneta/adapters/sequel.rb +20 -6
- data/lib/moneta/adapters/sqlite.rb +13 -1
- data/lib/moneta/adapters/tokyocabinet.rb +5 -0
- data/lib/moneta/cache.rb +10 -0
- data/lib/moneta/expires.rb +19 -22
- data/lib/moneta/lock.rb +2 -2
- data/lib/moneta/mixins.rb +33 -11
- data/lib/moneta/optionmerger.rb +1 -1
- data/lib/moneta/proxy.rb +13 -8
- data/lib/moneta/server.rb +13 -6
- data/lib/moneta/shared.rb +6 -10
- data/lib/moneta/synchronize.rb +125 -0
- data/lib/moneta/transformer.rb +50 -42
- data/lib/moneta/transformer/config.rb +34 -32
- data/lib/moneta/utils.rb +20 -0
- data/lib/moneta/version.rb +1 -1
- data/lib/moneta/weak.rb +17 -0
- data/lib/moneta/wrapper.rb +5 -0
- data/lib/rack/moneta_cookies.rb +2 -2
- data/lib/rack/moneta_store.rb +4 -4
- data/script/benchmarks +3 -9
- data/script/generate-specs +278 -41
- data/script/install-bundle +2 -2
- data/spec/moneta/adapter_activerecord_spec.rb +1 -0
- data/spec/moneta/adapter_cassandra_spec.rb +1 -0
- data/spec/moneta/adapter_cassandra_with_default_expires_spec.rb +1 -0
- data/spec/moneta/adapter_client_spec.rb +1 -0
- data/spec/moneta/adapter_cookie_spec.rb +1 -0
- data/spec/moneta/adapter_couch_spec.rb +1 -0
- data/spec/moneta/adapter_datamapper_spec.rb +1 -0
- data/spec/moneta/adapter_daybreak_spec.rb +1 -0
- data/spec/moneta/adapter_dbm_spec.rb +1 -0
- data/spec/moneta/adapter_file_spec.rb +1 -0
- data/spec/moneta/adapter_fog_spec.rb +1 -0
- data/spec/moneta/adapter_gdbm_spec.rb +1 -1
- data/spec/moneta/adapter_hbase_spec.rb +1 -0
- data/spec/moneta/adapter_leveldb_spec.rb +1 -0
- data/spec/moneta/adapter_localmemcache_spec.rb +1 -0
- data/spec/moneta/adapter_lruhash_spec.rb +1 -0
- data/spec/moneta/adapter_memcached_dalli_spec.rb +2 -0
- data/spec/moneta/adapter_memcached_dalli_with_default_expires_spec.rb +2 -0
- data/spec/moneta/adapter_memcached_native_spec.rb +2 -0
- data/spec/moneta/adapter_memcached_native_with_default_expires_spec.rb +2 -0
- data/spec/moneta/adapter_memcached_spec.rb +2 -0
- data/spec/moneta/adapter_memcached_with_default_expires_spec.rb +2 -0
- data/spec/moneta/adapter_memory_spec.rb +1 -0
- data/spec/moneta/adapter_mongo_spec.rb +2 -0
- data/spec/moneta/adapter_mongo_with_default_expires_spec.rb +2 -0
- data/spec/moneta/adapter_pstore_spec.rb +1 -0
- data/spec/moneta/adapter_redis_spec.rb +2 -0
- data/spec/moneta/adapter_redis_with_default_expires_spec.rb +2 -0
- data/spec/moneta/adapter_restclient_spec.rb +1 -0
- data/spec/moneta/adapter_riak_spec.rb +1 -0
- data/spec/moneta/adapter_sdbm_spec.rb +1 -0
- data/spec/moneta/adapter_sequel_spec.rb +1 -0
- data/spec/moneta/adapter_sqlite_spec.rb +1 -0
- data/spec/moneta/adapter_tdb_spec.rb +1 -0
- data/spec/moneta/adapter_tokyocabinet_bdb_spec.rb +1 -0
- data/spec/moneta/adapter_tokyocabinet_hdb_spec.rb +1 -0
- data/spec/moneta/adapter_yaml_spec.rb +1 -0
- data/spec/moneta/cache_file_memory_spec.rb +1 -0
- data/spec/moneta/cache_memory_null_spec.rb +1 -0
- data/spec/moneta/expires_file_spec.rb +3 -1
- data/spec/moneta/expires_memory_spec.rb +2 -0
- data/spec/moneta/expires_memory_with_default_expires_spec.rb +2 -0
- data/spec/moneta/lock_spec.rb +1 -0
- data/spec/moneta/mutex_spec.rb +71 -0
- data/spec/moneta/null_adapter_spec.rb +1 -0
- data/spec/moneta/optionmerger_spec.rb +5 -7
- data/spec/moneta/pool_spec.rb +1 -0
- data/spec/moneta/proxy_expires_memory_spec.rb +2 -0
- data/spec/moneta/proxy_redis_spec.rb +2 -0
- data/spec/moneta/semaphore_spec.rb +84 -0
- data/spec/moneta/{shared_spec.rb → shared_tcp_spec.rb} +4 -3
- data/spec/moneta/shared_unix_spec.rb +37 -0
- data/spec/moneta/simple_activerecord_spec.rb +1 -0
- data/spec/moneta/simple_activerecord_with_expires_spec.rb +3 -1
- data/spec/moneta/simple_cassandra_spec.rb +1 -0
- data/spec/moneta/simple_client_tcp_spec.rb +1 -0
- data/spec/moneta/simple_client_unix_spec.rb +3 -2
- data/spec/moneta/simple_couch_spec.rb +1 -0
- data/spec/moneta/simple_couch_with_expires_spec.rb +2 -1
- data/spec/moneta/simple_datamapper_spec.rb +1 -0
- data/spec/moneta/simple_datamapper_with_expires_spec.rb +3 -1
- data/spec/moneta/simple_datamapper_with_repository_spec.rb +1 -0
- data/spec/moneta/simple_daybreak_spec.rb +1 -0
- data/spec/moneta/simple_daybreak_with_expires_spec.rb +3 -1
- data/spec/moneta/simple_dbm_spec.rb +1 -0
- data/spec/moneta/simple_dbm_with_expires_spec.rb +3 -1
- data/spec/moneta/simple_file_spec.rb +1 -0
- data/spec/moneta/simple_file_with_expires_spec.rb +3 -1
- data/spec/moneta/simple_fog_spec.rb +1 -0
- data/spec/moneta/simple_fog_with_expires_spec.rb +2 -1
- data/spec/moneta/simple_gdbm_spec.rb +1 -0
- data/spec/moneta/simple_gdbm_with_expires_spec.rb +3 -1
- data/spec/moneta/simple_hashfile_spec.rb +1 -0
- data/spec/moneta/simple_hashfile_with_expires_spec.rb +3 -1
- data/spec/moneta/simple_hbase_spec.rb +1 -0
- data/spec/moneta/simple_hbase_with_expires_spec.rb +3 -1
- data/spec/moneta/simple_leveldb_spec.rb +1 -0
- data/spec/moneta/simple_leveldb_with_expires_spec.rb +3 -1
- data/spec/moneta/simple_localmemcache_spec.rb +1 -0
- data/spec/moneta/simple_localmemcache_with_expires_spec.rb +2 -1
- data/spec/moneta/simple_lruhash_spec.rb +1 -0
- data/spec/moneta/simple_lruhash_with_expires_spec.rb +3 -1
- data/spec/moneta/simple_memcached_dalli_spec.rb +2 -0
- data/spec/moneta/simple_memcached_native_spec.rb +2 -0
- data/spec/moneta/simple_memcached_spec.rb +2 -0
- data/spec/moneta/simple_memory_spec.rb +1 -0
- data/spec/moneta/simple_memory_with_compress_spec.rb +1 -0
- data/spec/moneta/simple_memory_with_expires_spec.rb +3 -1
- data/spec/moneta/simple_memory_with_json_key_serializer_spec.rb +1 -0
- data/spec/moneta/simple_memory_with_json_serializer_spec.rb +1 -0
- data/spec/moneta/simple_memory_with_json_value_serializer_spec.rb +1 -0
- data/spec/moneta/simple_memory_with_prefix_spec.rb +1 -0
- data/spec/moneta/simple_memory_with_snappy_compress_spec.rb +1 -0
- data/spec/moneta/simple_mongo_spec.rb +2 -0
- data/spec/moneta/simple_null_spec.rb +1 -0
- data/spec/moneta/simple_pstore_spec.rb +1 -0
- data/spec/moneta/simple_pstore_with_expires_spec.rb +3 -1
- data/spec/moneta/simple_redis_spec.rb +2 -0
- data/spec/moneta/simple_restclient_spec.rb +1 -0
- data/spec/moneta/simple_riak_spec.rb +1 -0
- data/spec/moneta/simple_riak_with_expires_spec.rb +2 -1
- data/spec/moneta/simple_sdbm_spec.rb +1 -0
- data/spec/moneta/simple_sdbm_with_expires_spec.rb +3 -1
- data/spec/moneta/simple_sequel_spec.rb +1 -0
- data/spec/moneta/simple_sequel_with_expires_spec.rb +3 -1
- data/spec/moneta/simple_sqlite_spec.rb +1 -0
- data/spec/moneta/simple_sqlite_with_expires_spec.rb +3 -1
- data/spec/moneta/simple_tdb_spec.rb +1 -0
- data/spec/moneta/simple_tdb_with_expires_spec.rb +3 -1
- data/spec/moneta/simple_tokyocabinet_spec.rb +1 -0
- data/spec/moneta/simple_tokyocabinet_with_expires_spec.rb +3 -1
- data/spec/moneta/simple_yaml_spec.rb +1 -0
- data/spec/moneta/simple_yaml_with_expires_spec.rb +3 -1
- data/spec/moneta/stack_file_memory_spec.rb +1 -0
- data/spec/moneta/stack_memory_file_spec.rb +1 -0
- data/spec/moneta/transformer_bencode_spec.rb +1 -0
- data/spec/moneta/transformer_bert_spec.rb +1 -0
- data/spec/moneta/transformer_bson_spec.rb +1 -0
- data/spec/moneta/transformer_bzip2_spec.rb +1 -0
- data/spec/moneta/transformer_json_spec.rb +1 -0
- data/spec/moneta/transformer_key_inspect_spec.rb +73 -0
- data/spec/moneta/transformer_key_marshal_spec.rb +1 -0
- data/spec/moneta/transformer_key_to_s_spec.rb +1 -0
- data/spec/moneta/transformer_key_yaml_spec.rb +1 -0
- data/spec/moneta/transformer_lzma_spec.rb +1 -0
- data/spec/moneta/transformer_lzo_spec.rb +1 -0
- data/spec/moneta/transformer_marshal_base64_spec.rb +1 -0
- data/spec/moneta/transformer_marshal_escape_spec.rb +1 -0
- data/spec/moneta/transformer_marshal_hmac_spec.rb +1 -0
- data/spec/moneta/transformer_marshal_md5_spec.rb +1 -0
- data/spec/moneta/transformer_marshal_md5_spread_spec.rb +1 -0
- data/spec/moneta/transformer_marshal_prefix_spec.rb +1 -0
- data/spec/moneta/transformer_marshal_rmd160_spec.rb +1 -0
- data/spec/moneta/transformer_marshal_sha1_spec.rb +1 -0
- data/spec/moneta/transformer_marshal_sha256_spec.rb +1 -0
- data/spec/moneta/transformer_marshal_sha384_spec.rb +1 -0
- data/spec/moneta/transformer_marshal_sha512_spec.rb +1 -0
- data/spec/moneta/transformer_marshal_spec.rb +1 -0
- data/spec/moneta/transformer_marshal_truncate_spec.rb +1 -0
- data/spec/moneta/transformer_marshal_uuencode_spec.rb +1 -0
- data/spec/moneta/transformer_msgpack_spec.rb +1 -0
- data/spec/moneta/transformer_ox_spec.rb +1 -0
- data/spec/moneta/transformer_quicklz_spec.rb +1 -0
- data/spec/moneta/transformer_snappy_spec.rb +1 -0
- data/spec/moneta/transformer_tnet_spec.rb +1 -0
- data/spec/moneta/transformer_value_marshal_spec.rb +1 -0
- data/spec/moneta/transformer_value_yaml_spec.rb +1 -0
- data/spec/moneta/transformer_yaml_spec.rb +1 -0
- data/spec/moneta/transformer_zlib_spec.rb +1 -0
- data/spec/moneta/weak_create_spec.rb +114 -0
- data/spec/moneta/weak_increment_spec.rb +114 -0
- data/spec/monetaspecs.rb +75 -2
- data/spec/rack/moneta_cookies_spec.rb +1 -1
- metadata +20 -4
data/lib/moneta/transformer.rb
CHANGED
@@ -57,86 +57,91 @@ module Moneta
|
|
57
57
|
end
|
58
58
|
end_eval
|
59
59
|
|
60
|
-
key = compile_transformer(keys, 'key')
|
61
|
-
dump = compile_transformer(values, 'value')
|
62
|
-
load = compile_transformer(values.reverse, 'value', 1)
|
60
|
+
key, key_opts = compile_transformer(keys, 'key')
|
61
|
+
dump, dump_opts = compile_transformer(values, 'value')
|
62
|
+
load, load_opts = compile_transformer(values.reverse, 'value', 1)
|
63
63
|
|
64
64
|
if values.empty?
|
65
|
-
compile_key_transformer(klass, key)
|
65
|
+
compile_key_transformer(klass, key, key_opts)
|
66
66
|
elsif keys.empty?
|
67
|
-
compile_value_transformer(klass, load, dump)
|
67
|
+
compile_value_transformer(klass, load, load_opts, dump, dump_opts)
|
68
68
|
else
|
69
|
-
compile_key_value_transformer(klass, key, load, dump)
|
69
|
+
compile_key_value_transformer(klass, key, key_opts, load, load_opts, dump, dump_opts)
|
70
70
|
end
|
71
71
|
|
72
72
|
klass
|
73
73
|
end
|
74
74
|
|
75
|
-
def
|
75
|
+
def without(*options)
|
76
|
+
options = options.flatten.uniq
|
77
|
+
options.empty? ? 'options' : "Utils.without(options, #{options.map(&:to_sym).map(&:inspect).join(', ')})"
|
78
|
+
end
|
79
|
+
|
80
|
+
def compile_key_transformer(klass, key, key_opts)
|
76
81
|
klass.class_eval <<-end_eval, __FILE__, __LINE__
|
77
82
|
def key?(key, options = {})
|
78
|
-
@adapter.key?(#{key},
|
83
|
+
@adapter.key?(#{key}, #{without key_opts})
|
79
84
|
end
|
80
85
|
def increment(key, amount = 1, options = {})
|
81
|
-
@adapter.increment(#{key}, amount,
|
86
|
+
@adapter.increment(#{key}, amount, #{without key_opts})
|
82
87
|
end
|
83
88
|
def load(key, options = {})
|
84
|
-
|
85
|
-
@adapter.load(#{key}, options)
|
89
|
+
@adapter.load(#{key}, #{without :raw, key_opts})
|
86
90
|
end
|
87
91
|
def store(key, value, options = {})
|
88
|
-
|
89
|
-
@adapter.store(#{key}, value, options)
|
92
|
+
@adapter.store(#{key}, value, #{without :raw, key_opts})
|
90
93
|
end
|
91
94
|
def delete(key, options = {})
|
92
|
-
|
93
|
-
|
95
|
+
@adapter.delete(#{key}, #{without :raw, key_opts})
|
96
|
+
end
|
97
|
+
def create(key, value, options = {})
|
98
|
+
@adapter.create(#{key}, value, #{without :raw, key_opts})
|
94
99
|
end
|
95
100
|
end_eval
|
96
101
|
end
|
97
102
|
|
98
|
-
def compile_value_transformer(klass, load, dump)
|
103
|
+
def compile_value_transformer(klass, load, load_opts, dump, dump_opts)
|
99
104
|
klass.class_eval <<-end_eval, __FILE__, __LINE__
|
100
105
|
def load(key, options = {})
|
101
|
-
|
102
|
-
value
|
103
|
-
value && !raw ? #{load} : value
|
106
|
+
value = @adapter.load(key, #{without :raw, load_opts})
|
107
|
+
value && !options[:raw] ? #{load} : value
|
104
108
|
end
|
105
109
|
def store(key, value, options = {})
|
106
|
-
|
107
|
-
@adapter.store(key, raw ? value : #{dump}, options)
|
110
|
+
@adapter.store(key, options[:raw] ? value : #{dump}, #{without :raw, dump_opts})
|
108
111
|
value
|
109
112
|
end
|
110
113
|
def delete(key, options = {})
|
111
|
-
|
112
|
-
value
|
113
|
-
|
114
|
+
value = @adapter.delete(key, #{without :raw, load_opts})
|
115
|
+
value && !options[:raw] ? #{load} : value
|
116
|
+
end
|
117
|
+
def create(key, value, options = {})
|
118
|
+
@adapter.create(key, options[:raw] ? value : #{dump}, #{without :raw, dump_opts})
|
114
119
|
end
|
115
120
|
end_eval
|
116
121
|
end
|
117
122
|
|
118
|
-
def compile_key_value_transformer(klass, key, load, dump)
|
123
|
+
def compile_key_value_transformer(klass, key, key_opts, load, load_opts, dump, dump_opts)
|
119
124
|
klass.class_eval <<-end_eval, __FILE__, __LINE__
|
120
125
|
def key?(key, options = {})
|
121
|
-
@adapter.key?(#{key},
|
126
|
+
@adapter.key?(#{key}, #{without key_opts})
|
122
127
|
end
|
123
128
|
def increment(key, amount = 1, options = {})
|
124
|
-
@adapter.increment(#{key}, amount,
|
129
|
+
@adapter.increment(#{key}, amount, #{without key_opts})
|
125
130
|
end
|
126
131
|
def load(key, options = {})
|
127
|
-
|
128
|
-
value
|
129
|
-
value && !raw ? #{load} : value
|
132
|
+
value = @adapter.load(#{key}, #{without :raw, key_opts, load_opts})
|
133
|
+
value && !options[:raw] ? #{load} : value
|
130
134
|
end
|
131
135
|
def store(key, value, options = {})
|
132
|
-
|
133
|
-
@adapter.store(#{key}, raw ? value : #{dump}, options)
|
136
|
+
@adapter.store(#{key}, options[:raw] ? value : #{dump}, #{without :raw, key_opts, dump_opts})
|
134
137
|
value
|
135
138
|
end
|
136
139
|
def delete(key, options = {})
|
137
|
-
|
138
|
-
value
|
139
|
-
|
140
|
+
value = @adapter.delete(#{key}, #{without :raw, key_opts, load_opts})
|
141
|
+
value && !options[:raw] ? #{load} : value
|
142
|
+
end
|
143
|
+
def create(key, value, options = {})
|
144
|
+
@adapter.create(#{key}, options[:raw] ? value : #{dump}, #{without :raw, key_opts, dump_opts})
|
140
145
|
end
|
141
146
|
end_eval
|
142
147
|
end
|
@@ -151,7 +156,6 @@ module Moneta
|
|
151
156
|
end.join("\n")
|
152
157
|
end
|
153
158
|
|
154
|
-
# Compile transformer validator regular expression
|
155
159
|
def compile_validator(s)
|
156
160
|
Regexp.new('\A' + s.gsub(/\w+/) do
|
157
161
|
'(' + TRANSFORMER.select {|k,v| v.first.to_s == $& }.map {|v| ":#{v.first}" }.join('|') + ')'
|
@@ -160,16 +164,20 @@ module Moneta
|
|
160
164
|
|
161
165
|
# Returned compiled transformer code string
|
162
166
|
def compile_transformer(transformer, var, i = 2)
|
163
|
-
|
167
|
+
value, options = var, []
|
168
|
+
transformer.each do |name|
|
164
169
|
raise ArgumentError, "Unknown transformer #{name}" unless t = TRANSFORMER[name]
|
165
170
|
require t[3] if t[3]
|
166
171
|
code = t[i]
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
+
options += code.scan(/options\[:(\w+)\]/).flatten
|
173
|
+
value =
|
174
|
+
if t[0] == :serialize && var == 'key'
|
175
|
+
"(tmp = #{value}; String === tmp ? tmp : #{code % 'tmp'})"
|
176
|
+
else
|
177
|
+
code % value
|
178
|
+
end
|
172
179
|
end
|
180
|
+
return value, options
|
173
181
|
end
|
174
182
|
|
175
183
|
def class_name(keys, values)
|
@@ -2,44 +2,46 @@ module Moneta
|
|
2
2
|
class Transformer
|
3
3
|
# Available key/value transformers
|
4
4
|
TRANSFORMER = {
|
5
|
-
# Name => [ Type, Load,
|
6
|
-
:bencode => [ :serialize, '::BEncode.load(%s)',
|
7
|
-
:bert => [ :serialize, '::BERT.decode(%s)',
|
8
|
-
:bson => [ :serialize, "::BSON.deserialize(%s)['v']",
|
9
|
-
:json => [ :serialize, '::MultiJson.load(%s).first',
|
10
|
-
:marshal => [ :serialize, '::Marshal.load(%s)',
|
11
|
-
:msgpack => [ :serialize, '::MessagePack.unpack(%s)',
|
12
|
-
:ox => [ :serialize, '::Ox.parse_obj(%s)',
|
13
|
-
:tnet => [ :serialize, '::TNetstring.parse(%s).first',
|
14
|
-
:yaml => [ :serialize, '::YAML.load(%s)',
|
15
|
-
:bzip2 => [ :compress, '::Bzip2.uncompress(%s)',
|
16
|
-
:lzma => [ :compress, '::LZMA.decompress(%s)',
|
17
|
-
:lzo => [ :compress, '::LZO.decompress(%s)',
|
18
|
-
:snappy => [ :compress, '::Snappy.inflate(%s)',
|
19
|
-
:quicklz => [ :compress, '::QuickLZ.decompress(%s)',
|
20
|
-
:zlib => [ :compress, '::Zlib::Inflate.inflate(%s)',
|
21
|
-
:uuencode => [ :encode, "%s.unpack('u').first",
|
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, "::BSON.deserialize(%s)['v']", "::BSON.serialize('v'=>%s).to_s", 'bson' ],
|
9
|
+
:json => [ :serialize, '::MultiJson.load(%s).first', '::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
|
+
:tnet => [ :serialize, '::TNetstring.parse(%s).first', '::TNetstring.dump(%s)', 'tnetstring' ],
|
14
|
+
:yaml => [ :serialize, '::YAML.load(%s)', '::YAML.dump(%s)', 'yaml' ],
|
15
|
+
:bzip2 => [ :compress, '::Bzip2.uncompress(%s)', '::Bzip2.compress(%s)', 'bzip2' ],
|
16
|
+
:lzma => [ :compress, '::LZMA.decompress(%s)', '::LZMA.compress(%s)', 'lzma' ],
|
17
|
+
:lzo => [ :compress, '::LZO.decompress(%s)', '::LZO.compress(%s)', 'lzoruby' ],
|
18
|
+
:snappy => [ :compress, '::Snappy.inflate(%s)', '::Snappy.deflate(%s)', 'snappy' ],
|
19
|
+
:quicklz => [ :compress, '::QuickLZ.decompress(%s)', '::QuickLZ.compress(%s)', 'qlzruby' ],
|
20
|
+
:zlib => [ :compress, '::Zlib::Inflate.inflate(%s)', '::Zlib::Deflate.deflate(%s)', 'zlib' ],
|
21
|
+
:uuencode => [ :encode, "%s.unpack('u').first", "[%s].pack('u').strip" ],
|
22
22
|
:base64 => RUBY_VERSION > '1.9' ?
|
23
|
-
[ :encode, "%s.unpack('m0').first",
|
24
|
-
[ :encode, "%s.unpack('m').first",
|
25
|
-
:escape => [ :encode, 'Helper.unescape(%s)',
|
26
|
-
:hmac => [ :hmac, 'Helper.hmacverify(%s,
|
27
|
-
|
28
|
-
:
|
29
|
-
:
|
30
|
-
:
|
31
|
-
:
|
32
|
-
:
|
33
|
-
:
|
34
|
-
:
|
35
|
-
:
|
36
|
-
:
|
23
|
+
[ :encode, "%s.unpack('m0').first", "[%s].pack('m0')" ] :
|
24
|
+
[ :encode, "%s.unpack('m').first", "[%s].pack('m').gsub(\"\n\", '')" ],
|
25
|
+
:escape => [ :encode, 'Helper.unescape(%s)', 'Helper.escape(%s)' ],
|
26
|
+
:hmac => [ :hmac, 'Helper.hmacverify(%s, options[:secret] || @secret)',
|
27
|
+
'Helper.hmacsign(%s, options[:secret] || @secret)', 'openssl' ],
|
28
|
+
:truncate => [ :truncate, nil, 'Helper.truncate(%s, @maxlen)', 'digest/md5' ],
|
29
|
+
:md5 => [ :digest, nil, '::Digest::MD5.hexdigest(%s)', 'digest/md5' ],
|
30
|
+
:rmd160 => [ :digest, nil, '::Digest::RMD160.hexdigest(%s)', 'digest/rmd160' ],
|
31
|
+
:sha1 => [ :digest, nil, '::Digest::SHA1.hexdigest(%s)', 'digest/sha1' ],
|
32
|
+
:sha256 => [ :digest, nil, '::Digest::SHA256.hexdigest(%s)', 'digest/sha2' ],
|
33
|
+
:sha384 => [ :digest, nil, '::Digest::SHA384.hexdigest(%s)', 'digest/sha2' ],
|
34
|
+
:sha512 => [ :digest, nil, '::Digest::SHA512.hexdigest(%s)', 'digest/sha2' ],
|
35
|
+
:prefix => [ :prefix, nil, '(options[:prefix] || @prefix)+%s' ],
|
36
|
+
:spread => [ :spread, nil, 'Helper.spread(%s)' ],
|
37
|
+
:to_s => [ :string, nil, '%s.to_s' ],
|
38
|
+
:inspect => [ :string, nil, '%s.inspect' ],
|
37
39
|
}
|
38
40
|
|
39
41
|
# Allowed value transformers (Read it like a regular expression!)
|
40
42
|
VALUE_TRANSFORMER = 'serialize? compress? hmac? encode?'
|
41
43
|
|
42
44
|
# Allowed key transformers (Read it like a regular expression!)
|
43
|
-
KEY_TRANSFORMER = '(serialize |
|
45
|
+
KEY_TRANSFORMER = '(serialize | string)? prefix? ((encode? truncate?) | (digest spread?))?'
|
44
46
|
end
|
45
47
|
end
|
data/lib/moneta/utils.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
module Moneta
|
2
|
+
# @api private
|
3
|
+
module Utils
|
4
|
+
extend self
|
5
|
+
|
6
|
+
def without(hash, *keys)
|
7
|
+
if keys.any? {|k| hash.include?(k) }
|
8
|
+
hash = hash.dup
|
9
|
+
keys.each {|k| hash.delete(k) }
|
10
|
+
end
|
11
|
+
hash
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_int(value)
|
15
|
+
intvalue = value.to_i
|
16
|
+
raise "#{value.inspect} is not an integer value" unless value == nil || intvalue.to_s == value.to_s
|
17
|
+
intvalue
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/moneta/version.rb
CHANGED
data/lib/moneta/weak.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
module Moneta
|
2
|
+
# Adds weak create support to the underlying store
|
3
|
+
#
|
4
|
+
# @note The increment method will not be thread or multi-process safe (this is meant by weak)
|
5
|
+
# @api public
|
6
|
+
class WeakCreate < Proxy
|
7
|
+
include CreateSupport
|
8
|
+
end
|
9
|
+
|
10
|
+
# Adds weak increment support to the underlying store
|
11
|
+
#
|
12
|
+
# @note The increment method will not be thread or multi-process safe (this is meant by weak)
|
13
|
+
# @api public
|
14
|
+
class WeakIncrement < Proxy
|
15
|
+
include IncrementSupport
|
16
|
+
end
|
17
|
+
end
|
data/lib/moneta/wrapper.rb
CHANGED
@@ -27,6 +27,11 @@ module Moneta
|
|
27
27
|
wrap(:increment, key, amount, options) { super }
|
28
28
|
end
|
29
29
|
|
30
|
+
# (see Proxy#create)
|
31
|
+
def create(key, value, options = {})
|
32
|
+
wrap(:create, key, value, options) { super }
|
33
|
+
end
|
34
|
+
|
30
35
|
# (see Proxy#clear)
|
31
36
|
def clear(options = {})
|
32
37
|
wrap(:clear, options) { super }
|
data/lib/rack/moneta_cookies.rb
CHANGED
@@ -23,7 +23,7 @@ module Rack
|
|
23
23
|
# adapter :Cookie
|
24
24
|
# end
|
25
25
|
#
|
26
|
-
# run lambda
|
26
|
+
# run lambda { |env|
|
27
27
|
# req = Rack::Request.new(env)
|
28
28
|
# req.cookies #=> is now a Moneta store!
|
29
29
|
# env['rack.request.cookie_hash'] #=> is now a Moneta store!
|
@@ -31,7 +31,7 @@ module Rack
|
|
31
31
|
# req.cookies['key'] = 'value' #=> sets 'moneta.key'
|
32
32
|
# req.cookies.delete('key') #=> removes 'moneta.key'
|
33
33
|
# [200, {}, []]
|
34
|
-
#
|
34
|
+
# }
|
35
35
|
#
|
36
36
|
# @api public
|
37
37
|
class MonetaCookies
|
data/lib/rack/moneta_store.rb
CHANGED
@@ -8,9 +8,9 @@ module Rack
|
|
8
8
|
# # Add Rack::MonetaStore somewhere in your rack stack
|
9
9
|
# use Rack::MonetaStore, :Memory, :cache => true
|
10
10
|
#
|
11
|
-
# run lambda
|
11
|
+
# run lambda { |env|
|
12
12
|
# env['rack.moneta_store'] # is a Moneta store with per-request caching
|
13
|
-
#
|
13
|
+
# }
|
14
14
|
#
|
15
15
|
# @example config.ru
|
16
16
|
# # Pass it a block like the one passed to Moneta.build
|
@@ -19,9 +19,9 @@ module Rack
|
|
19
19
|
# adapter :Cookie
|
20
20
|
# end
|
21
21
|
#
|
22
|
-
# run lambda
|
22
|
+
# run lambda { |env|
|
23
23
|
# env['rack.moneta_store'] # is a Moneta store without caching
|
24
|
-
#
|
24
|
+
# }
|
25
25
|
#
|
26
26
|
# @api public
|
27
27
|
class MonetaStore
|
data/script/benchmarks
CHANGED
@@ -24,12 +24,6 @@ class Array
|
|
24
24
|
m = mean
|
25
25
|
Math.sqrt(map {|s| (s - m) ** 2 }.mean)
|
26
26
|
end
|
27
|
-
|
28
|
-
def randomize
|
29
|
-
rest, result = dup, []
|
30
|
-
result << rest.slice!(rand(rest.size)) until result.size == size
|
31
|
-
result
|
32
|
-
end
|
33
27
|
end
|
34
28
|
|
35
29
|
class MonetaBenchmarks
|
@@ -242,7 +236,7 @@ class MonetaBenchmarks
|
|
242
236
|
puts "\e[31m#{name} not benchmarked - #{ex.message}\e[0m"
|
243
237
|
STORES.delete(name)
|
244
238
|
ensure
|
245
|
-
cache.close if cache
|
239
|
+
(cache.close rescue nil) if cache
|
246
240
|
end
|
247
241
|
end
|
248
242
|
end
|
@@ -312,14 +306,14 @@ class MonetaBenchmarks
|
|
312
306
|
store.clear
|
313
307
|
print "%s[%-#{2 * @config[:runs]}s] " % ["\b" * (2 * @config[:runs] + 3), state << 'W']
|
314
308
|
|
315
|
-
@data
|
309
|
+
@data.shuffle!
|
316
310
|
m1 = Benchmark.measure do
|
317
311
|
@data.each {|k,v| store[k] = v }
|
318
312
|
end
|
319
313
|
|
320
314
|
print "%s[%-#{2 * @config[:runs]}s] " % ["\b" * (2 * @config[:runs] + 3), state << 'R']
|
321
315
|
|
322
|
-
@data
|
316
|
+
@data.shuffle!
|
323
317
|
error = 0
|
324
318
|
m2 = Benchmark.measure do
|
325
319
|
@data.each do |k, v|
|
data/script/generate-specs
CHANGED
@@ -61,14 +61,17 @@ class Specs
|
|
61
61
|
a = specs.dup
|
62
62
|
if a.include?(:transform_value)
|
63
63
|
a.delete(:transform_value)
|
64
|
-
a << :
|
64
|
+
a << :transform_value_expires
|
65
65
|
end
|
66
|
+
a << :create_expires if a.include?(:create)
|
66
67
|
a << :expires
|
67
68
|
new(:specs => a)
|
68
69
|
end
|
69
70
|
|
70
71
|
def with_native_expires
|
71
|
-
|
72
|
+
a = specs.dup
|
73
|
+
a << :create_expires if a.include?(:create)
|
74
|
+
new(:specs => a.with(:expires))
|
72
75
|
end
|
73
76
|
|
74
77
|
def without_marshallable
|
@@ -98,11 +101,15 @@ class Specs
|
|
98
101
|
def with_default_expires
|
99
102
|
new(:specs => specs.with(:default_expires))
|
100
103
|
end
|
104
|
+
|
105
|
+
def without_create
|
106
|
+
new(:specs => specs.without(:create, :create_expires).with(:not_create))
|
107
|
+
end
|
101
108
|
end
|
102
109
|
|
103
|
-
ADAPTER_SPECS = Specs.new(:specs => [:null, :store, :returndifferent, :increment, :persist, :multiprocess], :key => %w(string), :value => %w(string))
|
104
|
-
STANDARD_SPECS = Specs.new(:specs => [:null, :store, :returndifferent, :marshallable_key, :marshallable_value, :transform_value, :increment, :persist, :multiprocess])
|
105
|
-
TRANSFORMER_SPECS = Specs.new(:specs => [:null, :store, :returndifferent, :transform_value, :increment])
|
110
|
+
ADAPTER_SPECS = Specs.new(:specs => [:null, :store, :returndifferent, :increment, :persist, :multiprocess, :create], :key => %w(string), :value => %w(string))
|
111
|
+
STANDARD_SPECS = Specs.new(:specs => [:null, :store, :returndifferent, :marshallable_key, :marshallable_value, :transform_value, :increment, :persist, :multiprocess, :create])
|
112
|
+
TRANSFORMER_SPECS = Specs.new(:specs => [:null, :store, :returndifferent, :transform_value, :increment, :create])
|
106
113
|
|
107
114
|
header = "# Generated by #{File.basename(__FILE__)}\n"
|
108
115
|
|
@@ -129,16 +136,16 @@ end
|
|
129
136
|
}
|
130
137
|
},
|
131
138
|
'simple_client_unix' => {
|
132
|
-
:preamble => "start_server(Moneta::Adapters::Memory.new, :
|
139
|
+
:preamble => "start_server(Moneta::Adapters::Memory.new, :socket => File.join(make_tempdir, 'simple_client_unix'))\n",
|
133
140
|
:store => :Client,
|
134
|
-
:options => ":
|
141
|
+
:options => ":socket => File.join(make_tempdir, 'simple_client_unix')",
|
135
142
|
:specs => STANDARD_SPECS
|
136
143
|
},
|
137
144
|
'simple_restclient' => {
|
138
145
|
:preamble => "start_restserver\n",
|
139
146
|
:store => :RestClient,
|
140
147
|
:options => ":url => 'http://localhost:8808/moneta/'",
|
141
|
-
:specs => STANDARD_SPECS.without_increment
|
148
|
+
:specs => STANDARD_SPECS.without_increment.without_create
|
142
149
|
},
|
143
150
|
'simple_memory' => {
|
144
151
|
:store => :Memory,
|
@@ -215,12 +222,12 @@ end
|
|
215
222
|
'simple_cassandra' => {
|
216
223
|
:store => :Cassandra,
|
217
224
|
:options => ':keyspace => "simple_cassandra"',
|
218
|
-
:specs => STANDARD_SPECS.without_increment.with_native_expires,
|
225
|
+
:specs => STANDARD_SPECS.without_increment.without_create.with_native_expires,
|
219
226
|
},
|
220
227
|
'simple_hbase' => {
|
221
228
|
:store => :HBase,
|
222
229
|
:options => ':table => "simple_hbase"',
|
223
|
-
:specs => STANDARD_SPECS
|
230
|
+
:specs => STANDARD_SPECS.without_create
|
224
231
|
},
|
225
232
|
'simple_hbase_with_expires' => {
|
226
233
|
:store => :HBase,
|
@@ -314,12 +321,12 @@ end
|
|
314
321
|
'simple_localmemcache' => {
|
315
322
|
:store => :LocalMemCache,
|
316
323
|
:options => ':file => File.join(make_tempdir, "simple_localmemcache")',
|
317
|
-
:specs => STANDARD_SPECS.without_increment
|
324
|
+
:specs => STANDARD_SPECS.without_increment.without_create
|
318
325
|
},
|
319
326
|
'simple_localmemcache_with_expires' => {
|
320
327
|
:store => :LocalMemCache,
|
321
328
|
:options => ':file => File.join(make_tempdir, "simple_localmemcache_with_expires"), :expires => true',
|
322
|
-
:specs => STANDARD_SPECS.without_increment.with_expires
|
329
|
+
:specs => STANDARD_SPECS.without_increment.without_create.with_expires
|
323
330
|
},
|
324
331
|
'simple_tokyocabinet' => {
|
325
332
|
:store => :TokyoCabinet,
|
@@ -365,25 +372,25 @@ end
|
|
365
372
|
:options => ":bucket => 'simple_riak'",
|
366
373
|
# We don't want Riak warnings in tests
|
367
374
|
:preamble => "require 'riak'\n\nRiak.disable_list_keys_warnings = true\n\n",
|
368
|
-
:specs => STANDARD_SPECS.without_increment
|
375
|
+
:specs => STANDARD_SPECS.without_increment.without_create
|
369
376
|
},
|
370
377
|
'simple_riak_with_expires' => {
|
371
378
|
:store => :Riak,
|
372
379
|
:options => ":bucket => 'simple_riak_with_expires', :expires => true",
|
373
380
|
# We don't want Riak warnings in tests
|
374
381
|
:preamble => "require 'riak'\n\nRiak.disable_list_keys_warnings = true\n\n",
|
375
|
-
:specs => STANDARD_SPECS.without_increment.with_expires
|
382
|
+
:specs => STANDARD_SPECS.without_increment.with_expires.without_create
|
376
383
|
},
|
377
384
|
'simple_couch' => {
|
378
385
|
:store => :Couch,
|
379
386
|
:options => ":db => 'simple_couch'",
|
380
387
|
:load_value => '::Marshal.load(value.unpack(\'m\').first)',
|
381
|
-
:specs => STANDARD_SPECS.without_increment
|
388
|
+
:specs => STANDARD_SPECS.without_increment.without_create
|
382
389
|
},
|
383
390
|
'simple_couch_with_expires' => {
|
384
391
|
:store => :Couch,
|
385
392
|
:options => ":db => 'simple_couch_with_expires', :expires => true",
|
386
|
-
:specs => STANDARD_SPECS.without_increment.with_expires,
|
393
|
+
:specs => STANDARD_SPECS.without_increment.without_create.with_expires,
|
387
394
|
:load_value => '::Marshal.load(value.unpack(\'m\').first)'
|
388
395
|
},
|
389
396
|
'simple_mongo' => {
|
@@ -393,11 +400,11 @@ end
|
|
393
400
|
},
|
394
401
|
'simple_null' => {
|
395
402
|
:store => :Null,
|
396
|
-
:specs => STANDARD_SPECS.without_increment.without_store.without_persist
|
403
|
+
:specs => STANDARD_SPECS.without_increment.without_create.without_store.without_persist
|
397
404
|
},
|
398
405
|
'null_adapter' => {
|
399
406
|
:build => 'Moneta::Adapters::Null.new',
|
400
|
-
:specs => Specs.new(:specs => [:null, :not_increment, :not_persist])
|
407
|
+
:specs => Specs.new(:specs => [:null, :not_increment, :not_create, :not_persist])
|
401
408
|
},
|
402
409
|
'simple_sequel' => {
|
403
410
|
:store => :Sequel,
|
@@ -449,7 +456,7 @@ end
|
|
449
456
|
},
|
450
457
|
'simple_fog' => {
|
451
458
|
:store => :Fog,
|
452
|
-
:specs => STANDARD_SPECS.without_increment,
|
459
|
+
:specs => STANDARD_SPECS.without_increment.without_create,
|
453
460
|
:options => ":aws_access_key_id => 'fake_access_key_id',
|
454
461
|
:aws_secret_access_key => 'fake_secret_access_key',
|
455
462
|
:provider => 'AWS',
|
@@ -466,7 +473,21 @@ end
|
|
466
473
|
:expires => true",
|
467
474
|
# Put Fog into testing mode
|
468
475
|
:preamble => "require 'fog'\nFog.mock!\n",
|
469
|
-
:specs => STANDARD_SPECS.without_increment.with_expires
|
476
|
+
:specs => STANDARD_SPECS.without_increment.without_create.with_expires
|
477
|
+
},
|
478
|
+
'weak_create' => {
|
479
|
+
:build => %{Moneta.build do
|
480
|
+
use :WeakCreate
|
481
|
+
adapter :Memory
|
482
|
+
end},
|
483
|
+
:specs => STANDARD_SPECS.without_transform.without_persist.returnsame
|
484
|
+
},
|
485
|
+
'weak_increment' => {
|
486
|
+
:build => %{Moneta.build do
|
487
|
+
use :WeakIncrement
|
488
|
+
adapter :Memory
|
489
|
+
end},
|
490
|
+
:specs => STANDARD_SPECS.without_transform.without_persist.returnsame
|
470
491
|
},
|
471
492
|
'expires_memory' => {
|
472
493
|
:build => %{Moneta.build do
|
@@ -549,10 +570,27 @@ end
|
|
549
570
|
end},
|
550
571
|
:specs => ADAPTER_SPECS.without_persist.returnsame
|
551
572
|
},
|
552
|
-
'
|
573
|
+
'shared_tcp' => {
|
553
574
|
:build => %{Moneta.build do
|
554
575
|
use(:Shared, :port => 9001) do
|
555
|
-
adapter :PStore, :file => File.join(make_tempdir, '
|
576
|
+
adapter :PStore, :file => File.join(make_tempdir, 'shared_tcp')
|
577
|
+
end
|
578
|
+
end},
|
579
|
+
:specs => ADAPTER_SPECS,
|
580
|
+
:tests => %{
|
581
|
+
it 'shares values' do
|
582
|
+
store['shared_key'] = 'shared_value'
|
583
|
+
second = new_store
|
584
|
+
second.key?('shared_key').should be_true
|
585
|
+
second['shared_key'].should == 'shared_value'
|
586
|
+
second.close
|
587
|
+
end
|
588
|
+
}
|
589
|
+
},
|
590
|
+
'shared_unix' => {
|
591
|
+
:build => %{Moneta.build do
|
592
|
+
use(:Shared, :socket => File.join(make_tempdir, 'shared_unix.socket')) do
|
593
|
+
adapter :PStore, :file => File.join(make_tempdir, 'shared_unix')
|
556
594
|
end
|
557
595
|
end},
|
558
596
|
:specs => ADAPTER_SPECS,
|
@@ -575,7 +613,7 @@ end
|
|
575
613
|
add { adapter :Memory }
|
576
614
|
end
|
577
615
|
end},
|
578
|
-
:specs => ADAPTER_SPECS.without_increment
|
616
|
+
:specs => ADAPTER_SPECS.without_increment.without_create
|
579
617
|
},
|
580
618
|
'stack_memory_file' => {
|
581
619
|
:build => %{Moneta.build do
|
@@ -586,7 +624,7 @@ end},
|
|
586
624
|
add { adapter :File, :dir => File.join(make_tempdir, "stack_memory_file") }
|
587
625
|
end
|
588
626
|
end},
|
589
|
-
:specs => STANDARD_SPECS.without_increment.returnsame.without_transform.stringkeys_only.stringvalues_only
|
627
|
+
:specs => STANDARD_SPECS.without_increment.without_create.returnsame.without_transform.stringkeys_only.stringvalues_only
|
590
628
|
},
|
591
629
|
'lock' => {
|
592
630
|
:build => %{Moneta.build do
|
@@ -810,6 +848,19 @@ end},
|
|
810
848
|
it 'compile transformer class' do
|
811
849
|
store.should_not be_nil
|
812
850
|
Moneta::Transformer::To_sKey.should_not be_nil
|
851
|
+
end}
|
852
|
+
},
|
853
|
+
'transformer_key_inspect' => {
|
854
|
+
:build => %{Moneta.build do
|
855
|
+
use :Transformer, :key => :inspect
|
856
|
+
adapter :Memory
|
857
|
+
end},
|
858
|
+
:specs => TRANSFORMER_SPECS.returnsame.simplekeys_only,
|
859
|
+
:load_value => 'value',
|
860
|
+
:tests => %{
|
861
|
+
it 'compile transformer class' do
|
862
|
+
store.should_not be_nil
|
863
|
+
Moneta::Transformer::InspectKey.should_not be_nil
|
813
864
|
end}
|
814
865
|
},
|
815
866
|
'transformer_value_marshal' => {
|
@@ -1050,19 +1101,19 @@ end
|
|
1050
1101
|
'adapter_restclient' => {
|
1051
1102
|
:preamble => "start_restserver\n",
|
1052
1103
|
:build => "Moneta::Adapters::RestClient.new(:url => 'http://localhost:8808/moneta/')",
|
1053
|
-
:specs => ADAPTER_SPECS.without_increment
|
1104
|
+
:specs => ADAPTER_SPECS.without_increment.without_create
|
1054
1105
|
},
|
1055
1106
|
'adapter_cassandra' => {
|
1056
1107
|
:build => "Moneta::Adapters::Cassandra.new(:keyspace => 'adapter_cassandra')",
|
1057
|
-
:specs => ADAPTER_SPECS.without_increment.with_native_expires
|
1108
|
+
:specs => ADAPTER_SPECS.without_increment.without_create.with_native_expires
|
1058
1109
|
},
|
1059
1110
|
'adapter_cassandra_with_default_expires' => {
|
1060
1111
|
:build => %{Moneta::Adapters::Cassandra.new(:keyspace => 'adapter_cassandra_with_default_expires', :expires => 1)},
|
1061
|
-
:specs => ADAPTER_SPECS.without_increment.with_native_expires.with_default_expires
|
1112
|
+
:specs => ADAPTER_SPECS.without_increment.without_create.with_native_expires.with_default_expires
|
1062
1113
|
},
|
1063
1114
|
'adapter_hbase' => {
|
1064
1115
|
:build => "Moneta::Adapters::HBase.new(:table => 'adapter_hbase')",
|
1065
|
-
:specs => ADAPTER_SPECS
|
1116
|
+
:specs => ADAPTER_SPECS.without_create
|
1066
1117
|
},
|
1067
1118
|
'adapter_cookie' => {
|
1068
1119
|
:build => 'Moneta::Adapters::Cookie.new',
|
@@ -1070,7 +1121,7 @@ end
|
|
1070
1121
|
},
|
1071
1122
|
'adapter_couch' => {
|
1072
1123
|
:build => "Moneta::Adapters::Couch.new(:db => 'adapter_couch')",
|
1073
|
-
:specs => ADAPTER_SPECS.without_increment
|
1124
|
+
:specs => ADAPTER_SPECS.without_increment.without_create
|
1074
1125
|
},
|
1075
1126
|
'adapter_datamapper' => {
|
1076
1127
|
:build => 'Moneta::Adapters::DataMapper.new(:setup => "sqlite3://#{make_tempdir}/adapter_datamapper")',
|
@@ -1132,15 +1183,15 @@ end
|
|
1132
1183
|
# Put Fog into testing mode
|
1133
1184
|
:preamble => "require 'fog'\nFog.mock!\n",
|
1134
1185
|
# Fog returns same object in mocking mode (in-memory store)
|
1135
|
-
:specs => ADAPTER_SPECS.without_increment.returnsame
|
1186
|
+
:specs => ADAPTER_SPECS.without_increment.without_create.returnsame
|
1136
1187
|
},
|
1137
1188
|
'adapter_gdbm' => {
|
1138
1189
|
:build => 'Moneta::Adapters::GDBM.new(:file => File.join(make_tempdir, "adapter_gdbm"))',
|
1139
|
-
:specs => ADAPTER_SPECS
|
1190
|
+
:specs => ADAPTER_SPECS.without_multiprocess
|
1140
1191
|
},
|
1141
1192
|
'adapter_localmemcache' => {
|
1142
1193
|
:build => 'Moneta::Adapters::LocalMemCache.new(:file => File.join(make_tempdir, "adapter_localmemcache"))',
|
1143
|
-
:specs => ADAPTER_SPECS.without_increment
|
1194
|
+
:specs => ADAPTER_SPECS.without_increment.without_create
|
1144
1195
|
},
|
1145
1196
|
'adapter_memcached_dalli' => {
|
1146
1197
|
:build => 'Moneta::Adapters::MemcachedDalli.new(:namespace => "adapter_memcached_dalli")',
|
@@ -1218,7 +1269,7 @@ end}
|
|
1218
1269
|
'adapter_riak' => {
|
1219
1270
|
:build => 'Moneta::Adapters::Riak.new',
|
1220
1271
|
:options => ":bucket => 'adapter_riak'",
|
1221
|
-
:specs => ADAPTER_SPECS.without_increment,
|
1272
|
+
:specs => ADAPTER_SPECS.without_increment.without_create,
|
1222
1273
|
# We don't want Riak warnings in tests
|
1223
1274
|
:preamble => "require 'riak'\n\nRiak.disable_list_keys_warnings = true\n\n"
|
1224
1275
|
},
|
@@ -1250,6 +1301,133 @@ end}
|
|
1250
1301
|
:build => 'Moneta::Adapters::YAML.new(:file => File.join(make_tempdir, "adapter_yaml"))',
|
1251
1302
|
:specs => STANDARD_SPECS.simplevalues_only.simplekeys_only.without_transform
|
1252
1303
|
},
|
1304
|
+
'mutex' => {
|
1305
|
+
:store => :Memory,
|
1306
|
+
:specs => Specs.new,
|
1307
|
+
:tests => %{
|
1308
|
+
it 'should have #lock' do
|
1309
|
+
mutex = Moneta::Mutex.new(store, 'mutex')
|
1310
|
+
mutex.lock.should be_true
|
1311
|
+
mutex.locked?.should be_true
|
1312
|
+
expect do
|
1313
|
+
mutex.lock
|
1314
|
+
end.to raise_error(RuntimeError)
|
1315
|
+
expect do
|
1316
|
+
mutex.try_lock
|
1317
|
+
end.to raise_error(RuntimeError)
|
1318
|
+
mutex.unlock.should be_nil
|
1319
|
+
mutex.locked?.should be_false
|
1320
|
+
end
|
1321
|
+
|
1322
|
+
it 'should have #enter' do
|
1323
|
+
mutex = Moneta::Mutex.new(store, 'mutex')
|
1324
|
+
mutex.enter.should be_true
|
1325
|
+
mutex.locked?.should be_true
|
1326
|
+
expect do
|
1327
|
+
mutex.enter
|
1328
|
+
end.to raise_error(RuntimeError)
|
1329
|
+
expect do
|
1330
|
+
mutex.try_enter
|
1331
|
+
end.to raise_error(RuntimeError)
|
1332
|
+
mutex.leave.should be_nil
|
1333
|
+
mutex.locked?.should be_false
|
1334
|
+
end
|
1335
|
+
|
1336
|
+
it 'should lock with #lock' do
|
1337
|
+
a = Moneta::Mutex.new(store, 'mutex')
|
1338
|
+
b = Moneta::Mutex.new(store, 'mutex')
|
1339
|
+
a.lock.should be_true
|
1340
|
+
b.try_lock.should be_false
|
1341
|
+
a.unlock.should be_nil
|
1342
|
+
end
|
1343
|
+
|
1344
|
+
it 'should have lock timeout' do
|
1345
|
+
a = Moneta::Mutex.new(store, 'mutex')
|
1346
|
+
b = Moneta::Mutex.new(store, 'mutex')
|
1347
|
+
a.lock.should be_true
|
1348
|
+
b.lock(1).should be_false
|
1349
|
+
a.unlock.should be_nil
|
1350
|
+
end
|
1351
|
+
|
1352
|
+
it 'should have #synchronize' do
|
1353
|
+
mutex = Moneta::Mutex.new(store, 'mutex')
|
1354
|
+
mutex.synchronize do
|
1355
|
+
mutex.locked?.should be_true
|
1356
|
+
end
|
1357
|
+
mutex.locked?.should be_false
|
1358
|
+
end
|
1359
|
+
}
|
1360
|
+
},
|
1361
|
+
'semaphore' => {
|
1362
|
+
:store => :Memory,
|
1363
|
+
:specs => Specs.new,
|
1364
|
+
:tests => %{
|
1365
|
+
it 'should have #lock' do
|
1366
|
+
mutex = Moneta::Semaphore.new(store, 'semaphore')
|
1367
|
+
mutex.lock.should be_true
|
1368
|
+
mutex.locked?.should be_true
|
1369
|
+
expect do
|
1370
|
+
mutex.lock
|
1371
|
+
end.to raise_error(RuntimeError)
|
1372
|
+
expect do
|
1373
|
+
mutex.try_lock
|
1374
|
+
end.to raise_error(RuntimeError)
|
1375
|
+
mutex.unlock.should be_nil
|
1376
|
+
mutex.locked?.should be_false
|
1377
|
+
end
|
1378
|
+
|
1379
|
+
it 'should have #enter' do
|
1380
|
+
mutex = Moneta::Semaphore.new(store, 'semaphore')
|
1381
|
+
mutex.enter.should be_true
|
1382
|
+
mutex.locked?.should be_true
|
1383
|
+
expect do
|
1384
|
+
mutex.enter
|
1385
|
+
end.to raise_error(RuntimeError)
|
1386
|
+
expect do
|
1387
|
+
mutex.try_enter
|
1388
|
+
end.to raise_error(RuntimeError)
|
1389
|
+
mutex.leave.should be_nil
|
1390
|
+
mutex.locked?.should be_false
|
1391
|
+
end
|
1392
|
+
|
1393
|
+
it 'should lock with #lock' do
|
1394
|
+
a = Moneta::Semaphore.new(store, 'semaphore')
|
1395
|
+
b = Moneta::Semaphore.new(store, 'semaphore')
|
1396
|
+
a.lock.should be_true
|
1397
|
+
b.try_lock.should be_false
|
1398
|
+
a.unlock.should be_nil
|
1399
|
+
end
|
1400
|
+
|
1401
|
+
it 'should have lock timeout' do
|
1402
|
+
a = Moneta::Semaphore.new(store, 'semaphore')
|
1403
|
+
b = Moneta::Semaphore.new(store, 'semaphore')
|
1404
|
+
a.lock.should be_true
|
1405
|
+
b.lock(1).should be_false
|
1406
|
+
a.unlock.should be_nil
|
1407
|
+
end
|
1408
|
+
|
1409
|
+
it 'should count concurrent accesses' do
|
1410
|
+
a = Moneta::Semaphore.new(store, 'semaphore', 2)
|
1411
|
+
b = Moneta::Semaphore.new(store, 'semaphore', 2)
|
1412
|
+
c = Moneta::Semaphore.new(store, 'semaphore', 2)
|
1413
|
+
a.synchronize do
|
1414
|
+
a.locked?.should be_true
|
1415
|
+
b.synchronize do
|
1416
|
+
b.locked?.should be_true
|
1417
|
+
c.try_lock.should be_false
|
1418
|
+
end
|
1419
|
+
end
|
1420
|
+
end
|
1421
|
+
|
1422
|
+
it 'should have #synchronize' do
|
1423
|
+
semaphore = Moneta::Semaphore.new(store, 'semaphore')
|
1424
|
+
semaphore.synchronize do
|
1425
|
+
semaphore.locked?.should be_true
|
1426
|
+
end
|
1427
|
+
semaphore.locked?.should be_false
|
1428
|
+
end
|
1429
|
+
}
|
1430
|
+
},
|
1253
1431
|
'optionmerger' => {
|
1254
1432
|
:store => :Memory,
|
1255
1433
|
:specs => Specs.new,
|
@@ -1314,22 +1492,20 @@ it 'merges options except for some methods' do
|
|
1314
1492
|
end
|
1315
1493
|
|
1316
1494
|
it 'has method #raw' do
|
1317
|
-
store.raw.default_options.should == {:store=>{:raw=>true},:load=>{:raw=>true},:delete=>{:raw=>true}}
|
1495
|
+
store.raw.default_options.should == {:store=>{:raw=>true},:create=>{:raw=>true},:load=>{:raw=>true},:delete=>{:raw=>true}}
|
1318
1496
|
store.raw.should equal(store.raw.raw)
|
1319
1497
|
end
|
1320
1498
|
|
1321
1499
|
it 'has method #prefix' do
|
1322
|
-
store.prefix('a').default_options.should == {:store=>{:prefix=>'a'},:load=>{:prefix=>'a'},
|
1500
|
+
store.prefix('a').default_options.should == {:store=>{:prefix=>'a'},:load=>{:prefix=>'a'},:create=>{:prefix=>'a'},
|
1323
1501
|
:delete=>{:prefix=>'a'},:key? => {:prefix=>'a'},:increment=>{:prefix=>'a'}}
|
1324
1502
|
|
1325
|
-
store.prefix('a').prefix('b').default_options.should == {:store=>{:prefix=>'ab'},:load=>{:prefix=>'ab'},
|
1503
|
+
store.prefix('a').prefix('b').default_options.should == {:store=>{:prefix=>'ab'},:load=>{:prefix=>'ab'},:create=>{:prefix=>'ab'},
|
1326
1504
|
:delete=>{:prefix=>'ab'},:key? => {:prefix=>'ab'},:increment=>{:prefix=>'ab'}}
|
1327
1505
|
|
1328
|
-
store.raw.prefix('b').default_options.should == {:store=>{:raw=>true,:prefix=>'b'},:load=>{:raw=>true,:prefix=>'b'}
|
1329
|
-
:delete=>{:raw=>true,:prefix=>'b'},:key? => {:prefix=>'b'},:increment=>{:prefix=>'b'}}
|
1506
|
+
store.raw.prefix('b').default_options.should == {:store=>{:raw=>true,:prefix=>'b'},:load=>{:raw=>true,:prefix=>'b'},:create=>{:raw=>true,:prefix=>'b'},:delete=>{:raw=>true,:prefix=>'b'},:key? => {:prefix=>'b'},:increment=>{:prefix=>'b'}}
|
1330
1507
|
|
1331
|
-
store.prefix('a').raw.default_options.should == {:store=>{:raw=>true,:prefix=>'a'},:load=>{:raw=>true,:prefix=>'a'}
|
1332
|
-
:delete=>{:raw=>true,:prefix=>'a'},:key? => {:prefix=>'a'},:increment=>{:prefix=>'a'}}
|
1508
|
+
store.prefix('a').raw.default_options.should == {:store=>{:raw=>true,:prefix=>'a'},:load=>{:raw=>true,:prefix=>'a'},:create=>{:raw=>true,:prefix=>'a'},:delete=>{:raw=>true,:prefix=>'a'},:key? => {:prefix=>'a'},:increment=>{:prefix=>'a'}}
|
1333
1509
|
end
|
1334
1510
|
|
1335
1511
|
it 'supports adding proxis using #with' do
|
@@ -1796,6 +1972,67 @@ it 'raises error in #decrement on non integer value' do
|
|
1796
1972
|
expect do
|
1797
1973
|
store.decrement('strkey')
|
1798
1974
|
end.to raise_error
|
1975
|
+
end
|
1976
|
+
|
1977
|
+
it 'supports Semaphore' do
|
1978
|
+
a = Moneta::Semaphore.new(store, 'semaphore', 2)
|
1979
|
+
b = Moneta::Semaphore.new(store, 'semaphore', 2)
|
1980
|
+
c = Moneta::Semaphore.new(store, 'semaphore', 2)
|
1981
|
+
a.synchronize do
|
1982
|
+
a.locked?.should be_true
|
1983
|
+
b.synchronize do
|
1984
|
+
b.locked?.should be_true
|
1985
|
+
c.try_lock.should be_false
|
1986
|
+
end
|
1987
|
+
end
|
1988
|
+
end
|
1989
|
+
}
|
1990
|
+
|
1991
|
+
SPECS['create'] = %{it 'creates the given key' do
|
1992
|
+
store.create('key','value').should be_true
|
1993
|
+
store['key'].should == 'value'
|
1994
|
+
end
|
1995
|
+
|
1996
|
+
it 'creates raw value with the given key' do
|
1997
|
+
store.raw.create('key','value').should be_true
|
1998
|
+
store.raw['key'].should == 'value'
|
1999
|
+
end
|
2000
|
+
|
2001
|
+
it 'does not create a key if it exists' do
|
2002
|
+
store['key'] = 'value'
|
2003
|
+
store.create('key','another value').should be_false
|
2004
|
+
store['key'].should == 'value'
|
2005
|
+
end
|
2006
|
+
|
2007
|
+
it 'supports Mutex' do
|
2008
|
+
a = Moneta::Mutex.new(store, 'mutex')
|
2009
|
+
b = Moneta::Mutex.new(store, 'mutex')
|
2010
|
+
a.lock.should be_true
|
2011
|
+
b.try_lock.should be_false
|
2012
|
+
a.unlock.should be_nil
|
2013
|
+
end
|
2014
|
+
}
|
2015
|
+
|
2016
|
+
SPECS['not_create'] = %{it 'does not support #create' do
|
2017
|
+
expect do
|
2018
|
+
store.create('key','value')
|
2019
|
+
end.to raise_error(NotImplementedError)
|
2020
|
+
end}
|
2021
|
+
|
2022
|
+
SPECS['create_expires'] = %{it 'creates the given key and expires it' do
|
2023
|
+
store.create('key','value', :expires => 1).should be_true
|
2024
|
+
store['key'].should == 'value'
|
2025
|
+
sleep 2
|
2026
|
+
store.key?('key').should be_false
|
2027
|
+
end
|
2028
|
+
|
2029
|
+
it 'does not change expires if the key exists' do
|
2030
|
+
store.store('key', 'value', :expires => false).should == 'value'
|
2031
|
+
store.create('key','another value', :expires => 1).should be_false
|
2032
|
+
store['key'].should == 'value'
|
2033
|
+
sleep 2
|
2034
|
+
store['key'].should == 'value'
|
2035
|
+
store.key?('key').should be_true
|
1799
2036
|
end}
|
1800
2037
|
|
1801
2038
|
SPECS['marshallable_key'] = %{it 'refuses to #[] from keys that cannot be marshalled' do
|
@@ -1889,7 +2126,7 @@ it 'might raise exception on invalid value' do
|
|
1889
2126
|
end
|
1890
2127
|
end}
|
1891
2128
|
|
1892
|
-
SPECS['
|
2129
|
+
SPECS['transform_value_expires'] = %{it 'allows to bypass transformer with :raw' do
|
1893
2130
|
store['key'] = 'value'
|
1894
2131
|
load_value(store.load('key', :raw => true)).should == 'value'
|
1895
2132
|
store['key'] = [1,2,3]
|