moneta 0.7.6 → 0.7.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (200) hide show
  1. data/CHANGES +15 -0
  2. data/README.md +160 -50
  3. data/Rakefile +11 -2
  4. data/SPEC.md +7 -2
  5. data/lib/moneta.rb +7 -1
  6. data/lib/moneta/adapters/activerecord.rb +27 -3
  7. data/lib/moneta/adapters/cassandra.rb +1 -1
  8. data/lib/moneta/adapters/client.rb +8 -2
  9. data/lib/moneta/adapters/cookie.rb +1 -1
  10. data/lib/moneta/adapters/couch.rb +2 -1
  11. data/lib/moneta/adapters/datamapper.rb +16 -0
  12. data/lib/moneta/adapters/daybreak.rb +19 -1
  13. data/lib/moneta/adapters/file.rb +12 -0
  14. data/lib/moneta/adapters/hbase.rb +1 -2
  15. data/lib/moneta/adapters/lruhash.rb +4 -1
  16. data/lib/moneta/adapters/memcached.rb +7 -3
  17. data/lib/moneta/adapters/memcached/dalli.rb +8 -2
  18. data/lib/moneta/adapters/memcached/native.rb +10 -3
  19. data/lib/moneta/adapters/memory.rb +1 -0
  20. data/lib/moneta/adapters/mongo.rb +32 -5
  21. data/lib/moneta/adapters/pstore.rb +13 -2
  22. data/lib/moneta/adapters/redis.rb +19 -0
  23. data/lib/moneta/adapters/restclient.rb +1 -1
  24. data/lib/moneta/adapters/sequel.rb +20 -6
  25. data/lib/moneta/adapters/sqlite.rb +13 -1
  26. data/lib/moneta/adapters/tokyocabinet.rb +5 -0
  27. data/lib/moneta/cache.rb +10 -0
  28. data/lib/moneta/expires.rb +19 -22
  29. data/lib/moneta/lock.rb +2 -2
  30. data/lib/moneta/mixins.rb +33 -11
  31. data/lib/moneta/optionmerger.rb +1 -1
  32. data/lib/moneta/proxy.rb +13 -8
  33. data/lib/moneta/server.rb +13 -6
  34. data/lib/moneta/shared.rb +6 -10
  35. data/lib/moneta/synchronize.rb +125 -0
  36. data/lib/moneta/transformer.rb +50 -42
  37. data/lib/moneta/transformer/config.rb +34 -32
  38. data/lib/moneta/utils.rb +20 -0
  39. data/lib/moneta/version.rb +1 -1
  40. data/lib/moneta/weak.rb +17 -0
  41. data/lib/moneta/wrapper.rb +5 -0
  42. data/lib/rack/moneta_cookies.rb +2 -2
  43. data/lib/rack/moneta_store.rb +4 -4
  44. data/script/benchmarks +3 -9
  45. data/script/generate-specs +278 -41
  46. data/script/install-bundle +2 -2
  47. data/spec/moneta/adapter_activerecord_spec.rb +1 -0
  48. data/spec/moneta/adapter_cassandra_spec.rb +1 -0
  49. data/spec/moneta/adapter_cassandra_with_default_expires_spec.rb +1 -0
  50. data/spec/moneta/adapter_client_spec.rb +1 -0
  51. data/spec/moneta/adapter_cookie_spec.rb +1 -0
  52. data/spec/moneta/adapter_couch_spec.rb +1 -0
  53. data/spec/moneta/adapter_datamapper_spec.rb +1 -0
  54. data/spec/moneta/adapter_daybreak_spec.rb +1 -0
  55. data/spec/moneta/adapter_dbm_spec.rb +1 -0
  56. data/spec/moneta/adapter_file_spec.rb +1 -0
  57. data/spec/moneta/adapter_fog_spec.rb +1 -0
  58. data/spec/moneta/adapter_gdbm_spec.rb +1 -1
  59. data/spec/moneta/adapter_hbase_spec.rb +1 -0
  60. data/spec/moneta/adapter_leveldb_spec.rb +1 -0
  61. data/spec/moneta/adapter_localmemcache_spec.rb +1 -0
  62. data/spec/moneta/adapter_lruhash_spec.rb +1 -0
  63. data/spec/moneta/adapter_memcached_dalli_spec.rb +2 -0
  64. data/spec/moneta/adapter_memcached_dalli_with_default_expires_spec.rb +2 -0
  65. data/spec/moneta/adapter_memcached_native_spec.rb +2 -0
  66. data/spec/moneta/adapter_memcached_native_with_default_expires_spec.rb +2 -0
  67. data/spec/moneta/adapter_memcached_spec.rb +2 -0
  68. data/spec/moneta/adapter_memcached_with_default_expires_spec.rb +2 -0
  69. data/spec/moneta/adapter_memory_spec.rb +1 -0
  70. data/spec/moneta/adapter_mongo_spec.rb +2 -0
  71. data/spec/moneta/adapter_mongo_with_default_expires_spec.rb +2 -0
  72. data/spec/moneta/adapter_pstore_spec.rb +1 -0
  73. data/spec/moneta/adapter_redis_spec.rb +2 -0
  74. data/spec/moneta/adapter_redis_with_default_expires_spec.rb +2 -0
  75. data/spec/moneta/adapter_restclient_spec.rb +1 -0
  76. data/spec/moneta/adapter_riak_spec.rb +1 -0
  77. data/spec/moneta/adapter_sdbm_spec.rb +1 -0
  78. data/spec/moneta/adapter_sequel_spec.rb +1 -0
  79. data/spec/moneta/adapter_sqlite_spec.rb +1 -0
  80. data/spec/moneta/adapter_tdb_spec.rb +1 -0
  81. data/spec/moneta/adapter_tokyocabinet_bdb_spec.rb +1 -0
  82. data/spec/moneta/adapter_tokyocabinet_hdb_spec.rb +1 -0
  83. data/spec/moneta/adapter_yaml_spec.rb +1 -0
  84. data/spec/moneta/cache_file_memory_spec.rb +1 -0
  85. data/spec/moneta/cache_memory_null_spec.rb +1 -0
  86. data/spec/moneta/expires_file_spec.rb +3 -1
  87. data/spec/moneta/expires_memory_spec.rb +2 -0
  88. data/spec/moneta/expires_memory_with_default_expires_spec.rb +2 -0
  89. data/spec/moneta/lock_spec.rb +1 -0
  90. data/spec/moneta/mutex_spec.rb +71 -0
  91. data/spec/moneta/null_adapter_spec.rb +1 -0
  92. data/spec/moneta/optionmerger_spec.rb +5 -7
  93. data/spec/moneta/pool_spec.rb +1 -0
  94. data/spec/moneta/proxy_expires_memory_spec.rb +2 -0
  95. data/spec/moneta/proxy_redis_spec.rb +2 -0
  96. data/spec/moneta/semaphore_spec.rb +84 -0
  97. data/spec/moneta/{shared_spec.rb → shared_tcp_spec.rb} +4 -3
  98. data/spec/moneta/shared_unix_spec.rb +37 -0
  99. data/spec/moneta/simple_activerecord_spec.rb +1 -0
  100. data/spec/moneta/simple_activerecord_with_expires_spec.rb +3 -1
  101. data/spec/moneta/simple_cassandra_spec.rb +1 -0
  102. data/spec/moneta/simple_client_tcp_spec.rb +1 -0
  103. data/spec/moneta/simple_client_unix_spec.rb +3 -2
  104. data/spec/moneta/simple_couch_spec.rb +1 -0
  105. data/spec/moneta/simple_couch_with_expires_spec.rb +2 -1
  106. data/spec/moneta/simple_datamapper_spec.rb +1 -0
  107. data/spec/moneta/simple_datamapper_with_expires_spec.rb +3 -1
  108. data/spec/moneta/simple_datamapper_with_repository_spec.rb +1 -0
  109. data/spec/moneta/simple_daybreak_spec.rb +1 -0
  110. data/spec/moneta/simple_daybreak_with_expires_spec.rb +3 -1
  111. data/spec/moneta/simple_dbm_spec.rb +1 -0
  112. data/spec/moneta/simple_dbm_with_expires_spec.rb +3 -1
  113. data/spec/moneta/simple_file_spec.rb +1 -0
  114. data/spec/moneta/simple_file_with_expires_spec.rb +3 -1
  115. data/spec/moneta/simple_fog_spec.rb +1 -0
  116. data/spec/moneta/simple_fog_with_expires_spec.rb +2 -1
  117. data/spec/moneta/simple_gdbm_spec.rb +1 -0
  118. data/spec/moneta/simple_gdbm_with_expires_spec.rb +3 -1
  119. data/spec/moneta/simple_hashfile_spec.rb +1 -0
  120. data/spec/moneta/simple_hashfile_with_expires_spec.rb +3 -1
  121. data/spec/moneta/simple_hbase_spec.rb +1 -0
  122. data/spec/moneta/simple_hbase_with_expires_spec.rb +3 -1
  123. data/spec/moneta/simple_leveldb_spec.rb +1 -0
  124. data/spec/moneta/simple_leveldb_with_expires_spec.rb +3 -1
  125. data/spec/moneta/simple_localmemcache_spec.rb +1 -0
  126. data/spec/moneta/simple_localmemcache_with_expires_spec.rb +2 -1
  127. data/spec/moneta/simple_lruhash_spec.rb +1 -0
  128. data/spec/moneta/simple_lruhash_with_expires_spec.rb +3 -1
  129. data/spec/moneta/simple_memcached_dalli_spec.rb +2 -0
  130. data/spec/moneta/simple_memcached_native_spec.rb +2 -0
  131. data/spec/moneta/simple_memcached_spec.rb +2 -0
  132. data/spec/moneta/simple_memory_spec.rb +1 -0
  133. data/spec/moneta/simple_memory_with_compress_spec.rb +1 -0
  134. data/spec/moneta/simple_memory_with_expires_spec.rb +3 -1
  135. data/spec/moneta/simple_memory_with_json_key_serializer_spec.rb +1 -0
  136. data/spec/moneta/simple_memory_with_json_serializer_spec.rb +1 -0
  137. data/spec/moneta/simple_memory_with_json_value_serializer_spec.rb +1 -0
  138. data/spec/moneta/simple_memory_with_prefix_spec.rb +1 -0
  139. data/spec/moneta/simple_memory_with_snappy_compress_spec.rb +1 -0
  140. data/spec/moneta/simple_mongo_spec.rb +2 -0
  141. data/spec/moneta/simple_null_spec.rb +1 -0
  142. data/spec/moneta/simple_pstore_spec.rb +1 -0
  143. data/spec/moneta/simple_pstore_with_expires_spec.rb +3 -1
  144. data/spec/moneta/simple_redis_spec.rb +2 -0
  145. data/spec/moneta/simple_restclient_spec.rb +1 -0
  146. data/spec/moneta/simple_riak_spec.rb +1 -0
  147. data/spec/moneta/simple_riak_with_expires_spec.rb +2 -1
  148. data/spec/moneta/simple_sdbm_spec.rb +1 -0
  149. data/spec/moneta/simple_sdbm_with_expires_spec.rb +3 -1
  150. data/spec/moneta/simple_sequel_spec.rb +1 -0
  151. data/spec/moneta/simple_sequel_with_expires_spec.rb +3 -1
  152. data/spec/moneta/simple_sqlite_spec.rb +1 -0
  153. data/spec/moneta/simple_sqlite_with_expires_spec.rb +3 -1
  154. data/spec/moneta/simple_tdb_spec.rb +1 -0
  155. data/spec/moneta/simple_tdb_with_expires_spec.rb +3 -1
  156. data/spec/moneta/simple_tokyocabinet_spec.rb +1 -0
  157. data/spec/moneta/simple_tokyocabinet_with_expires_spec.rb +3 -1
  158. data/spec/moneta/simple_yaml_spec.rb +1 -0
  159. data/spec/moneta/simple_yaml_with_expires_spec.rb +3 -1
  160. data/spec/moneta/stack_file_memory_spec.rb +1 -0
  161. data/spec/moneta/stack_memory_file_spec.rb +1 -0
  162. data/spec/moneta/transformer_bencode_spec.rb +1 -0
  163. data/spec/moneta/transformer_bert_spec.rb +1 -0
  164. data/spec/moneta/transformer_bson_spec.rb +1 -0
  165. data/spec/moneta/transformer_bzip2_spec.rb +1 -0
  166. data/spec/moneta/transformer_json_spec.rb +1 -0
  167. data/spec/moneta/transformer_key_inspect_spec.rb +73 -0
  168. data/spec/moneta/transformer_key_marshal_spec.rb +1 -0
  169. data/spec/moneta/transformer_key_to_s_spec.rb +1 -0
  170. data/spec/moneta/transformer_key_yaml_spec.rb +1 -0
  171. data/spec/moneta/transformer_lzma_spec.rb +1 -0
  172. data/spec/moneta/transformer_lzo_spec.rb +1 -0
  173. data/spec/moneta/transformer_marshal_base64_spec.rb +1 -0
  174. data/spec/moneta/transformer_marshal_escape_spec.rb +1 -0
  175. data/spec/moneta/transformer_marshal_hmac_spec.rb +1 -0
  176. data/spec/moneta/transformer_marshal_md5_spec.rb +1 -0
  177. data/spec/moneta/transformer_marshal_md5_spread_spec.rb +1 -0
  178. data/spec/moneta/transformer_marshal_prefix_spec.rb +1 -0
  179. data/spec/moneta/transformer_marshal_rmd160_spec.rb +1 -0
  180. data/spec/moneta/transformer_marshal_sha1_spec.rb +1 -0
  181. data/spec/moneta/transformer_marshal_sha256_spec.rb +1 -0
  182. data/spec/moneta/transformer_marshal_sha384_spec.rb +1 -0
  183. data/spec/moneta/transformer_marshal_sha512_spec.rb +1 -0
  184. data/spec/moneta/transformer_marshal_spec.rb +1 -0
  185. data/spec/moneta/transformer_marshal_truncate_spec.rb +1 -0
  186. data/spec/moneta/transformer_marshal_uuencode_spec.rb +1 -0
  187. data/spec/moneta/transformer_msgpack_spec.rb +1 -0
  188. data/spec/moneta/transformer_ox_spec.rb +1 -0
  189. data/spec/moneta/transformer_quicklz_spec.rb +1 -0
  190. data/spec/moneta/transformer_snappy_spec.rb +1 -0
  191. data/spec/moneta/transformer_tnet_spec.rb +1 -0
  192. data/spec/moneta/transformer_value_marshal_spec.rb +1 -0
  193. data/spec/moneta/transformer_value_yaml_spec.rb +1 -0
  194. data/spec/moneta/transformer_yaml_spec.rb +1 -0
  195. data/spec/moneta/transformer_zlib_spec.rb +1 -0
  196. data/spec/moneta/weak_create_spec.rb +114 -0
  197. data/spec/moneta/weak_increment_spec.rb +114 -0
  198. data/spec/monetaspecs.rb +75 -2
  199. data/spec/rack/moneta_cookies_spec.rb +1 -1
  200. metadata +20 -4
