moneta 0.7.3 → 0.7.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (178) hide show
  1. data/.travis.yml +17 -51
  2. data/CHANGES +13 -0
  3. data/Gemfile +4 -4
  4. data/README.md +79 -40
  5. data/Rakefile +40 -25
  6. data/benchmarks/run.rb +35 -5
  7. data/lib/moneta.rb +5 -5
  8. data/lib/moneta/adapters/activerecord.rb +4 -6
  9. data/lib/moneta/adapters/cassandra.rb +8 -11
  10. data/lib/moneta/adapters/couch.rb +3 -1
  11. data/lib/moneta/adapters/daybreak.rb +28 -0
  12. data/lib/moneta/adapters/fog.rb +3 -3
  13. data/lib/moneta/adapters/hbase.rb +2 -4
  14. data/lib/moneta/adapters/memcached/dalli.rb +8 -7
  15. data/lib/moneta/adapters/memcached/native.rb +8 -9
  16. data/lib/moneta/adapters/mongo.rb +42 -11
  17. data/lib/moneta/adapters/pstore.rb +4 -6
  18. data/lib/moneta/adapters/redis.rb +17 -10
  19. data/lib/moneta/adapters/restclient.rb +19 -10
  20. data/lib/moneta/adapters/sequel.rb +4 -6
  21. data/lib/moneta/adapters/tdb.rb +22 -0
  22. data/lib/moneta/expires.rb +28 -12
  23. data/lib/moneta/mixins.rb +64 -3
  24. data/lib/moneta/pool.rb +37 -0
  25. data/lib/moneta/proxy.rb +18 -7
  26. data/lib/moneta/server.rb +1 -1
  27. data/lib/moneta/shared.rb +2 -2
  28. data/lib/moneta/transformer/helper.rb +1 -1
  29. data/lib/moneta/version.rb +1 -1
  30. data/{spec/generate.rb → script/generate-specs.rb} +195 -91
  31. data/script/install-bundle.rb +35 -0
  32. data/spec/helper.rb +6 -0
  33. data/spec/moneta/adapter_activerecord_spec.rb +1 -1
  34. data/spec/moneta/adapter_cassandra_spec.rb +1 -12
  35. data/spec/moneta/adapter_cassandra_with_default_expires_spec.rb +21 -0
  36. data/spec/moneta/adapter_client_spec.rb +1 -1
  37. data/spec/moneta/adapter_cookie_spec.rb +1 -1
  38. data/spec/moneta/adapter_couch_spec.rb +1 -1
  39. data/spec/moneta/adapter_datamapper_spec.rb +1 -1
  40. data/spec/moneta/adapter_daybreak_spec.rb +19 -0
  41. data/spec/moneta/adapter_dbm_spec.rb +1 -1
  42. data/spec/moneta/adapter_file_spec.rb +1 -1
  43. data/spec/moneta/adapter_fog_spec.rb +1 -1
  44. data/spec/moneta/adapter_gdbm_spec.rb +1 -1
  45. data/spec/moneta/adapter_hbase_spec.rb +1 -1
  46. data/spec/moneta/adapter_leveldb_spec.rb +1 -1
  47. data/spec/moneta/adapter_localmemcache_spec.rb +1 -1
  48. data/spec/moneta/adapter_lruhash_spec.rb +1 -1
  49. data/spec/moneta/adapter_memcached_dalli_spec.rb +1 -12
  50. data/spec/moneta/adapter_memcached_dalli_with_default_expires_spec.rb +21 -0
  51. data/spec/moneta/adapter_memcached_native_spec.rb +1 -13
  52. data/spec/moneta/adapter_memcached_native_with_default_expires_spec.rb +21 -0
  53. data/spec/moneta/adapter_memcached_spec.rb +1 -12
  54. data/spec/moneta/adapter_memcached_with_default_expires_spec.rb +21 -0
  55. data/spec/moneta/adapter_memory_spec.rb +1 -1
  56. data/spec/moneta/adapter_mongo_spec.rb +9 -2
  57. data/spec/moneta/adapter_mongo_with_default_expires_spec.rb +21 -0
  58. data/spec/moneta/adapter_pstore_spec.rb +1 -1
  59. data/spec/moneta/adapter_redis_spec.rb +1 -12
  60. data/spec/moneta/adapter_redis_with_default_expires_spec.rb +21 -0
  61. data/spec/moneta/adapter_restclient_spec.rb +1 -1
  62. data/spec/moneta/adapter_riak_spec.rb +1 -1
  63. data/spec/moneta/adapter_sdbm_spec.rb +1 -1
  64. data/spec/moneta/adapter_sequel_spec.rb +1 -1
  65. data/spec/moneta/adapter_sqlite_spec.rb +1 -1
  66. data/spec/moneta/adapter_tdb_spec.rb +19 -0
  67. data/spec/moneta/adapter_tokyocabinet_bdb_spec.rb +1 -1
  68. data/spec/moneta/adapter_tokyocabinet_hdb_spec.rb +1 -1
  69. data/spec/moneta/adapter_yaml_spec.rb +1 -1
  70. data/spec/moneta/cache_file_memory_spec.rb +1 -1
  71. data/spec/moneta/cache_memory_null_spec.rb +1 -1
  72. data/spec/moneta/expires_file_spec.rb +1 -1
  73. data/spec/moneta/expires_memory_spec.rb +1 -12
  74. data/spec/moneta/expires_memory_with_default_expires_spec.rb +111 -0
  75. data/spec/moneta/lock_spec.rb +1 -1
  76. data/spec/moneta/null_adapter_spec.rb +1 -1
  77. data/spec/moneta/optionmerger_spec.rb +1 -1
  78. data/spec/moneta/pool_spec.rb +23 -0
  79. data/spec/moneta/proxy_expires_memory_spec.rb +1 -1
  80. data/spec/moneta/proxy_redis_spec.rb +1 -1
  81. data/spec/moneta/shared_spec.rb +1 -1
  82. data/spec/moneta/simple_activerecord_spec.rb +1 -1
  83. data/spec/moneta/simple_activerecord_with_expires_spec.rb +1 -1
  84. data/spec/moneta/simple_cassandra_spec.rb +1 -1
  85. data/spec/moneta/simple_client_tcp_spec.rb +1 -1
  86. data/spec/moneta/simple_client_unix_spec.rb +1 -1
  87. data/spec/moneta/simple_couch_spec.rb +1 -1
  88. data/spec/moneta/simple_couch_with_expires_spec.rb +1 -1
  89. data/spec/moneta/simple_datamapper_spec.rb +1 -1
  90. data/spec/moneta/simple_datamapper_with_expires_spec.rb +1 -1
  91. data/spec/moneta/simple_datamapper_with_repository_spec.rb +1 -1
  92. data/spec/moneta/simple_daybreak_spec.rb +144 -0
  93. data/spec/moneta/simple_daybreak_with_expires_spec.rb +145 -0
  94. data/spec/moneta/simple_dbm_spec.rb +1 -1
  95. data/spec/moneta/simple_dbm_with_expires_spec.rb +1 -1
  96. data/spec/moneta/simple_file_spec.rb +1 -1
  97. data/spec/moneta/simple_file_with_expires_spec.rb +1 -1
  98. data/spec/moneta/simple_fog_spec.rb +1 -1
  99. data/spec/moneta/simple_fog_with_expires_spec.rb +1 -1
  100. data/spec/moneta/simple_gdbm_spec.rb +1 -1
  101. data/spec/moneta/simple_gdbm_with_expires_spec.rb +1 -1
  102. data/spec/moneta/simple_hashfile_spec.rb +1 -1
  103. data/spec/moneta/simple_hashfile_with_expires_spec.rb +1 -1
  104. data/spec/moneta/simple_hbase_spec.rb +1 -1
  105. data/spec/moneta/simple_hbase_with_expires_spec.rb +1 -1
  106. data/spec/moneta/simple_leveldb_spec.rb +1 -1
  107. data/spec/moneta/simple_leveldb_with_expires_spec.rb +1 -1
  108. data/spec/moneta/simple_localmemcache_spec.rb +1 -1
  109. data/spec/moneta/simple_localmemcache_with_expires_spec.rb +1 -1
  110. data/spec/moneta/simple_lruhash_spec.rb +1 -1
  111. data/spec/moneta/simple_lruhash_with_expires_spec.rb +1 -1
  112. data/spec/moneta/simple_memcached_dalli_spec.rb +1 -1
  113. data/spec/moneta/simple_memcached_native_spec.rb +1 -1
  114. data/spec/moneta/simple_memcached_spec.rb +1 -1
  115. data/spec/moneta/simple_memory_spec.rb +1 -1
  116. data/spec/moneta/simple_memory_with_compress_spec.rb +1 -1
  117. data/spec/moneta/simple_memory_with_expires_spec.rb +1 -1
  118. data/spec/moneta/simple_memory_with_json_key_serializer_spec.rb +1 -1
  119. data/spec/moneta/simple_memory_with_json_serializer_spec.rb +1 -1
  120. data/spec/moneta/simple_memory_with_json_value_serializer_spec.rb +1 -1
  121. data/spec/moneta/simple_memory_with_prefix_spec.rb +1 -1
  122. data/spec/moneta/simple_memory_with_snappy_compress_spec.rb +1 -1
  123. data/spec/moneta/simple_mongo_spec.rb +3 -2
  124. data/spec/moneta/simple_null_spec.rb +1 -1
  125. data/spec/moneta/simple_pstore_spec.rb +1 -1
  126. data/spec/moneta/simple_pstore_with_expires_spec.rb +1 -1
  127. data/spec/moneta/simple_redis_spec.rb +1 -1
  128. data/spec/moneta/simple_restclient_spec.rb +1 -1
  129. data/spec/moneta/simple_riak_spec.rb +1 -1
  130. data/spec/moneta/simple_riak_with_expires_spec.rb +1 -1
  131. data/spec/moneta/simple_sdbm_spec.rb +1 -1
  132. data/spec/moneta/simple_sdbm_with_expires_spec.rb +1 -1
  133. data/spec/moneta/simple_sequel_spec.rb +1 -1
  134. data/spec/moneta/simple_sequel_with_expires_spec.rb +1 -1
  135. data/spec/moneta/simple_sqlite_spec.rb +1 -1
  136. data/spec/moneta/simple_sqlite_with_expires_spec.rb +1 -1
  137. data/spec/moneta/simple_tdb_spec.rb +144 -0
  138. data/spec/moneta/{simple_mongo_with_expires_spec.rb → simple_tdb_with_expires_spec.rb} +4 -4
  139. data/spec/moneta/simple_tokyocabinet_spec.rb +1 -1
  140. data/spec/moneta/simple_tokyocabinet_with_expires_spec.rb +1 -1
  141. data/spec/moneta/simple_yaml_spec.rb +1 -1
  142. data/spec/moneta/simple_yaml_with_expires_spec.rb +1 -1
  143. data/spec/moneta/stack_file_memory_spec.rb +1 -1
  144. data/spec/moneta/stack_memory_file_spec.rb +1 -1
  145. data/spec/moneta/transformer_bencode_spec.rb +1 -1
  146. data/spec/moneta/transformer_bert_spec.rb +1 -1
  147. data/spec/moneta/transformer_bson_spec.rb +1 -1
  148. data/spec/moneta/transformer_bzip2_spec.rb +1 -1
  149. data/spec/moneta/transformer_json_spec.rb +1 -1
  150. data/spec/moneta/transformer_key_marshal_spec.rb +1 -1
  151. data/spec/moneta/transformer_key_yaml_spec.rb +1 -1
  152. data/spec/moneta/transformer_lzma_spec.rb +1 -1
  153. data/spec/moneta/transformer_lzo_spec.rb +1 -1
  154. data/spec/moneta/transformer_marshal_base64_spec.rb +1 -1
  155. data/spec/moneta/transformer_marshal_escape_spec.rb +1 -1
  156. data/spec/moneta/transformer_marshal_hmac_spec.rb +1 -1
  157. data/spec/moneta/transformer_marshal_md5_spec.rb +1 -1
  158. data/spec/moneta/transformer_marshal_md5_spread_spec.rb +1 -1
  159. data/spec/moneta/transformer_marshal_prefix_spec.rb +1 -1
  160. data/spec/moneta/transformer_marshal_rmd160_spec.rb +1 -1
  161. data/spec/moneta/transformer_marshal_sha1_spec.rb +1 -1
  162. data/spec/moneta/transformer_marshal_sha256_spec.rb +1 -1
  163. data/spec/moneta/transformer_marshal_sha384_spec.rb +1 -1
  164. data/spec/moneta/transformer_marshal_sha512_spec.rb +1 -1
  165. data/spec/moneta/transformer_marshal_spec.rb +1 -1
  166. data/spec/moneta/transformer_marshal_truncate_spec.rb +1 -1
  167. data/spec/moneta/transformer_marshal_uuencode_spec.rb +1 -1
  168. data/spec/moneta/transformer_msgpack_spec.rb +1 -1
  169. data/spec/moneta/transformer_ox_spec.rb +1 -1
  170. data/spec/moneta/transformer_quicklz_spec.rb +1 -1
  171. data/spec/moneta/transformer_snappy_spec.rb +1 -1
  172. data/spec/moneta/transformer_tnet_spec.rb +1 -1
  173. data/spec/moneta/transformer_value_marshal_spec.rb +1 -1
  174. data/spec/moneta/transformer_value_yaml_spec.rb +1 -1
  175. data/spec/moneta/transformer_yaml_spec.rb +1 -1
  176. data/spec/moneta/transformer_zlib_spec.rb +1 -1
  177. data/spec/monetaspecs.rb +105 -3
  178. metadata +35 -6
