moneta 0.7.6 → 0.7.8

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.
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