@@ -36,7 +36,7 @@ module Moneta
36
36
  begin
37
37
  @client.add_keyspace(ks_def)
38
38
  rescue Exception => ex
39
- warn "Cassandra: #{ex.message}"
39
+ warn "Moneta::Adapters::Cassandra - #{ex.message}"
40
40
  end
41
41
  break if @client.keyspaces.include?(keyspace)
42
42
  sleep 0.1
@@ -11,9 +11,9 @@ module Moneta
11
11
  # @param [Hash] options
12
12
  # @option options [Integer] :port (9000) TCP port
13
13
  # @option options [String] :host ('127.0.0.1') Hostname
14
- # @option options [String] :file Unix socket file name as alternative to `:port` and `:host`
14
+ # @option options [String] :socket Unix socket file name as alternative to `:port` and `:host`
15
15
  def initialize(options = {})
16
- @socket = options[:file] ? UNIXSocket.open(options[:file]) :
16
+ @socket = options[:socket] ? UNIXSocket.open(options[:socket]) :
17
17
  TCPSocket.open(options[:host] || '127.0.0.1', options[:port] || DEFAULT_PORT)
18
18
  end
19
19
 
@@ -48,6 +48,12 @@ module Moneta
48
48
  read_result
49
49
  end
50
50
 
51
+ # (see Proxy#create)
52
+ def create(key, value, options = {})
53
+ write(@socket, [:create, key, value, options])
54
+ read_result
55
+ end
56
+
51
57
  # (see Proxy#clear)