data/lib/moneta.rb CHANGED
@@ -2,6 +2,7 @@ module Moneta
2
2
  autoload :Builder, 'moneta/builder'
3
3
  autoload :Cache, 'moneta/cache'
4
4
  autoload :Defaults, 'moneta/mixins'
5
+ autoload :ExpiresSupport, 'moneta/mixins'
5
6
  autoload :Expires, 'moneta/expires'
6
7
  autoload :HashAdapter, 'moneta/mixins'
7
8
  autoload :IncrementSupport, 'moneta/mixins'
@@ -10,6 +11,7 @@ module Moneta
10
11
  autoload :Net, 'moneta/mixins'
11
12
  autoload :OptionMerger, 'moneta/optionmerger'
12
13
  autoload :OptionSupport, 'moneta/mixins'
14
+ autoload :Pool, 'moneta/pool'
13
15
  autoload :Proxy, 'moneta/proxy'
14
16
  autoload :Server, 'moneta/server'
15
17
  autoload :Shared, 'moneta/shared'
@@ -23,6 +25,7 @@ module Moneta
23
25
  autoload :Client, 'moneta/adapters/client'
24
26
  autoload :Cookie, 'moneta/adapters/cookie'
25
27
  autoload :Couch, 'moneta/adapters/couch'
28
+ autoload :Daybreak, 'moneta/adapters/daybreak'
26
29
  autoload :DBM, 'moneta/adapters/dbm'
