moneta 0.7.3 → 0.7.4
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.
- data/.travis.yml +17 -51
- data/CHANGES +13 -0
- data/Gemfile +4 -4
- data/README.md +79 -40
- data/Rakefile +40 -25
- data/benchmarks/run.rb +35 -5
- data/lib/moneta.rb +5 -5
- data/lib/moneta/adapters/activerecord.rb +4 -6
- data/lib/moneta/adapters/cassandra.rb +8 -11
- data/lib/moneta/adapters/couch.rb +3 -1
- data/lib/moneta/adapters/daybreak.rb +28 -0
- data/lib/moneta/adapters/fog.rb +3 -3
- data/lib/moneta/adapters/hbase.rb +2 -4
- data/lib/moneta/adapters/memcached/dalli.rb +8 -7
- data/lib/moneta/adapters/memcached/native.rb +8 -9
- data/lib/moneta/adapters/mongo.rb +42 -11
- data/lib/moneta/adapters/pstore.rb +4 -6
- data/lib/moneta/adapters/redis.rb +17 -10
- data/lib/moneta/adapters/restclient.rb +19 -10
- data/lib/moneta/adapters/sequel.rb +4 -6
- data/lib/moneta/adapters/tdb.rb +22 -0
- data/lib/moneta/expires.rb +28 -12
- data/lib/moneta/mixins.rb +64 -3
- data/lib/moneta/pool.rb +37 -0
- data/lib/moneta/proxy.rb +18 -7
- data/lib/moneta/server.rb +1 -1
- data/lib/moneta/shared.rb +2 -2
- data/lib/moneta/transformer/helper.rb +1 -1
- data/lib/moneta/version.rb +1 -1
- data/{spec/generate.rb → script/generate-specs.rb} +195 -91
- data/script/install-bundle.rb +35 -0
- data/spec/helper.rb +6 -0
- data/spec/moneta/adapter_activerecord_spec.rb +1 -1
- data/spec/moneta/adapter_cassandra_spec.rb +1 -12
- data/spec/moneta/adapter_cassandra_with_default_expires_spec.rb +21 -0
- data/spec/moneta/adapter_client_spec.rb +1 -1
- data/spec/moneta/adapter_cookie_spec.rb +1 -1
- data/spec/moneta/adapter_couch_spec.rb +1 -1
- data/spec/moneta/adapter_datamapper_spec.rb +1 -1
- data/spec/moneta/adapter_daybreak_spec.rb +19 -0
- data/spec/moneta/adapter_dbm_spec.rb +1 -1
- data/spec/moneta/adapter_file_spec.rb +1 -1
- data/spec/moneta/adapter_fog_spec.rb +1 -1
- data/spec/moneta/adapter_gdbm_spec.rb +1 -1
- data/spec/moneta/adapter_hbase_spec.rb +1 -1
- data/spec/moneta/adapter_leveldb_spec.rb +1 -1
- data/spec/moneta/adapter_localmemcache_spec.rb +1 -1
- data/spec/moneta/adapter_lruhash_spec.rb +1 -1
- data/spec/moneta/adapter_memcached_dalli_spec.rb +1 -12
- data/spec/moneta/adapter_memcached_dalli_with_default_expires_spec.rb +21 -0
- data/spec/moneta/adapter_memcached_native_spec.rb +1 -13
- data/spec/moneta/adapter_memcached_native_with_default_expires_spec.rb +21 -0
- data/spec/moneta/adapter_memcached_spec.rb +1 -12
- data/spec/moneta/adapter_memcached_with_default_expires_spec.rb +21 -0
- data/spec/moneta/adapter_memory_spec.rb +1 -1
- data/spec/moneta/adapter_mongo_spec.rb +9 -2
- data/spec/moneta/adapter_mongo_with_default_expires_spec.rb +21 -0
- data/spec/moneta/adapter_pstore_spec.rb +1 -1
- data/spec/moneta/adapter_redis_spec.rb +1 -12
- data/spec/moneta/adapter_redis_with_default_expires_spec.rb +21 -0
- data/spec/moneta/adapter_restclient_spec.rb +1 -1
- data/spec/moneta/adapter_riak_spec.rb +1 -1
- data/spec/moneta/adapter_sdbm_spec.rb +1 -1
- data/spec/moneta/adapter_sequel_spec.rb +1 -1
- data/spec/moneta/adapter_sqlite_spec.rb +1 -1
- data/spec/moneta/adapter_tdb_spec.rb +19 -0
- data/spec/moneta/adapter_tokyocabinet_bdb_spec.rb +1 -1
- data/spec/moneta/adapter_tokyocabinet_hdb_spec.rb +1 -1
- data/spec/moneta/adapter_yaml_spec.rb +1 -1
- data/spec/moneta/cache_file_memory_spec.rb +1 -1
- data/spec/moneta/cache_memory_null_spec.rb +1 -1
- data/spec/moneta/expires_file_spec.rb +1 -1
- data/spec/moneta/expires_memory_spec.rb +1 -12
- data/spec/moneta/expires_memory_with_default_expires_spec.rb +111 -0
- data/spec/moneta/lock_spec.rb +1 -1
- data/spec/moneta/null_adapter_spec.rb +1 -1
- data/spec/moneta/optionmerger_spec.rb +1 -1
- data/spec/moneta/pool_spec.rb +23 -0
- data/spec/moneta/proxy_expires_memory_spec.rb +1 -1
- data/spec/moneta/proxy_redis_spec.rb +1 -1
- data/spec/moneta/shared_spec.rb +1 -1
- data/spec/moneta/simple_activerecord_spec.rb +1 -1
- data/spec/moneta/simple_activerecord_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_cassandra_spec.rb +1 -1
- data/spec/moneta/simple_client_tcp_spec.rb +1 -1
- data/spec/moneta/simple_client_unix_spec.rb +1 -1
- data/spec/moneta/simple_couch_spec.rb +1 -1
- data/spec/moneta/simple_couch_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_datamapper_spec.rb +1 -1
- data/spec/moneta/simple_datamapper_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_datamapper_with_repository_spec.rb +1 -1
- data/spec/moneta/simple_daybreak_spec.rb +144 -0
- data/spec/moneta/simple_daybreak_with_expires_spec.rb +145 -0
- data/spec/moneta/simple_dbm_spec.rb +1 -1
- data/spec/moneta/simple_dbm_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_file_spec.rb +1 -1
- data/spec/moneta/simple_file_with_expires_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/simple_gdbm_spec.rb +1 -1
- data/spec/moneta/simple_gdbm_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_hashfile_spec.rb +1 -1
- data/spec/moneta/simple_hashfile_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_hbase_spec.rb +1 -1
- data/spec/moneta/simple_hbase_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_leveldb_spec.rb +1 -1
- data/spec/moneta/simple_leveldb_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_localmemcache_spec.rb +1 -1
- data/spec/moneta/simple_localmemcache_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_lruhash_spec.rb +1 -1
- data/spec/moneta/simple_lruhash_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_memcached_dalli_spec.rb +1 -1
- data/spec/moneta/simple_memcached_native_spec.rb +1 -1
- data/spec/moneta/simple_memcached_spec.rb +1 -1
- data/spec/moneta/simple_memory_spec.rb +1 -1
- data/spec/moneta/simple_memory_with_compress_spec.rb +1 -1
- data/spec/moneta/simple_memory_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_memory_with_json_key_serializer_spec.rb +1 -1
- data/spec/moneta/simple_memory_with_json_serializer_spec.rb +1 -1
- data/spec/moneta/simple_memory_with_json_value_serializer_spec.rb +1 -1
- data/spec/moneta/simple_memory_with_prefix_spec.rb +1 -1
- data/spec/moneta/simple_memory_with_snappy_compress_spec.rb +1 -1
- data/spec/moneta/simple_mongo_spec.rb +3 -2
- data/spec/moneta/simple_null_spec.rb +1 -1
- data/spec/moneta/simple_pstore_spec.rb +1 -1
- data/spec/moneta/simple_pstore_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_redis_spec.rb +1 -1
- data/spec/moneta/simple_restclient_spec.rb +1 -1
- data/spec/moneta/simple_riak_spec.rb +1 -1
- data/spec/moneta/simple_riak_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_sdbm_spec.rb +1 -1
- data/spec/moneta/simple_sdbm_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_sequel_spec.rb +1 -1
- data/spec/moneta/simple_sequel_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_sqlite_spec.rb +1 -1
- data/spec/moneta/simple_sqlite_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_tdb_spec.rb +144 -0
- data/spec/moneta/{simple_mongo_with_expires_spec.rb → simple_tdb_with_expires_spec.rb} +4 -4
- data/spec/moneta/simple_tokyocabinet_spec.rb +1 -1
- data/spec/moneta/simple_tokyocabinet_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_yaml_spec.rb +1 -1
- data/spec/moneta/simple_yaml_with_expires_spec.rb +1 -1
- data/spec/moneta/stack_file_memory_spec.rb +1 -1
- data/spec/moneta/stack_memory_file_spec.rb +1 -1
- data/spec/moneta/transformer_bencode_spec.rb +1 -1
- data/spec/moneta/transformer_bert_spec.rb +1 -1
- data/spec/moneta/transformer_bson_spec.rb +1 -1
- data/spec/moneta/transformer_bzip2_spec.rb +1 -1
- data/spec/moneta/transformer_json_spec.rb +1 -1
- data/spec/moneta/transformer_key_marshal_spec.rb +1 -1
- data/spec/moneta/transformer_key_yaml_spec.rb +1 -1
- data/spec/moneta/transformer_lzma_spec.rb +1 -1
- data/spec/moneta/transformer_lzo_spec.rb +1 -1
- data/spec/moneta/transformer_marshal_base64_spec.rb +1 -1
- data/spec/moneta/transformer_marshal_escape_spec.rb +1 -1
- data/spec/moneta/transformer_marshal_hmac_spec.rb +1 -1
- data/spec/moneta/transformer_marshal_md5_spec.rb +1 -1
- data/spec/moneta/transformer_marshal_md5_spread_spec.rb +1 -1
- data/spec/moneta/transformer_marshal_prefix_spec.rb +1 -1
- data/spec/moneta/transformer_marshal_rmd160_spec.rb +1 -1
- data/spec/moneta/transformer_marshal_sha1_spec.rb +1 -1
- data/spec/moneta/transformer_marshal_sha256_spec.rb +1 -1
- data/spec/moneta/transformer_marshal_sha384_spec.rb +1 -1
- data/spec/moneta/transformer_marshal_sha512_spec.rb +1 -1
- data/spec/moneta/transformer_marshal_spec.rb +1 -1
- data/spec/moneta/transformer_marshal_truncate_spec.rb +1 -1
- data/spec/moneta/transformer_marshal_uuencode_spec.rb +1 -1
- data/spec/moneta/transformer_msgpack_spec.rb +1 -1
- data/spec/moneta/transformer_ox_spec.rb +1 -1
- data/spec/moneta/transformer_quicklz_spec.rb +1 -1
- data/spec/moneta/transformer_snappy_spec.rb +1 -1
- data/spec/moneta/transformer_tnet_spec.rb +1 -1
- data/spec/moneta/transformer_value_marshal_spec.rb +1 -1
- data/spec/moneta/transformer_value_yaml_spec.rb +1 -1
- data/spec/moneta/transformer_yaml_spec.rb +1 -1
- data/spec/moneta/transformer_zlib_spec.rb +1 -1
- data/spec/monetaspecs.rb +105 -3
- metadata +35 -6
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require '
|
|
1
|
+
require 'net/http'
|
|
2
2
|
|
|
3
3
|
module Moneta
|
|
4
4
|
module Adapters
|
|
@@ -10,38 +10,47 @@ module Moneta
|
|
|
10
10
|
# @param [Hash] options
|
|
11
11
|
# @option options [String] :url URL
|
|
12
12
|
def initialize(options = {})
|
|
13
|
-
raise ArgumentError, 'Option :url is required' unless
|
|
13
|
+
raise ArgumentError, 'Option :url is required' unless url = options[:url]
|
|
14
|
+
url = URI(url)
|
|
15
|
+
@path = url.path
|
|
16
|
+
@client = ::Net::HTTP.start(url.host, url.port)
|
|
14
17
|
end
|
|
15
18
|
|
|
16
19
|
# (see Proxy#key?)
|
|
17
20
|
def key?(key, options = {})
|
|
18
|
-
response =
|
|
19
|
-
response.code == 200
|
|
21
|
+
response = @client.request_head(@path + key)
|
|
22
|
+
response.code == '200'
|
|
20
23
|
end
|
|
21
24
|
|
|
22
25
|
# (see Proxy#load)
|
|
23
26
|
def load(key, options = {})
|
|
24
|
-
response =
|
|
25
|
-
response.code == 200 ? response.body : nil
|
|
27
|
+
response = @client.request_get(@path + key)
|
|
28
|
+
response.code == '200' ? response.body : nil
|
|
26
29
|
end
|
|
27
30
|
|
|
28
31
|
# (see Proxy#store)
|
|
29
32
|
def store(key, value, options = {})
|
|
30
|
-
|
|
33
|
+
response = @client.request_post(@path + key, value)
|
|
34
|
+
raise "HTTP error #{response.code}" unless response.code == '200'
|
|
31
35
|
value
|
|
32
36
|
end
|
|
33
37
|
|
|
34
38
|
# (see Proxy#delete)
|
|
35
39
|
def delete(key, options = {})
|
|
36
|
-
response =
|
|
37
|
-
response.code == 200 ? response.body : nil
|
|
40
|
+
response = @client.request(::Net::HTTP::Delete.new(@path + key))
|
|
41
|
+
response.code == '200' ? response.body : nil
|
|
38
42
|
end
|
|
39
43
|
|
|
40
44
|
# (see Proxy#clear)
|
|
41
45
|
def clear(options = {})
|
|
42
|
-
|
|
46
|
+
@client.request(::Net::HTTP::Delete.new(@path))
|
|
43
47
|
self
|
|
44
48
|
end
|
|
49
|
+
|
|
50
|
+
def close
|
|
51
|
+
@client.finish
|
|
52
|
+
nil
|
|
53
|
+
end
|
|
45
54
|
end
|
|
46
55
|
end
|
|
47
56
|
end
|
|
@@ -6,6 +6,7 @@ module Moneta
|
|
|
6
6
|
# @api public
|
|
7
7
|
class Sequel
|
|
8
8
|
include Defaults
|
|
9
|
+
include IncrementSupport
|
|
9
10
|
|
|
10
11
|
# @param [Hash] options
|
|
11
12
|
# @option options [String] :db Sequel database
|
|
@@ -50,12 +51,9 @@ module Moneta
|
|
|
50
51
|
@db.transaction do
|
|
51
52
|
locked_table = @table.for_update
|
|
52
53
|
if record = locked_table[:k => key]
|
|
53
|
-
value = record[:v]
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
intvalue += amount
|
|
57
|
-
locked_table.update(:k => key, :v => intvalue.to_s)
|
|
58
|
-
intvalue
|
|
54
|
+
value = convert_for_increment(record[:v]) + amount
|
|
55
|
+
locked_table.update(:k => key, :v => value.to_s)
|
|
56
|
+
value
|
|
59
57
|
else
|
|
60
58
|
locked_table.insert(:k => key, :v => amount.to_s)
|
|
61
59
|
amount
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
require 'tdb'
|
|
2
|
+
|
|
3
|
+
module Moneta
|
|
4
|
+
module Adapters
|
|
5
|
+
# TDB backend
|
|
6
|
+
# @api public
|
|
7
|
+
class TDB < Memory
|
|
8
|
+
# @param [Hash] options
|
|
9
|
+
# @option options [String] :file Database file
|
|
10
|
+
def initialize(options = {})
|
|
11
|
+
raise ArgumentError, 'Option :file is required' unless file = options.delete(:file)
|
|
12
|
+
@hash = ::TDB.new(file, options)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# (see Proxy#close)
|
|
16
|
+
def close
|
|
17
|
+
@hash.close
|
|
18
|
+
nil
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
data/lib/moneta/expires.rb
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
module Moneta
|
|
2
2
|
# Adds expiration support to the underlying store
|
|
3
3
|
#
|
|
4
|
-
#
|
|
4
|
+
# `#store`, `#load` and `#key?` support the `:expires` option to set/update
|
|
5
5
|
# the expiration time.
|
|
6
6
|
#
|
|
7
7
|
# @api public
|
|
8
8
|
class Expires < Proxy
|
|
9
|
+
include ExpiresSupport
|
|
10
|
+
|
|
9
11
|
# @param [Moneta store] adapter The underlying store
|
|
10
12
|
# @param [Hash] options
|
|
11
13
|
# @option options [String] :expires Default expiration time
|
|
12
14
|
def initialize(adapter, options = {})
|
|
13
15
|
super
|
|
14
|
-
|
|
16
|
+
self.default_expires = options[:expires]
|
|
15
17
|
end
|
|
16
18
|
|
|
17
19
|
# (see Proxy#key?)
|
|
@@ -33,14 +35,12 @@ module Moneta
|
|
|
33
35
|
# (see Proxy#store)
|
|
34
36
|
def store(key, value, options = {})
|
|
35
37
|
return super if options.include?(:raw)
|
|
36
|
-
expires =
|
|
37
|
-
if expires
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
super(key, [value], options)
|
|
41
|
-
else
|
|
42
|
-
super(key, value, options)
|
|
38
|
+
expires = expires_at(options)
|
|
39
|
+
if options.include?(:expires)
|
|
40
|
+
options = options.dup
|
|
41
|
+
options.delete(:expires)
|
|
43
42
|
end
|
|
43
|
+
store_entry(key, value, expires, options)
|
|
44
44
|
value
|
|
45
45
|
end
|
|
46
46
|
|
|
@@ -54,20 +54,36 @@ module Moneta
|
|
|
54
54
|
private
|
|
55
55
|
|
|
56
56
|
def load_entry(key, options)
|
|
57
|
-
new_expires =
|
|
57
|
+
new_expires = expires_at(options, nil)
|
|
58
|
+
if options.include?(:expires)
|
|
59
|
+
options = options.dup
|
|
60
|
+
options.delete(:expires)
|
|
61
|
+
end
|
|
58
62
|
entry = @adapter.load(key, options)
|
|
59
63
|
if entry != nil
|
|
60
64
|
value, expires = entry
|
|
61
65
|
if expires && Time.now.to_i > expires
|
|
62
66
|
delete(key)
|
|
63
67
|
nil
|
|
64
|
-
elsif new_expires
|
|
65
|
-
|
|
68
|
+
elsif new_expires != nil
|
|
69
|
+
store_entry(key, value, new_expires, options)
|
|
66
70
|
entry
|
|
67
71
|
else
|
|
68
72
|
entry
|
|
69
73
|
end
|
|
70
74
|
end
|
|
71
75
|
end
|
|
76
|
+
|
|
77
|
+
def store_entry(key, value, expires, options)
|
|
78
|
+
entry =
|
|
79
|
+
if expires
|
|
80
|
+
[value, expires.to_i]
|
|
81
|
+
elsif Array === value || value == nil
|
|
82
|
+
[value]
|
|
83
|
+
else
|
|
84
|
+
value
|
|
85
|
+
end
|
|
86
|
+
@adapter.store(key, entry, options)
|
|
87
|
+
end
|
|
72
88
|
end
|
|
73
89
|
end
|
data/lib/moneta/mixins.rb
CHANGED
|
@@ -51,6 +51,9 @@ module Moneta
|
|
|
51
51
|
#
|
|
52
52
|
# @param [Object] key
|
|
53
53
|
# @param [Hash] options
|
|
54
|
+
# @option options [Integer] :expires Update expiration time (See `Moneta::Expires`)
|
|
55
|
+
# @option options [String] :prefix Prefix key (See `Moneta::Transformer`)
|
|
56
|
+
# @option options Other options as defined by the adapters or middleware
|
|
54
57
|
# @return [Boolean]
|
|
55
58
|
# @api public
|
|
56
59
|
def key?(key, options = {})
|
|
@@ -146,11 +149,16 @@ module Moneta
|
|
|
146
149
|
# (see Defaults#increment)
|
|
147
150
|
# @api public
|
|
148
151
|
def increment(key, amount = 1, options = {})
|
|
149
|
-
value = load(key, options)
|
|
152
|
+
value = convert_for_increment(load(key, options)) + amount
|
|
153
|
+
store(key, value.to_s, options)
|
|
154
|
+
value
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
protected
|
|
158
|
+
|
|
159
|
+
def convert_for_increment(value)
|
|
150
160
|
intvalue = value.to_i
|
|
151
161
|
raise 'Tried to increment non integer value' unless value == nil || intvalue.to_s == value.to_s
|
|
152
|
-
intvalue += amount
|
|
153
|
-
store(key, intvalue.to_s, options)
|
|
154
162
|
intvalue
|
|
155
163
|
end
|
|
156
164
|
end
|
|
@@ -204,4 +212,57 @@ module Moneta
|
|
|
204
212
|
io.write(pack(o))
|
|
205
213
|
end
|
|
206
214
|
end
|
|
215
|
+
|
|
216
|
+
# This mixin handles the calculation of expiration times.
|
|
217
|
+
#
|
|
218
|
+
#
|
|
219
|
+
module ExpiresSupport
|
|
220
|
+
attr_accessor :default_expires
|
|
221
|
+
|
|
222
|
+
protected
|
|
223
|
+
|
|
224
|
+
# Calculates the time when something will expire.
|
|
225
|
+
#
|
|
226
|
+
# This method considers false and 0 as "no-expire" and every positive
|
|
227
|
+
# number as a time to live in seconds.
|
|
228
|
+
#
|
|
229
|
+
# @param [Hash] options Options hash
|
|
230
|
+
# @option options [0,false,nil,Numeric] :expires expires value given by user
|
|
231
|
+
# @param [0,false,nil,Numeric] default default expiration time
|
|
232
|
+
#
|
|
233
|
+
# @return [false] if it should not expire
|
|
234
|
+
# @return [Time] the time when something should expire
|
|
235
|
+
# @return [nil] if it is not known
|
|
236
|
+
def expires_at(options, default = @default_expires)
|
|
237
|
+
value = expires_value(options, default)
|
|
238
|
+
Numeric === value ? Time.now + value : value
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
# Calculates the number of seconds something should last.
|
|
242
|
+
#
|
|
243
|
+
# This method considers false and 0 as "no-expire" and every positive
|
|
244
|
+
# number as a time to live in seconds.
|
|
245
|
+
#
|
|
246
|
+
# @param [Hash] options Options hash
|
|
247
|
+
# @option options [0,false,nil,Numeric] :expires expires value given by user
|
|
248
|
+
# @param [0,false,nil,Numeric] default default expiration time
|
|
249
|
+
#
|
|
250
|
+
# @return [false] if it should not expire
|
|
251
|
+
# @return [Numeric] seconds until expiration
|
|
252
|
+
# @return [nil] if it is not known
|
|
253
|
+
def expires_value(options, default = @default_expires)
|
|
254
|
+
case value = options[:expires]
|
|
255
|
+
when 0, false
|
|
256
|
+
false
|
|
257
|
+
when nil
|
|
258
|
+
default ? default.to_i : nil
|
|
259
|
+
when Numeric
|
|
260
|
+
value = value.to_i
|
|
261
|
+
raise ArgumentError, ":expires must be a positive value, got #{value}" if value < 0
|
|
262
|
+
value
|
|
263
|
+
else
|
|
264
|
+
raise ArgumentError, ":expires must be Numeric or false, got #{value.inspect}"
|
|
265
|
+
end
|
|
266
|
+
end
|
|
267
|
+
end
|
|
207
268
|
end
|
data/lib/moneta/pool.rb
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
module Moneta
|
|
2
|
+
# Creates a pool of stores.
|
|
3
|
+
# Each thread gets its own store.
|
|
4
|
+
#
|
|
5
|
+
# @example Add `Moneta::Pool` to proxy stack
|
|
6
|
+
# Moneta.build do
|
|
7
|
+
# use(:Pool) do
|
|
8
|
+
# # Every thread gets its own instance
|
|
9
|
+
# adapter :MemcachedNative
|
|
10
|
+
# end
|
|
11
|
+
# end
|
|
12
|
+
#
|
|
13
|
+
# @api public
|
|
14
|
+
class Pool < Wrapper
|
|
15
|
+
# @param [Moneta store] adapter The underlying store
|
|
16
|
+
# @param [Hash] options
|
|
17
|
+
def initialize(options = {}, &block)
|
|
18
|
+
super(nil)
|
|
19
|
+
@builder = Builder.new(&block)
|
|
20
|
+
@pool, @active = [], {}
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
protected
|
|
24
|
+
|
|
25
|
+
def adapter
|
|
26
|
+
@active[Thread.current]
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def wrap(*args)
|
|
30
|
+
@pool << @builder.build.last if @pool.empty?
|
|
31
|
+
@active[Thread.current] = @pool.pop
|
|
32
|
+
yield
|
|
33
|
+
ensure
|
|
34
|
+
@pool << @active.delete(Thread.current)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
data/lib/moneta/proxy.rb
CHANGED
|
@@ -14,27 +14,31 @@ module Moneta
|
|
|
14
14
|
|
|
15
15
|
# (see Defaults#key?)
|
|
16
16
|
def key?(key, options = {})
|
|
17
|
-
|
|
17
|
+
adapter.key?(key, options)
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
# (see Defaults#increment)
|
|
21
21
|
def increment(key, amount = 1, options = {})
|
|
22
|
-
|
|
22
|
+
adapter.increment(key, amount, options)
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
# (see Defaults#close)
|
|
26
26
|
def close
|
|
27
|
-
|
|
27
|
+
adapter.close
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
# Fetch value with key. Return nil if the key doesn't exist
|
|
31
31
|
#
|
|
32
32
|
# @param [Object] key
|
|
33
33
|
# @param [Hash] options
|
|
34
|
+
# @option options [Integer] :expires Update expiration time (See `Moneta::Expires`)
|
|
35
|
+
# @option options [Boolean] :raw Raw access without value transformation (See `Moneta::Transformer`)
|
|
36
|
+
# @option options [String] :prefix Prefix key (See `Moneta::Transformer`)
|
|
37
|
+
# @option options Other options as defined by the adapters or middleware
|
|
34
38
|
# @return [Object] value
|
|
35
39
|
# @api public
|
|
36
40
|
def load(key, options = {})
|
|
37
|
-
|
|
41
|
+
adapter.load(key, options)
|
|
38
42
|
end
|
|
39
43
|
|
|
40
44
|
# Store value with key
|
|
@@ -42,10 +46,14 @@ module Moneta
|
|
|
42
46
|
# @param [Object] key
|
|
43
47
|
# @param [Object] value
|
|
44
48
|
# @param [Hash] options
|
|
49
|
+
# @option options [Integer] :expires Set expiration time (See `Moneta::Expires`)
|
|
50
|
+
# @option options [Boolean] :raw Raw access without value transformation (See `Moneta::Transformer`)
|
|
51
|
+
# @option options [String] :prefix Prefix key (See `Moneta::Transformer`)
|
|
52
|
+
# @option options Other options as defined by the adapters or middleware
|
|
45
53
|
# @return value
|
|
46
54
|
# @api public
|
|
47
55
|
def store(key, value, options = {})
|
|
48
|
-
|
|
56
|
+
adapter.store(key, value, options)
|
|
49
57
|
end
|
|
50
58
|
|
|
51
59
|
# Delete the key from the store and return the current value
|
|
@@ -53,9 +61,12 @@ module Moneta
|
|
|
53
61
|
# @param [Object] key
|
|
54
62
|
# @return [Object] current value
|
|
55
63
|
# @param [Hash] options
|
|
64
|
+
# @option options [Boolean] :raw Raw access without value transformation (See `Moneta::Transformer`)
|
|
65
|
+
# @option options [String] :prefix Prefix key (See `Moneta::Transformer`)
|
|
66
|
+
# @option options Other options as defined by the adapters or middleware
|
|
56
67
|
# @api public
|
|
57
68
|
def delete(key, options = {})
|
|
58
|
-
|
|
69
|
+
adapter.delete(key, options)
|
|
59
70
|
end
|
|
60
71
|
|
|
61
72
|
# Clear all keys in this store
|
|
@@ -64,7 +75,7 @@ module Moneta
|
|
|
64
75
|
# @return [void]
|
|
65
76
|
# @api public
|
|
66
77
|
def clear(options = {})
|
|
67
|
-
|
|
78
|
+
adapter.clear(options)
|
|
68
79
|
self
|
|
69
80
|
end
|
|
70
81
|
end
|
data/lib/moneta/server.rb
CHANGED
data/lib/moneta/shared.rb
CHANGED
|
@@ -39,7 +39,7 @@ module Moneta
|
|
|
39
39
|
@adapter ||= Adapters::Client.new(@options)
|
|
40
40
|
yield
|
|
41
41
|
rescue Exception => ex
|
|
42
|
-
|
|
42
|
+
warn "Failed to connect: #{ex.message}"
|
|
43
43
|
begin
|
|
44
44
|
# TODO: Implement this using forking (MRI) and threading (JRuby)
|
|
45
45
|
# to get maximal performance
|
|
@@ -48,7 +48,7 @@ module Moneta
|
|
|
48
48
|
@thread = Thread.new { @server.run }
|
|
49
49
|
sleep 0.1 until @server.running?
|
|
50
50
|
rescue Exception => ex
|
|
51
|
-
|
|
51
|
+
warn "Failed to start server: #{ex.message}"
|
|
52
52
|
@adapter.close if @adapter
|
|
53
53
|
@adapter = nil
|
|
54
54
|
end
|
data/lib/moneta/version.rb
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
PATH = File.expand_path(File.join(__FILE__, '..', '..', 'spec'))
|
|
4
|
+
|
|
1
5
|
class Specs
|
|
2
6
|
attr_reader :key, :value, :specs
|
|
3
7
|
|
|
@@ -93,13 +97,19 @@ class Specs
|
|
|
93
97
|
a.delete(:marshallable_value)
|
|
94
98
|
Specs.new(a, key, value)
|
|
95
99
|
end
|
|
100
|
+
|
|
101
|
+
def with_default_expires
|
|
102
|
+
a = specs.dup
|
|
103
|
+
a << :default_expires
|
|
104
|
+
Specs.new(a, key, value)
|
|
105
|
+
end
|
|
96
106
|
end
|
|
97
107
|
|
|
98
108
|
ADAPTER_SPECS = Specs.new([:null, :store, :returndifferent, :increment, :persist], %w(string), %w(string))
|
|
99
109
|
STANDARD_SPECS = Specs.new([:null, :store, :returndifferent, :marshallable_key, :marshallable_value, :transform_value, :increment, :persist])
|
|
100
110
|
TRANSFORMER_SPECS = Specs.new([:null, :store, :returndifferent, :transform_value, :increment])
|
|
101
111
|
|
|
102
|
-
header = "# Generated by #{__FILE__}\n"
|
|
112
|
+
header = "# Generated by #{File.basename(__FILE__)}\n"
|
|
103
113
|
|
|
104
114
|
TESTS = {
|
|
105
115
|
'simple_client_tcp' => {
|
|
@@ -232,6 +242,26 @@ end
|
|
|
232
242
|
:options => ':file => File.join(make_tempdir, "simple_dbm_with_expires"), :expires => true',
|
|
233
243
|
:specs => STANDARD_SPECS.with_expires
|
|
234
244
|
},
|
|
245
|
+
'simple_tdb' => {
|
|
246
|
+
:store => :TDB,
|
|
247
|
+
:options => ':file => File.join(make_tempdir, "simple_tdb")',
|
|
248
|
+
:specs => STANDARD_SPECS
|
|
249
|
+
},
|
|
250
|
+
'simple_tdb_with_expires' => {
|
|
251
|
+
:store => :TDB,
|
|
252
|
+
:options => ':file => File.join(make_tempdir, "simple_tdb_with_expires"), :expires => true',
|
|
253
|
+
:specs => STANDARD_SPECS.with_expires
|
|
254
|
+
},
|
|
255
|
+
'simple_daybreak' => {
|
|
256
|
+
:store => :Daybreak,
|
|
257
|
+
:options => ':file => File.join(make_tempdir, "simple_daybreak")',
|
|
258
|
+
:specs => STANDARD_SPECS
|
|
259
|
+
},
|
|
260
|
+
'simple_daybreak_with_expires' => {
|
|
261
|
+
:store => :Daybreak,
|
|
262
|
+
:options => ':file => File.join(make_tempdir, "simple_daybreak_with_expires"), :expires => true',
|
|
263
|
+
:specs => STANDARD_SPECS.with_expires
|
|
264
|
+
},
|
|
235
265
|
'simple_gdbm' => {
|
|
236
266
|
:store => :GDBM,
|
|
237
267
|
:options => ':file => File.join(make_tempdir, "simple_gdbm")',
|
|
@@ -364,12 +394,7 @@ end
|
|
|
364
394
|
'simple_mongo' => {
|
|
365
395
|
:store => :Mongo,
|
|
366
396
|
:options => ":db => 'simple_mongo'",
|
|
367
|
-
:specs => STANDARD_SPECS.
|
|
368
|
-
},
|
|
369
|
-
'simple_mongo_with_expires' => {
|
|
370
|
-
:store => :Mongo,
|
|
371
|
-
:options => ":db => 'simple_mongo_with_expires', :expires => true",
|
|
372
|
-
:specs => STANDARD_SPECS.without_increment.with_expires
|
|
397
|
+
:specs => STANDARD_SPECS.with_native_expires
|
|
373
398
|
},
|
|
374
399
|
'simple_null' => {
|
|
375
400
|
:store => :Null,
|
|
@@ -453,19 +478,14 @@ end
|
|
|
453
478
|
use :Expires
|
|
454
479
|
adapter :Memory
|
|
455
480
|
end},
|
|
456
|
-
:specs => STANDARD_SPECS.without_transform.with_expires.without_persist
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
store.load('key1').should == 'val1'
|
|
465
|
-
sleep 2
|
|
466
|
-
store.load('key1').should be_nil
|
|
467
|
-
store['key2'].should == 'val2'
|
|
468
|
-
end}
|
|
481
|
+
:specs => STANDARD_SPECS.without_transform.with_expires.without_persist
|
|
482
|
+
},
|
|
483
|
+
'expires_memory_with_default_expires' => {
|
|
484
|
+
:build => %{Moneta.build do
|
|
485
|
+
use :Expires, :expires => 1
|
|
486
|
+
adapter :Memory
|
|
487
|
+
end},
|
|
488
|
+
:specs => STANDARD_SPECS.without_transform.with_expires.with_default_expires.without_persist
|
|
469
489
|
},
|
|
470
490
|
'expires_file' => {
|
|
471
491
|
:build => %{Moneta.build do
|
|
@@ -580,6 +600,14 @@ end},
|
|
|
580
600
|
end},
|
|
581
601
|
:specs => STANDARD_SPECS.without_transform.without_returndifferent.without_persist
|
|
582
602
|
},
|
|
603
|
+
'pool' => {
|
|
604
|
+
:build => %{Moneta.build do
|
|
605
|
+
use :Pool do
|
|
606
|
+
adapter :File, :dir => File.join(make_tempdir, "pool")
|
|
607
|
+
end
|
|
608
|
+
end},
|
|
609
|
+
:specs => ADAPTER_SPECS
|
|
610
|
+
},
|
|
583
611
|
'transformer_zlib' => {
|
|
584
612
|
:build => %{Moneta.build do
|
|
585
613
|
use :Transformer, :value => :zlib
|
|
@@ -857,19 +885,11 @@ end
|
|
|
857
885
|
},
|
|
858
886
|
'adapter_cassandra' => {
|
|
859
887
|
:build => "Moneta::Adapters::Cassandra.new(:keyspace => 'adapter_cassandra')",
|
|
860
|
-
:specs => ADAPTER_SPECS.without_increment.
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
store.store('key2', 'val2', :expires => 60)
|
|
866
|
-
store.load('key1').should == 'val1'
|
|
867
|
-
sleep 1
|
|
868
|
-
store.load('key1').should == 'val1'
|
|
869
|
-
sleep 2
|
|
870
|
-
store.load('key1').should be_nil
|
|
871
|
-
store['key2'].should == 'val2'
|
|
872
|
-
end}
|
|
888
|
+
:specs => ADAPTER_SPECS.without_increment.with_native_expires
|
|
889
|
+
},
|
|
890
|
+
'adapter_cassandra_with_default_expires' => {
|
|
891
|
+
:build => %{Moneta::Adapters::Cassandra.new(:expires => 1)},
|
|
892
|
+
:specs => ADAPTER_SPECS.without_increment.with_native_expires.with_default_expires
|
|
873
893
|
},
|
|
874
894
|
'adapter_hbase' => {
|
|
875
895
|
:build => "Moneta::Adapters::HBase.new(:table => 'adapter_hbase')",
|
|
@@ -923,6 +943,14 @@ end
|
|
|
923
943
|
:build => 'Moneta::Adapters::DBM.new(:file => File.join(make_tempdir, "adapter_dbm"))',
|
|
924
944
|
:specs => ADAPTER_SPECS
|
|
925
945
|
},
|
|
946
|
+
'adapter_tdb' => {
|
|
947
|
+
:build => 'Moneta::Adapters::TDB.new(:file => File.join(make_tempdir, "adapter_tdb"))',
|
|
948
|
+
:specs => ADAPTER_SPECS
|
|
949
|
+
},
|
|
950
|
+
'adapter_daybreak' => {
|
|
951
|
+
:build => 'Moneta::Adapters::Daybreak.new(:file => File.join(make_tempdir, "adapter_daybreak"))',
|
|
952
|
+
:specs => ADAPTER_SPECS
|
|
953
|
+
},
|
|
926
954
|
'adapter_file' => {
|
|
927
955
|
:build => 'Moneta::Adapters::File.new(:dir => File.join(make_tempdir, "adapter_file"))',
|
|
928
956
|
:specs => ADAPTER_SPECS
|
|
@@ -946,52 +974,27 @@ end
|
|
|
946
974
|
},
|
|
947
975
|
'adapter_memcached_dalli' => {
|
|
948
976
|
:build => 'Moneta::Adapters::MemcachedDalli.new(:namespace => "adapter_memcached_dalli")',
|
|
949
|
-
:specs => ADAPTER_SPECS.
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
store.store('key2', 'val2', :expires => 60)
|
|
955
|
-
store.load('key1').should == 'val1'
|
|
956
|
-
sleep 1
|
|
957
|
-
store.load('key1').should == 'val1'
|
|
958
|
-
sleep 2
|
|
959
|
-
store.load('key1').should be_nil
|
|
960
|
-
store['key2'].should == 'val2'
|
|
961
|
-
end}
|
|
977
|
+
:specs => ADAPTER_SPECS.with_native_expires
|
|
978
|
+
},
|
|
979
|
+
'adapter_memcached_dalli_with_default_expires' => {
|
|
980
|
+
:build => %{Moneta::Adapters::MemcachedDalli.new(:expires => 1)},
|
|
981
|
+
:specs => ADAPTER_SPECS.with_native_expires.with_default_expires
|
|
962
982
|
},
|
|
963
983
|
'adapter_memcached_native' => {
|
|
964
984
|
:build => 'Moneta::Adapters::MemcachedNative.new(:namespace => "adapter_memcached_native")',
|
|
965
|
-
:specs => ADAPTER_SPECS.
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
store.store('key2', 'val2', :expires => 60)
|
|
971
|
-
store.load('key1').should == 'val1'
|
|
972
|
-
sleep 1
|
|
973
|
-
store.load('key1').should == 'val1'
|
|
974
|
-
sleep 2
|
|
975
|
-
store.load('key1').should be_nil
|
|
976
|
-
store['key2'].should == 'val2'
|
|
977
|
-
end
|
|
978
|
-
}
|
|
985
|
+
:specs => ADAPTER_SPECS.with_native_expires
|
|
986
|
+
},
|
|
987
|
+
'adapter_memcached_native_with_default_expires' => {
|
|
988
|
+
:build => %{Moneta::Adapters::MemcachedNative.new(:expires => 1)},
|
|
989
|
+
:specs => ADAPTER_SPECS.with_native_expires.with_default_expires
|
|
979
990
|
},
|
|
980
991
|
'adapter_memcached' => {
|
|
981
992
|
:build => 'Moneta::Adapters::Memcached.new(:namespace => "adapter_memcached")',
|
|
982
|
-
:specs => ADAPTER_SPECS.
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
store.store('key2', 'val2', :expires => 60)
|
|
988
|
-
store.load('key1').should == 'val1'
|
|
989
|
-
sleep 1
|
|
990
|
-
store.load('key1').should == 'val1'
|
|
991
|
-
sleep 2
|
|
992
|
-
store.load('key1').should be_nil
|
|
993
|
-
store['key2'].should == 'val2'
|
|
994
|
-
end}
|
|
993
|
+
:specs => ADAPTER_SPECS.with_native_expires
|
|
994
|
+
},
|
|
995
|
+
'adapter_memcached_with_default_expires' => {
|
|
996
|
+
:build => %{Moneta::Adapters::Memcached.new(:expires => 1)},
|
|
997
|
+
:specs => ADAPTER_SPECS.with_native_expires.with_default_expires
|
|
995
998
|
},
|
|
996
999
|
'adapter_memory' => {
|
|
997
1000
|
:build => 'Moneta::Adapters::Memory.new',
|
|
@@ -1017,7 +1020,18 @@ end}
|
|
|
1017
1020
|
},
|
|
1018
1021
|
'adapter_mongo' => {
|
|
1019
1022
|
:build => 'Moneta::Adapters::Mongo.new(:db => "adapter_mongo")',
|
|
1020
|
-
:specs => ADAPTER_SPECS.
|
|
1023
|
+
:specs => ADAPTER_SPECS.with_native_expires,
|
|
1024
|
+
:tests => %{
|
|
1025
|
+
it 'automatically deletes expired document' do
|
|
1026
|
+
store.store('key', 'val', :expires => 30)
|
|
1027
|
+
store.instance_variable_get(:@collection).find_one('_id' => ::BSON::Binary.new('key')).should_not be_nil
|
|
1028
|
+
sleep 70 # Mongo needs up to 60 seconds
|
|
1029
|
+
store.instance_variable_get(:@collection).find_one('_id' => ::BSON::Binary.new('key')).should be_nil
|
|
1030
|
+
end}
|
|
1031
|
+
},
|
|
1032
|
+
'adapter_mongo_with_default_expires' => {
|
|
1033
|
+
:build => %{Moneta::Adapters::Mongo.new(:expires => 1)},
|
|
1034
|
+
:specs => ADAPTER_SPECS.with_expires.with_default_expires
|
|
1021
1035
|
},
|
|
1022
1036
|
'adapter_pstore' => {
|
|
1023
1037
|
:build => 'Moneta::Adapters::PStore.new(:file => File.join(make_tempdir, "adapter_pstore"))',
|
|
@@ -1025,19 +1039,11 @@ end}
|
|
|
1025
1039
|
},
|
|
1026
1040
|
'adapter_redis' => {
|
|
1027
1041
|
:build => 'Moneta::Adapters::Redis.new',
|
|
1028
|
-
:specs => ADAPTER_SPECS.
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
store.store('key2', 'val2', :expires => 60)
|
|
1034
|
-
store.load('key1').should == 'val1'
|
|
1035
|
-
sleep 1
|
|
1036
|
-
store.load('key1').should == 'val1'
|
|
1037
|
-
sleep 2
|
|
1038
|
-
store.load('key1').should be_nil
|
|
1039
|
-
store['key2'].should == 'val2'
|
|
1040
|
-
end}
|
|
1042
|
+
:specs => ADAPTER_SPECS.with_native_expires
|
|
1043
|
+
},
|
|
1044
|
+
'adapter_redis_with_default_expires' => {
|
|
1045
|
+
:build => %{Moneta::Adapters::Redis.new(:expires => 1)},
|
|
1046
|
+
:specs => ADAPTER_SPECS.with_native_expires.with_default_expires
|
|
1041
1047
|
},
|
|
1042
1048
|
'adapter_riak' => {
|
|
1043
1049
|
:build => 'Moneta::Adapters::Riak.new',
|
|
@@ -1330,6 +1336,20 @@ SPECS['expires'] = %{it 'supports expires on store and #[]' do
|
|
|
1330
1336
|
store['key1'].should be_nil
|
|
1331
1337
|
end
|
|
1332
1338
|
|
|
1339
|
+
it 'supports 0 as no-expires on store and #[]' do
|
|
1340
|
+
store.store('key1', 'val1', :expires => 0)
|
|
1341
|
+
store['key1'].should == 'val1'
|
|
1342
|
+
sleep 2
|
|
1343
|
+
store['key1'].should == 'val1'
|
|
1344
|
+
end
|
|
1345
|
+
|
|
1346
|
+
it 'supports false as no-expires on store and #[]' do
|
|
1347
|
+
store.store('key1', 'val1', :expires => false)
|
|
1348
|
+
store['key1'].should == 'val1'
|
|
1349
|
+
sleep 2
|
|
1350
|
+
store['key1'].should == 'val1'
|
|
1351
|
+
end
|
|
1352
|
+
|
|
1333
1353
|
it 'supports expires on store and load' do
|
|
1334
1354
|
store.store('key1', 'val1', :expires => 2)
|
|
1335
1355
|
store.load('key1').should == 'val1'
|
|
@@ -1360,6 +1380,20 @@ it 'supports updating the expiration time in load' do
|
|
|
1360
1380
|
store['key2'].should be_nil
|
|
1361
1381
|
end
|
|
1362
1382
|
|
|
1383
|
+
it 'supports 0 as no-expires in load' do
|
|
1384
|
+
store.store('key1', 'val1', :expires => 2)
|
|
1385
|
+
store.load('key1', :expires => 0).should == 'val1'
|
|
1386
|
+
sleep 2
|
|
1387
|
+
store.load('key1').should == 'val1'
|
|
1388
|
+
end
|
|
1389
|
+
|
|
1390
|
+
it 'supports false as no-expires in load' do
|
|
1391
|
+
store.store('key1', 'val1', :expires => 2)
|
|
1392
|
+
store.load('key1', :expires => false).should == 'val1'
|
|
1393
|
+
sleep 2
|
|
1394
|
+
store.load('key1').should == 'val1'
|
|
1395
|
+
end
|
|
1396
|
+
|
|
1363
1397
|
it 'supports updating the expiration time in key?' do
|
|
1364
1398
|
store.store('key2', 'val2', :expires => 2)
|
|
1365
1399
|
store['key2'].should == 'val2'
|
|
@@ -1372,6 +1406,20 @@ it 'supports updating the expiration time in key?' do
|
|
|
1372
1406
|
store['key2'].should be_nil
|
|
1373
1407
|
end
|
|
1374
1408
|
|
|
1409
|
+
it 'supports 0 as no-expires in key?' do
|
|
1410
|
+
store.store('key1', 'val1', :expires => 2)
|
|
1411
|
+
store.key?('key1', :expires => 0).should be_true
|
|
1412
|
+
sleep 2
|
|
1413
|
+
store['key1'].should == 'val1'
|
|
1414
|
+
end
|
|
1415
|
+
|
|
1416
|
+
it 'supports false as no-expires in key?' do
|
|
1417
|
+
store.store('key1', 'val1', :expires => 2)
|
|
1418
|
+
store.key?('key1', :expires => false ).should be_true
|
|
1419
|
+
sleep 2
|
|
1420
|
+
store['key1'].should == 'val1'
|
|
1421
|
+
end
|
|
1422
|
+
|
|
1375
1423
|
it 'supports updating the expiration time in fetch' do
|
|
1376
1424
|
store.store('key1', 'val1', :expires => 2)
|
|
1377
1425
|
store['key1'].should == 'val1'
|
|
@@ -1384,6 +1432,20 @@ it 'supports updating the expiration time in fetch' do
|
|
|
1384
1432
|
store['key1'].should be_nil
|
|
1385
1433
|
end
|
|
1386
1434
|
|
|
1435
|
+
it 'supports 0 as no-expires in fetch' do
|
|
1436
|
+
store.store('key1', 'val1', :expires => 2)
|
|
1437
|
+
store.fetch('key1', nil, :expires => 0).should == 'val1'
|
|
1438
|
+
sleep 2
|
|
1439
|
+
store.load('key1').should == 'val1'
|
|
1440
|
+
end
|
|
1441
|
+
|
|
1442
|
+
it 'supports false as no-expires in fetch' do
|
|
1443
|
+
store.store('key1', 'val1', :expires => 2)
|
|
1444
|
+
store.fetch('key1', nil, :expires => false).should == 'val1'
|
|
1445
|
+
sleep 2
|
|
1446
|
+
store.load('key1').should == 'val1'
|
|
1447
|
+
end
|
|
1448
|
+
|
|
1387
1449
|
it 'respects expires in delete' do
|
|
1388
1450
|
store.store('key2', 'val2', :expires => 2)
|
|
1389
1451
|
store['key2'].should == 'val2'
|
|
@@ -1394,14 +1456,56 @@ it 'respects expires in delete' do
|
|
|
1394
1456
|
end
|
|
1395
1457
|
|
|
1396
1458
|
it 'supports the #expires syntactic sugar' do
|
|
1397
|
-
store
|
|
1459
|
+
store.store('persistent_key', 'persistent_value', :expires => 0)
|
|
1398
1460
|
store.expires(2).store('key2', 'val2')
|
|
1399
1461
|
store['key2'].should == 'val2'
|
|
1400
1462
|
sleep 1
|
|
1401
1463
|
store['key2'].should == 'val2'
|
|
1402
1464
|
sleep 2
|
|
1403
1465
|
store.delete('key2').should be_nil
|
|
1404
|
-
store['
|
|
1466
|
+
store['persistent_key'].should == 'persistent_value'
|
|
1467
|
+
end
|
|
1468
|
+
|
|
1469
|
+
it 'supports false as no-expires on store and #[]' do
|
|
1470
|
+
store.store('key1', 'val1', :expires => false)
|
|
1471
|
+
store['key1'].should == 'val1'
|
|
1472
|
+
sleep 2
|
|
1473
|
+
store['key1'].should == 'val1'
|
|
1474
|
+
end
|
|
1475
|
+
|
|
1476
|
+
it 'does not update the expiration time in key? when not asked to do so' do
|
|
1477
|
+
store.store('key1', 'val1', :expires => 1)
|
|
1478
|
+
store.key?('key1').should be_true
|
|
1479
|
+
store.key?('key1', :expires => nil).should be_true
|
|
1480
|
+
sleep 2
|
|
1481
|
+
store.key?('key1').should be_false
|
|
1482
|
+
end
|
|
1483
|
+
|
|
1484
|
+
it 'does not update the expiration time in fetch when not asked to do so' do
|
|
1485
|
+
store.store('key1', 'val1', :expires => 1)
|
|
1486
|
+
store.fetch('key1').should == 'val1'
|
|
1487
|
+
store.fetch('key1', :expires => nil).should == 'val1'
|
|
1488
|
+
sleep 2
|
|
1489
|
+
store.fetch('key1').should be_nil
|
|
1490
|
+
end
|
|
1491
|
+
|
|
1492
|
+
it 'does not update the expiration time in load when not asked to do so' do
|
|
1493
|
+
store.store('key1', 'val1', :expires => 1)
|
|
1494
|
+
store.load('key1').should == 'val1'
|
|
1495
|
+
store.load('key1', :expires => nil).should == 'val1'
|
|
1496
|
+
sleep 2
|
|
1497
|
+
store.load('key1').should be_nil
|
|
1498
|
+
end}
|
|
1499
|
+
|
|
1500
|
+
SPECS['default_expires'] = %{it 'does set default expiration time' do
|
|
1501
|
+
store['key1'] = 'val1'
|
|
1502
|
+
store.key?('key1').should be_true
|
|
1503
|
+
store.fetch('key1').should == 'val1'
|
|
1504
|
+
store.load('key1').should == 'val1'
|
|
1505
|
+
sleep 2
|
|
1506
|
+
store.key?('key1').should be_false
|
|
1507
|
+
store.fetch('key1').should be_nil
|
|
1508
|
+
store.load('key1').should be_nil
|
|
1405
1509
|
end}
|
|
1406
1510
|
|
|
1407
1511
|
SPECS['not_increment'] = %{it 'does not support #increment' do
|
|
@@ -1637,7 +1741,7 @@ SPECS.each do |key, code|
|
|
|
1637
1741
|
"shared_examples_for '#{key}' do\n " << [code].flatten.join("\n\n").gsub("\n", "\n ") << "\nend\n\n"
|
|
1638
1742
|
end
|
|
1639
1743
|
specs_code.gsub!(/\n +\n/, "\n\n")
|
|
1640
|
-
File.open(File.join(
|
|
1744
|
+
File.open(File.join(PATH, 'monetaspecs.rb'), 'w') {|out| out << specs_code }
|
|
1641
1745
|
|
|
1642
1746
|
TESTS.each do |name, options|
|
|
1643
1747
|
build = options.delete(:build)
|
|
@@ -1680,5 +1784,5 @@ end
|
|
|
1680
1784
|
}
|
|
1681
1785
|
|
|
1682
1786
|
code.gsub!(/\n +\n/, "\n\n")
|
|
1683
|
-
File.open(File.join(
|
|
1787
|
+
File.open(File.join(PATH, 'moneta', "#{name}_spec.rb"), 'w') {|out| out << code }
|
|
1684
1788
|
end
|