52
58
  def clear(options = {})
53
59
  write(@socket, [:clear, options])
@@ -1,6 +1,6 @@
1
1
  module Moneta
2
2
  module Adapters
3
- # Cookie backend used by the middleware `Rack::MonetaCookies`
3
+ # Cookie backend used by the middleware {Rack::MonetaCookies}
4
4
  # @api public
5
5
  class Cookie < Memory
6
6
  attr_reader :cookies
@@ -40,7 +40,8 @@ module Moneta
40
40
  @db.save_doc(doc)
41
41
  value
42
42
  rescue ::RestClient::RequestFailed
43
- value
43
+ tries ||= 0
44
+ (tries += 1) < 10 ? retry : raise
44
45
  end
45
46
 
46
47
  # (see Proxy#delete)
@@ -12,6 +12,7 @@ module Moneta
12
12
  include ::DataMapper::Resource
13
13
  property :k, Text, :key => true
14
14
  property :v, Text, :lazy => false
15
+ self.raise_on_save_failure = true
15
16
  end
16
17
 
17
18
  # @param [Hash] options
@@ -49,6 +50,21 @@ module Moneta
49
50
  end
50
51
  value
51
52
  end
53
+ rescue
54
+ tries ||= 0
55
+ (tries += 1) < 10 ? retry : raise
56
+ end
57
+
58
+ # (see Proxy#create)
59
+ def create(key, value, options = {})
60
+ context do
61
+ Store.create(:k => key, :v => value)
62
+ true
63
+ end
64
+ rescue
65
+ # FIXME: This catches too many errors
66
+ # it should only catch a not-unique-exception
67
+ false
52
68
  end