27
30
  autoload :DataMapper, 'moneta/adapters/datamapper'
28
31
  autoload :File, 'moneta/adapters/file'
@@ -45,6 +48,7 @@ module Moneta
45
48
  autoload :SDBM, 'moneta/adapters/sdbm'
46
49
  autoload :Sequel, 'moneta/adapters/sequel'
47
50
  autoload :Sqlite, 'moneta/adapters/sqlite'
51
+ autoload :TDB, 'moneta/adapters/tdb'
48
52
  autoload :TokyoCabinet, 'moneta/adapters/tokyocabinet'
49
53
  autoload :YAML, 'moneta/adapters/yaml'
50
54
  end
@@ -98,10 +102,6 @@ module Moneta
98
102
  # Riak accepts only utf-8 keys over the http interface
99
103
  # We use base64 encoding therefore.
100
104
  transformer[:key] << :base64
101
- when :Memcached, :MemcachedDalli, :MemcachedNative
102
- # Memcached supports expires already
103
- options[:expires] = expires if Integer === expires
104
- expires = false
105
105
  when :PStore, :YAML, :Null
106
106
  # For PStore and YAML only the key has to be a string
107
107
  transformer.delete(:value) if transformer[:value] == [:marshal]
@@ -112,7 +112,7 @@ module Moneta
112
112
  when :File