53
69
 
54
70
  # (see Proxy#delete)
@@ -12,9 +12,27 @@ module Moneta
12
12
  @hash = ::Daybreak::DB.new(options[:file], :serializer => ::Daybreak::Serializer::None)
13
13
  end
14
14
 
15
+ # (see Proxy#load)
16
+ def load(key, options = {})
17
+ @hash.load if options[:sync]
18
+ @hash[key]
19
+ end
20
+
21
+ # (see Proxy#store)
22
+ def store(key, value, options = {})
23
+ @hash[key] = value
24
+ @hash.flush if options[:sync]
25
+ value
26
+ end
27
+
15
28
  # (see Proxy#increment)
16
29
  def increment(key, amount = 1, options = {})
17
- @hash.lock { return super }
30
+ @hash.lock { super }
31
+ end
32
+
33
+ # (see Proxy#create)
34
+ def create(key, value, options = {})
35
+ @hash.lock { super }
18
36
  end
19
37
 
20
38
  # (see Proxy#close)
@@ -1,4 +1,5 @@
1
1
  require 'fileutils'
2
+ require 'fcntl'
2
3
 
3
4
  module Moneta
4
5
  module Adapters
@@ -65,6 +66,17 @@ module Moneta
65
66
  lock(key) { super }
66
67
  end
67
68
 
69
+ # (see Proxy#create)
70
+ def create(key, value, options = {})
71
+ path = store_path(key)
72
+ FileUtils.mkpath(::File.dirname(path))
73
+ fd = ::File.sysopen(path, Fcntl::O_WRONLY | Fcntl::O_EXCL | Fcntl::O_CREAT)
74
+ ::File.open(fd, 'wb') {|file| file.write(value) }
75
+ true
76
+ rescue Errno::EEXIST
77
+ false
78
+ end
79
+
68
80
  protected
69
81
 
70
82
  def lock(key, &block)
@@ -6,7 +6,6 @@ module Moneta
6
6
  # @api public
7
7
  class HBase
8
8
  include Defaults
9
- include IncrementSupport
10
9
 
11
10
  # @param [Hash] options
12
11
  # @option options [String] :host ('127.0.0.1') Server host name
@@ -47,7 +46,7 @@ module Moneta
47
46
  def increment(key, amount = 1, options = {})
48
47
  result = @table.atomic_increment(key, @column, amount)
49
48
  # HACK: Throw error if applied to invalid value
50
- convert_for_increment(load(key)) if result == 0
49
+ Utils.to_int(load(key)) if result == 0
51
50
  result
52
51
  end
53
52
 
@@ -8,11 +8,14 @@ module Moneta
8
8
  class LRUHash