113
113
  # Use escaping
114
114
  transformer[:key] << :escape
115
- when :Cassandra, :Redis
115
+ when :Cassandra, :Redis, :Mongo, :Memcached, :MemcachedDalli, :MemcachedNative
116
116
  # Expires already supported
117
117
  options[:expires] = expires if Integer === expires
118
118
  expires = false
@@ -6,6 +6,7 @@ module Moneta
6
6
  # @api public
7
7
  class ActiveRecord
8
8
  include Defaults
9
+ include IncrementSupport
9
10
 
10
11
  def self.tables
11
12
  @tables ||= {}
@@ -66,13 +67,10 @@ module Moneta
66
67
  # (see Proxy#increment)
67
68
  def increment(key, amount = 1, options = {})
68
69
  record = @table.where(:k => key).lock.first_or_initialize
69
- value = record.v
70
- intvalue = value.to_i
71
- raise 'Tried to increment non integer value' unless value == nil || intvalue.to_s == value.to_s
72
- intvalue += amount
73
- record.v = intvalue.to_s
70
+ value = convert_for_increment(record.v) + amount
71
+ record.v = value.to_s
74
72
  record.save
75
- intvalue
73
+ value
76
74
  end
77
75
 
78
76
  # (see Proxy#clear)
@@ -9,6 +9,7 @@ module Moneta
9
9
  # @api public
10
10
  class Cassandra
11
11
  include Defaults
12
+ include ExpiresSupport
12
13
 
13
14
  # @param [Hash] options
14
15
  # @option options [String] :keyspace ('moneta') Cassandra keyspace
@@ -19,7 +20,7 @@ module Moneta
19
20
  def initialize(options = {})
20
21
  options[:host] ||= '127.0.0.1'
21
22
  options[:port] ||= 9160
22
- @expires = options[:expires]
23
+ self.default_expires = options[:expires]
23
24
  keyspace = (options[:keyspace] ||= 'moneta')
24
25
  @cf = (options[:column_family] || 'moneta').to_sym
25
26
  @client = ::Cassandra.new('system', "#{options[:host]}:#{options[:port]}")
@@ -35,7 +36,7 @@ module Moneta
35
36
  begin
36
37
  @client.add_keyspace(ks_def)
37
38
  rescue Exception => ex
38
- puts "Cassandra: #{ex.message}"
39
+ warn "Cassandra: #{ex.message}"
39
40
  end
40
41
  break if @client.keyspaces.include?(keyspace)
41
42
  sleep 0.1
@@ -47,9 +48,7 @@ module Moneta
47
48
  # (see Proxy#key?)
48
49
  def key?(key, options = {})
49
50
  if @client.exists?(@cf, key)
50
- if options.include?(:expires) && (value = load(key))
51
- store(key, value, options)
52
- end
51
+ load(key, options) if options.include?(:expires)
53
52
  true
54
53
  else
55
54
  false
@@ -60,17 +59,15 @@ module Moneta
60
59
  def load(key, options = {})
61
60
  value = @client.get(@cf, key)
62
61
  if value
63
- if options.include?(:expires)
64
- store(key, value['value'], options)
65
- else
66
- value['value']
67
- end
62
+ expires = expires_value(options, nil)
63
+ @client.insert(@cf, key, {'value' => value['value'] }, :ttl => expires || nil) if expires != nil
64
+ value['value']
68
65
  end
69
66
  end
70
67
 
71
68
  # (see Proxy#store)
72
69
  def store(key, value, options = {})
73
- @client.insert(@cf, key, {'value' => value}, :ttl => (options[:expires] || @expires))
70
+ @client.insert(@cf, key, {'value' => value}, :ttl => expires_value(options) || nil)
74
71
  value
75
72
  end
76
73
 
@@ -8,10 +8,12 @@ module Moneta
8
8
  include Defaults
9
9
 
10
10
  # @param [Hash] options
11
+ # @option options [String] :host ('http://127.0.0.1:5984') Couch host
11
12
  # @option options [String] :db ('moneta') Couch database
12
13
  def initialize(options = {})
13
14
  options[:db] ||= 'moneta'
14
- @db = ::CouchRest.database!(options[:db])
15
+ options[:host] ||= '127.0.0.1:5984'
16
+ @db = CouchRest.new(options[:host]).database!(options[:db])
15
17
  end
16
18
 
17
19
  # (see Proxy#key?)
@@ -0,0 +1,28 @@
1
+ require 'daybreak'
2
+
3
+ module Moneta
4
+ module Adapters
5
+ # Daybreak backend
6
+ # @api public
7
+ class Daybreak < Memory
8
+ # Disable serialization, we have `Moneta::Transformer` for that
9
+ class DB < ::Daybreak::DB
10
+ def serialize(value) value; end
11
+ def parse(value) value; end
12
+ end
13
+
14
+ # @param [Hash] options
15
+ # @option options [String] :file Database file
16
+ def initialize(options = {})
17
+ raise ArgumentError, 'Option :file is required' unless options[:file]
18
+ @hash = DB.new(options[:file])
19
+ end
20
+
21
+ # (see Proxy#close)
22
+ def close
23
+ @hash.close!
24
+ nil
25
+ end
26
+ end
27
+ end
28
+ end
@@ -1,4 +1,4 @@
1
- require 'fog'
1
+ require 'fog/storage'
2
2
 
3
3
  module Moneta