9
9
  include Defaults
10
10
  include IncrementSupport
11
+ include CreateSupport
11
12
 
12
13
  # @param [Hash] options
13
14
  # @option options [Integer] :max_size (1024000) Maximum total byte size of hash values
15
+ # @option options [Integer] :max_count (10240) Maximum number of hash values
14
16
  def initialize(options = {})
15
17
  @max_size = options[:max_size] || 1024000
18
+ @max_count = options[:max_count] || 10240
16
19
  clear
17
20
  end
18
21
 
@@ -40,7 +43,7 @@ module Moneta
40
43
  entry.value = value
41
44
  @size += entry.value.bytesize
42
45
  entry.insert_after(@list)
43
- delete(@list.prev.key) while @list.next != @list.prev && @size > @max_size
46
+ delete(@list.prev.key) while @list.next != @list.prev && (@size > @max_size || @entry.size > @max_count)
44
47
  value
45
48
  end
46
49
 
@@ -1,11 +1,15 @@
1
1
  module Moneta
2
2
  module Adapters
3
+ # Prefer Dalli over native Memcached!
4
+ #
5
+ # I measure no performance gain over the Dalli backend
6
+ # using the Moneta backends.
3
7
  begin
4
- require 'moneta/adapters/memcached/native'
5
- Memcached = MemcachedNative
6
- rescue LoadError
7
8
  require 'moneta/adapters/memcached/dalli'
8
9
  Memcached = MemcachedDalli
10
+ rescue LoadError
11
+ require 'moneta/adapters/memcached/native'
12
+ Memcached = MemcachedNative
9
13
  end
10
14
  end
11
15
  end
@@ -53,9 +53,10 @@ module Moneta
53
53
  end
54
54
  if result
55
55
  result
56
- else
57
- store(key, amount, options)
56
+ elsif create(key, amount.to_s, options)
58
57
  amount
58
+ else
59
+ increment(key, amount, options)
59
60
  end
60
61
  end
61
62
 
@@ -65,6 +66,11 @@ module Moneta
65
66
  self
66
67
  end
67
68
 
69
+ # (see Defaults#create)
70
+ def create(key, value, options = {})
71
+ @cache.add(key, value, expires_value(options) || nil, :raw => true)
72
+ end
73
+
68
74
  # (see Proxy#close)
69
75
  def close
70
76
  @cache.close
@@ -6,7 +6,6 @@ module Moneta
6
6
  # @api public
7
7
  class MemcachedNative
8
8
  include Defaults
9
- include IncrementSupport
10
9
  include ExpiresSupport
11
10
 
12
11
  # @param [Hash] options
@@ -59,13 +58,21 @@ module Moneta
59
58
  end
60
59
  # HACK: Throw error if applied to invalid value
61
60
  # see https://github.com/evan/memcached/issues/110
62
- convert_for_increment((@cache.get(key, false) rescue nil)) if result == 0
61
+ Utils.to_int((@cache.get(key, false) rescue nil)) if result == 0
63
62
  result
64
63
  rescue ::Memcached::NotFound => ex
65
- store(key, amount.to_s, options)
64
+ retry unless create(key, amount.to_s, options)
66
65
  amount
67
66
  end
68
67
 