4
4
  module Adapters
@@ -13,7 +13,7 @@ module Moneta
13
13
  def initialize(options = {})
14
14
  raise ArgumentError, 'Option :dir is required' unless dir = options.delete(:dir)
15
15
  storage = ::Fog::Storage.new(options)
16
- @directory = storage.directories.create(:key => dir)
16
+ @directory = storage.directories.get(dir) || storage.directories.create(:key => dir)
17
17
  end
18
18
 
19
19
  # (see Proxy#key?)
@@ -38,7 +38,7 @@ module Moneta
38
38
 
39
39
  # (see Proxy#store)
40
40
  def store(key, value, options = {})
41
- @directory.files.create(:key => key, :body => value)
41
+ @directory.files.create(options.merge(:key => key, :body => value))
42
42
  value
43
43
  end
44
44
 
@@ -6,6 +6,7 @@ module Moneta
6
6
  # @api public
7
7
  class HBase
8
8
  include Defaults
9
+ include IncrementSupport
9
10
 
10
11
  # @param [Hash] options
11
12
  # @option options [String] :host ('127.0.0.1') Server host name
@@ -46,10 +47,7 @@ module Moneta
46
47
  def increment(key, amount = 1, options = {})
47
48
  result = @table.atomic_increment(key, @column, amount)
48
49
  # HACK: Throw error if applied to invalid value
49
- if result == 0
50
- value = load(key)
51
- raise 'Tried to increment non integer value' unless value.to_s == value.to_i.to_s
52
- end
50
+ convert_for_increment(load(key)) if result == 0
53
51
  result
54
52
  end
55
53
 
@@ -6,13 +6,14 @@ module Moneta
6
6
  # @api public
7
7
  class MemcachedDalli
8
8
  include Defaults
9
+ include ExpiresSupport
9
10
 
10
11
  # @param [Hash] options
11
12
  # @option options [String] :server ('127.0.0.1:11211') Memcached server
12
13
  # @option options [Integer] :expires Default expiration time
13
14
  # @option options Other options passed to `Dalli::Client#new`
14
15
  def initialize(options = {})
15
- options[:expires_in] = options.delete(:expires)
16
+ self.default_expires = options.delete(:expires)
16
17
  server = options.delete(:server) || '127.0.0.1:11211'
17
18
  @cache = ::Dalli::Client.new(server, options)
18
19
  end
@@ -20,16 +21,16 @@ module Moneta
20
21
  # (see Proxy#load)
21
22
  def load(key, options = {})
22
23
  value = @cache.get(key)
23
- if value && options.include?(:expires)
24
- store(key, value, options)
25
- else
24
+ if value
25
+ expires = expires_value(options, nil)
26
+ @cache.set(key, value, expires || nil, :raw => true) if expires != nil
26
27
  value
27
28
  end
28
29
  end
29
30
 
30
31
  # (see Proxy#store)
31
32
  def store(key, value, options = {})
32
- @cache.set(key, value, options[:expires], :raw => true)
33
+ @cache.set(key, value, expires_value(options) || nil, :raw => true)
33
34
  value
34
35
  end
35
36
 
@@ -45,9 +46,9 @@ module Moneta
45
46
  # FIXME: There is a Dalli bug, load(key) returns a wrong value after increment
46
47
  # therefore we set default = nil and create the counter manually
47
48
  result = if amount >= 0
48
- @cache.incr(key, amount, options[:expires], nil)
49
+ @cache.incr(key, amount, expires_value(options) || nil, nil)
49
50
  else
50
- @cache.decr(key, -amount, options[:expires], nil)
51
+ @cache.decr(key, -amount, expires_value(options) || nil, nil)
51
52
  end
52
53
  if result
53
54
  result
@@ -6,6 +6,8 @@ module Moneta
6
6
  # @api public
7
7
  class MemcachedNative
8
8
  include Defaults
9
+ include IncrementSupport
10
+ include ExpiresSupport
9
11
 
10
12
  # @param [Hash] options
11
13
  # @option options [String] :server ('127.0.0.1:11211') Memcached server
@@ -14,7 +16,7 @@ module Moneta
14
16
  # @option options Other options passed to `Memcached#new`
15
17
  def initialize(options = {})
16
18
  server = options.delete(:server) || '127.0.0.1:11211'
17
- @expires = options.delete(:expires) || 604800
19
+ self.default_expires = options.delete(:expires)
18
20
  options.merge!(:prefix_key => options.delete(:namespace)) if options[:namespace]
19
21
  # We don't want a limitation on the key charset. Therefore we use the binary protocol.
20
22
  # It is also faster.
@@ -25,9 +27,9 @@ module Moneta
25
27
  # (see Proxy#load)
26
28
  def load(key, options = {})
27
29
  value = @cache.get(key, false)
28
- if value && options.include?(:expires)
29
- store(key, value, options)
30
- else
30
+ if value
31
+ expires = expires_value(options, nil)
32
+ @cache.set(key, value, expires || 0, false) if expires != nil
31
33
  value
32
34
  end
33
35
  rescue ::Memcached::NotFound
@@ -36,7 +38,7 @@ module Moneta
36
38
  # (see Proxy#store)
37
39
  def store(key, value, options = {})
38
40
  # TTL must be Fixnum
39
- @cache.set(key, value, options[:expires] || @expires, false)
41
+ @cache.set(key, value, expires_value(options) || 0, false)
40
42
  value
41
43
  end
42
44
 
@@ -56,10 +58,7 @@ module Moneta
56
58
  @cache.decrement(key, -amount)
57
59
  end
58
60
  # HACK: Throw error if applied to invalid value
59
- if result == 0
60
- value = @cache.get(key, false) rescue nil
61
- raise 'Tried to increment non integer value' unless value.to_s == value.to_i.to_s
62
- end
61
+ convert_for_increment((@cache.get(key, false) rescue nil)) if result == 0
63
62
  result
64
63
  rescue ::Memcached::NotFound => ex
65
64
  store(key, amount.to_s, options)
@@ -3,28 +3,60 @@ require 'mongo'
3
3
  module Moneta
4
4
  module Adapters
5
5
  # MongoDB backend
6
+ #
7
+ # Supports expiration, documents will be automatically removed starting
8
+ # with mongodb >= 2.2 (see http://docs.mongodb.org/manual/tutorial/expire-data/).
9
+ #
6
10
  # @api public
7
11
  class Mongo
8
12
  include Defaults
13
+ include ExpiresSupport
9
14
 
10
15
  # @param [Hash] options
11
16
  # @option options [String] :collection ('moneta') MongoDB collection name
12
17
  # @option options [String] :host ('127.0.0.1') MongoDB server host
13
18
  # @option options [Integer] :port (MongoDB default port) MongoDB server port
14
19
  # @option options [String] :db ('moneta') MongoDB database
20
+ # @option options [Integer] :expires Default expiration time
15
21
  def initialize(options = {})
22
+ self.default_expires = options.delete(:expires)
16
23
  collection = options.delete(:collection) || 'moneta'
17
24
  host = options.delete(:host) || '127.0.0.1'
18
- port = options.delete(:port) || ::Mongo::Connection::DEFAULT_PORT
25
+ port = options.delete(:port) || ::Mongo::MongoClient::DEFAULT_PORT
19
26
  db = options.delete(:db) || 'moneta'
20
- connection = ::Mongo::Connection.new(host, port, options)
27
+ connection = ::Mongo::MongoClient.new(host, port, options)
21
28
  @collection = connection.db(db).collection(collection)
29
+ if connection.server_version >= '2.2'
30
+ @collection.ensure_index([['expiresAt', ::Mongo::ASCENDING]], :expireAfterSeconds => 0)
31
+ else
32
+ warn 'You are using MongoDB version < 2.2, expired documents will not be deleted'
33
+ end
22
34
  end
23
35
 
24
36
  # (see Proxy#load)
25
37
  def load(key, options = {})
26
- value = @collection.find_one('_id' => ::BSON::Binary.new(key))
27
- value && value['value'].to_s
38
+ key = ::BSON::Binary.new(key)
39
+ doc = @collection.find_one('_id' => key)
40
+ if doc && (!doc['expiresAt'] || doc['expiresAt'] >= Time.now)
41
+ expires = expires_at(options, nil)
42
+ @collection.update({ '_id' => key },
43
+ # expiresAt must be a Time object (BSON date datatype)
44
+ { '$set' => { 'expiresAt' => expires || nil } }) if expires != nil
45
+ doc['value'].to_s
46
+ end
47
+ end
48
+
49
+ # (see Proxy#store)
50
+ def store(key, value, options = {})
51
+ key = ::BSON::Binary.new(key)
52
+ intvalue = value.to_i
53
+ @collection.update({ '_id' => key },
54
+ { '_id' => key,
55
+ 'value' => intvalue.to_s == value ? intvalue : ::BSON::Binary.new(value),
56
+ # expiresAt must be a Time object (BSON date datatype)
57
+ 'expiresAt' => expires_at(options) || nil },
58
+ { :upsert => true })
59
+ value
28
60
  end