68
+ # (see Defaults#create)
69
+ def create(key, value, options = {})
70
+ @cache.add(key, value, expires_value(options) || 0, false)
71
+ true
72
+ rescue ::Memcached::ConnectionDataExists
73
+ false
74
+ end
75
+
69
76
  # (see Proxy#clear)
70
77
  def clear(options = {})
71
78
  @cache.flush
@@ -6,6 +6,7 @@ module Moneta
6
6
  include Defaults
7
7
  include HashAdapter
8
8
  include IncrementSupport
9
+ include CreateSupport
9
10
 
10
11
  # @param [Hash] options Options hash
11
12
  def initialize(options = {})
@@ -5,7 +5,7 @@ module Moneta
5
5
  # MongoDB backend
6
6
  #
7
7
  # Supports expiration, documents will be automatically removed starting
8
- # with mongodb >= 2.2 (see http://docs.mongodb.org/manual/tutorial/expire-data/).
8
+ # with mongodb >= 2.2 (see {http://docs.mongodb.org/manual/tutorial/expire-data/}).
9
9
  #
10
10
  # @api public
11
11
  class Mongo
@@ -15,6 +15,8 @@ module Moneta
15
15
  # @param [Hash] options
16
16
  # @option options [String] :collection ('moneta') MongoDB collection name
17
17
  # @option options [String] :host ('127.0.0.1') MongoDB server host
18
+ # @option options [String] :user Username used to authenticate
19
+ # @option options [String] :password Password used to authenticate
18
20
  # @option options [Integer] :port (MongoDB default port) MongoDB server port
19
21
  # @option options [String] :db ('moneta') MongoDB database
20
22
  # @option options [Integer] :expires Default expiration time
@@ -24,12 +26,16 @@ module Moneta
24
26
  host = options.delete(:host) || '127.0.0.1'
25
27
  port = options.delete(:port) || ::Mongo::MongoClient::DEFAULT_PORT
26
28
  db = options.delete(:db) || 'moneta'
27
- connection = ::Mongo::MongoClient.new(host, port, options)
28
- @collection = connection.db(db).collection(collection)
29
- if connection.server_version >= '2.2'
29
+ user = options.delete(:user)
30
+ password = options.delete(:password)
31
+ client = ::Mongo::MongoClient.new(host, port, options)
32
+ db = client.db(db)
33
+ db.authenticate(user, password, true) if user && password
34
+ @collection = db.collection(collection)
35
+ if client.server_version >= '2.2'
30
36
  @collection.ensure_index([['expiresAt', ::Mongo::ASCENDING]], :expireAfterSeconds => 0)
31
37
  else
32
- warn 'You are using MongoDB version < 2.2, expired documents will not be deleted'
38
+ warn 'Moneta::Adapters::Mongo - You are using MongoDB version < 2.2, expired documents will not be deleted'
33
39
  end
34
40
  end
35
41
 
@@ -74,11 +80,32 @@ module Moneta
74
80
  :upsert => true)['value']
75
81
  end
76
82
 
83
+ # (see Proxy#create)
84
+ def create(key, value, options = {})
85
+ key = ::BSON::Binary.new(key)
86
+ intvalue = value.to_i
87
+ @collection.insert('_id' => key,
88
+ 'value' => intvalue.to_s == value ? intvalue : ::BSON::Binary.new(value),
89
+ # expiresAt must be a Time object (BSON date datatype)
90
+ 'expiresAt' => expires_at(options) || nil)
91
+ true
92
+ rescue ::Mongo::OperationFailure
93
+ # FIXME: This catches too many errors
94
+ # it should only catch a not-unique-exception
95
+ false
96
+ end
97
+
77
98
  # (see Proxy#clear)
78
99
  def clear(options = {})
79
100
  @collection.remove
80
101
  self
81
102
  end
103
+
104
+ # (see Proxy#close)
105
+ def close
106
+ @collection.db.connection.close
107
+ nil
108
+ end
82
109
  end
83
110
  end
84
111
  end
@@ -6,7 +6,6 @@ module Moneta
6
6
  # @api public
7
7
  class PStore