29
61
 
30
62
  # (see Proxy#delete)
@@ -34,13 +66,12 @@ module Moneta
34
66
  value
35
67
  end
36
68
 
37
- # (see Proxy#store)
38
- def store(key, value, options = {})
39
- key = ::BSON::Binary.new(key)
40
- @collection.update({ '_id' => key },
41
- { '_id' => key, 'value' => ::BSON::Binary.new(value) },
42
- { :upsert => true })
43
- value
69
+ # (see Proxy#increment)
70
+ def increment(key, amount = 1, options = {})
71
+ @collection.find_and_modify(:query => { '_id' => ::BSON::Binary.new(key) },
72
+ :update => { '$inc' => { 'value' => amount } },
73
+ :new => true,
74
+ :upsert => true)['value']
44
75
  end
45
76
 
46
77
  # (see Proxy#clear)
@@ -6,6 +6,7 @@ module Moneta
6
6
  # @api public
7
7
  class PStore
8
8
  include Defaults
9
+ include IncrementSupport
9
10
 
10
11
  # @param [Hash] options
11
12
  # @option options [String] :file PStore file
@@ -38,12 +39,9 @@ module Moneta
38
39
  # (see Proxy#increment)
39
40
  def increment(key, amount = 1, options = {})
40
41
  @pstore.transaction do
41
- value = @pstore[key]
42
- intvalue = value.to_i
43
- raise 'Tried to increment non integer value' unless value == nil || intvalue.to_s == value.to_s
44
- intvalue += amount
45
- @pstore[key] = intvalue.to_s
46
- intvalue
42
+ value = convert_for_increment(@pstore[key]) + amount
43
+ @pstore[key] = value.to_s
44
+ value
47
45
  end
48
46
  end
49
47
 
@@ -6,21 +6,20 @@ module Moneta
6
6
  # @api public
7
7
  class Redis
8
8
  include Defaults
9
+ include ExpiresSupport
9
10
 
10
11
  # @param [Hash] options
11
12
  # @option options [Integer] :expires Default expiration time
12
13
  # @option options Other options passed to `Redis#new`
13
14
  def initialize(options = {})
14
- @expires = options.delete(:expires)
15
+ self.default_expires = options.delete(:expires)
15
16
  @redis = ::Redis.new(options)
16
17
  end
17
18
 
18
19
  # (see Proxy#key?)
19
20
  def key?(key, options = {})
20
21
  if @redis.exists(key)
21
- if expires = options[:expires]
22
- @redis.expire(key, expires)
23
- end
22
+ update_expires(key, options, nil)
24
23
  true
25
24
  else
26
25
  false
@@ -30,15 +29,13 @@ module Moneta
30
29
  # (see Proxy#load)
31
30
  def load(key, options = {})
32
31
  value = @redis.get(key)
33
- if value && (expires = options[:expires])
34
- @redis.expire(key, expires)
35
- end
32
+ update_expires(key, options, nil)
36
33
  value
37
34
  end
38
35
 
39
36
  # (see Proxy#store)
40
37
  def store(key, value, options = {})
41
- if expires = (options[:expires] || @expires)
38
+ if expires = expires_value(options)
42
39
  @redis.setex(key, expires, value)
43
40
  else
44
41
  @redis.set(key, value)
@@ -57,8 +54,7 @@ module Moneta
57
54
  # (see Proxy#increment)
58
55
  def increment(key, amount = 1, options = {})
59
56
  value = @redis.incrby(key, amount)
60
- expires = (options[:expires] || @expires)
61
- @redis.expire(key, expires) if expires
57
+ update_expires(key, options)
62
58
  value
63
59
  end
64
60
 
@@ -67,6 +63,17 @@ module Moneta
67
63
  @redis.flushdb
68
64
  self
69
65
  end
66
+
67
+ protected
68
+
69
+ def update_expires(key, options, default = @default_expires)
70
+ case expires = expires_value(options, default)
71
+ when false
72
+ @redis.persist(key)
73
+ when Numeric
74
+ @redis.expire(key, expires)
75
+ end
76
+ end
70
77
  end
71
78
  end
72
79
  end