8
8
  include Defaults
9
- include IncrementSupport
10
9
 
11
10
  # @param [Hash] options
12
11
  # @option options [String] :file PStore file
@@ -39,12 +38,24 @@ module Moneta
39
38
  # (see Proxy#increment)
40
39
  def increment(key, amount = 1, options = {})
41
40
  @pstore.transaction do
42
- value = convert_for_increment(@pstore[key]) + amount
41
+ value = Utils.to_int(@pstore[key]) + amount
43
42
  @pstore[key] = value.to_s
44
43
  value
45
44
  end
46
45
  end
47
46
 
47
+ # (see Proxy#create)
48
+ def create(key, value, options = {})
49
+ @pstore.transaction do
50
+ if @pstore.root?(key)
51
+ false
52
+ else
53
+ @pstore[key] = value
54
+ true
55
+ end
56
+ end
57
+ end
58
+
48
59
  # (see Proxy#clear)
49
60
  def clear(options = {})
50
61
  @pstore.transaction do
@@ -17,6 +17,9 @@ module Moneta
17
17
  end
18
18
 
19
19
  # (see Proxy#key?)
20
+ #
21
+ # This method considers false and 0 as "no-expire" and every positive
22
+ # number as a time to live in seconds.
20
23
  def key?(key, options = {})
21
24
  if @redis.exists(key)
22
25
  update_expires(key, options, nil)
@@ -64,6 +67,22 @@ module Moneta
64
67
  self
65
68
  end
66
69
 
70
+ # (see Defaults#create)
71
+ def create(key, value, options = {})
72
+ if @redis.setnx(key, value)
73
+ update_expires(key, options)
74
+ true
75
+ else
76
+ false
77
+ end
78
+ end
79
+
80
+ # (see Proxy#close)
81
+ def close
82
+ @redis.quit
83
+ nil
84
+ end
85
+
67
86
  protected
68
87
 
69
88
  def update_expires(key, options, default = @default_expires)
@@ -2,7 +2,7 @@ require 'net/http'
2
2
 
3
3
  module Moneta
4
4
  module Adapters
5
- # Moneta rest client backend which works together with `Rack::MonetaRest`
5
+ # Moneta rest client backend which works together with {Rack::MonetaRest}
6
6
  # @api public
7
7
  class RestClient
8
8
  include Defaults
@@ -6,7 +6,6 @@ module Moneta
6
6
  # @api public
7
7
  class Sequel
8
8
  include Defaults
9
- include IncrementSupport
10
9
 
11
10
  # @param [Hash] options
12
11
  # @option options [String] :db Sequel database
@@ -37,13 +36,28 @@ module Moneta
37
36
  # (see Proxy#store)
38
37
  def store(key, value, options = {})
39
38
  @db.transaction do
40
- if key?(key, options)
41
- @table.update(:k => key, :v => value)
42
- else
39
+ begin
43
40
  @table.insert(:k => key, :v => value)
41
+ rescue ::Sequel::DatabaseError
42
+ @table.update(:k => key, :v => value)
44
43
  end
45
- value
46
44
  end
45
+ value
46
+ rescue ::Sequel::DatabaseError
47
+ tries ||= 0
48
+ (tries += 1) < 10 ? retry : raise
49
+ end
50
+
51
+ # (see Proxy#store)
52
+ def create(key, value, options = {})
53
+ @db.transaction do
54
+ @table.insert(:k => key, :v => value)
55
+ end
56
+ true
57
+ rescue ::Sequel::DatabaseError
58
+ # FIXME: This catches too many errors
59
+ # it should only catch a not-unique-exception
60
+ false
47
61
  end
48
62
 
49
63
  # (see Proxy#increment)
@@ -51,7 +65,7 @@ module Moneta
51
65
  @db.transaction do
52
66
  locked_table = @table.for_update
53
67
  if record = locked_table[:k => key]
54
- value = convert_for_increment(record[:v]) + amount
68
+ value = Utils.to_int(record[:v]) + amount
55
69
  locked_table.update(:k => key, :v => value.to_s)
56
70
  value
57
71
  else