moneta 1.4.1 → 1.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +425 -0
  3. data/CHANGES +17 -0
  4. data/CONTRIBUTORS +2 -0
  5. data/Gemfile +161 -60
  6. data/README.md +21 -17
  7. data/lib/moneta/adapter.rb +52 -0
  8. data/lib/moneta/adapters/activerecord.rb +77 -68
  9. data/lib/moneta/adapters/activesupportcache.rb +22 -31
  10. data/lib/moneta/adapters/cassandra.rb +114 -116
  11. data/lib/moneta/adapters/client.rb +17 -18
  12. data/lib/moneta/adapters/couch.rb +31 -26
  13. data/lib/moneta/adapters/datamapper.rb +9 -5
  14. data/lib/moneta/adapters/daybreak.rb +15 -21
  15. data/lib/moneta/adapters/dbm.rb +6 -12
  16. data/lib/moneta/adapters/file.rb +21 -13
  17. data/lib/moneta/adapters/fog.rb +5 -6
  18. data/lib/moneta/adapters/gdbm.rb +6 -12
  19. data/lib/moneta/adapters/hbase.rb +10 -12
  20. data/lib/moneta/adapters/kyotocabinet.rb +22 -27
  21. data/lib/moneta/adapters/leveldb.rb +14 -20
  22. data/lib/moneta/adapters/lmdb.rb +19 -22
  23. data/lib/moneta/adapters/localmemcache.rb +7 -13
  24. data/lib/moneta/adapters/lruhash.rb +20 -20
  25. data/lib/moneta/adapters/memcached/dalli.rb +25 -33
  26. data/lib/moneta/adapters/memcached/native.rb +14 -20
  27. data/lib/moneta/adapters/memory.rb +5 -7
  28. data/lib/moneta/adapters/mongo.rb +53 -52
  29. data/lib/moneta/adapters/pstore.rb +21 -27
  30. data/lib/moneta/adapters/redis.rb +42 -37
  31. data/lib/moneta/adapters/restclient.rb +17 -25
  32. data/lib/moneta/adapters/riak.rb +8 -9
  33. data/lib/moneta/adapters/sdbm.rb +6 -12
  34. data/lib/moneta/adapters/sequel/mysql.rb +8 -8
  35. data/lib/moneta/adapters/sequel/postgres.rb +17 -17
  36. data/lib/moneta/adapters/sequel/postgres_hstore.rb +47 -47
  37. data/lib/moneta/adapters/sequel/sqlite.rb +9 -9
  38. data/lib/moneta/adapters/sequel.rb +56 -65
  39. data/lib/moneta/adapters/sqlite.rb +37 -35
  40. data/lib/moneta/adapters/tdb.rb +8 -14
  41. data/lib/moneta/adapters/tokyocabinet.rb +19 -17
  42. data/lib/moneta/adapters/tokyotyrant.rb +29 -30
  43. data/lib/moneta/adapters/yaml.rb +1 -5
  44. data/lib/moneta/config.rb +101 -0
  45. data/lib/moneta/expires.rb +0 -1
  46. data/lib/moneta/expires_support.rb +3 -4
  47. data/lib/moneta/pool.rb +27 -7
  48. data/lib/moneta/proxy.rb +29 -0
  49. data/lib/moneta/server.rb +21 -14
  50. data/lib/moneta/version.rb +1 -1
  51. data/lib/moneta/wrapper.rb +5 -0
  52. data/lib/moneta.rb +2 -0
  53. data/moneta.gemspec +1 -0
  54. data/spec/active_support/cache_moneta_store_spec.rb +13 -13
  55. data/spec/features/null.rb +28 -28
  56. data/spec/features/persist.rb +3 -3
  57. data/spec/features/returndifferent.rb +4 -4
  58. data/spec/features/returnsame.rb +4 -4
  59. data/spec/features/store.rb +104 -104
  60. data/spec/helper.rb +15 -4
  61. data/spec/moneta/adapters/activerecord/adapter_activerecord_existing_connection_spec.rb +3 -1
  62. data/spec/moneta/adapters/activerecord/adapter_activerecord_spec.rb +15 -7
  63. data/spec/moneta/adapters/activerecord/standard_activerecord_spec.rb +5 -2
  64. data/spec/moneta/adapters/activerecord/standard_activerecord_with_expires_spec.rb +5 -2
  65. data/spec/moneta/adapters/activesupportcache/adapter_activesupportcache_spec.rb +3 -3
  66. data/spec/moneta/adapters/activesupportcache/adapter_activesupportcache_with_default_expires_spec.rb +2 -2
  67. data/spec/moneta/adapters/cassandra/adapter_cassandra_spec.rb +1 -1
  68. data/spec/moneta/adapters/cassandra/adapter_cassandra_with_default_expires_spec.rb +1 -1
  69. data/spec/moneta/adapters/cassandra/standard_cassandra_spec.rb +1 -1
  70. data/spec/moneta/adapters/client/client_helper.rb +4 -3
  71. data/spec/moneta/adapters/datamapper/adapter_datamapper_spec.rb +25 -8
  72. data/spec/moneta/adapters/datamapper/standard_datamapper_spec.rb +2 -2
  73. data/spec/moneta/adapters/datamapper/standard_datamapper_with_expires_spec.rb +2 -2
  74. data/spec/moneta/adapters/datamapper/standard_datamapper_with_repository_spec.rb +2 -2
  75. data/spec/moneta/adapters/faraday_helper.rb +3 -2
  76. data/spec/moneta/adapters/lruhash/adapter_lruhash_spec.rb +10 -6
  77. data/spec/moneta/adapters/memcached/dalli/adapter_memcached_dalli_spec.rb +13 -3
  78. data/spec/moneta/adapters/memcached/native/adapter_memcached_native_spec.rb +13 -3
  79. data/spec/moneta/adapters/mongo/adapter_mongo_spec.rb +2 -2
  80. data/spec/moneta/adapters/mongo/adapter_mongo_with_default_expires_spec.rb +1 -1
  81. data/spec/moneta/adapters/redis/adapter_redis_spec.rb +13 -3
  82. data/spec/moneta/adapters/redis/standard_redis_spec.rb +8 -1
  83. data/spec/moneta/adapters/sequel/adapter_sequel_spec.rb +4 -4
  84. data/spec/moneta/adapters/sequel/helper.rb +10 -5
  85. data/spec/moneta/adapters/sequel/standard_sequel_spec.rb +1 -1
  86. data/spec/moneta/adapters/sequel/standard_sequel_with_expires_spec.rb +1 -1
  87. data/spec/moneta/adapters/sqlite/adapter_sqlite_spec.rb +1 -1
  88. data/spec/moneta/adapters/sqlite/standard_sqlite_spec.rb +1 -1
  89. data/spec/moneta/adapters/sqlite/standard_sqlite_with_expires_spec.rb +1 -1
  90. data/spec/moneta/config_spec.rb +219 -0
  91. data/spec/moneta/proxies/enumerable/enumerable_spec.rb +2 -2
  92. data/spec/moneta/proxies/pool/pool_spec.rb +31 -3
  93. data/spec/moneta/proxies/transformer/transformer_bson_spec.rb +3 -1
  94. data/spec/moneta/proxies/transformer/transformer_marshal_escape_spec.rb +2 -0
  95. data/spec/rack/session_moneta_spec.rb +44 -25
  96. data/spec/restserver.rb +3 -14
  97. metadata +25 -15
  98. data/.travis.yml +0 -146
  99. data/spec/moneta/adapters/memcached/dalli/adapter_memcached_dalli_with_default_expires_spec.rb +0 -15
  100. data/spec/moneta/adapters/memcached/native/adapter_memcached_native_with_default_expires_spec.rb +0 -15
  101. data/spec/moneta/adapters/redis/adapter_redis_with_default_expires_spec.rb +0 -10
  102. data/spec/moneta/proxies/proxy/proxy_redis_spec.rb +0 -13
@@ -5,28 +5,25 @@ module Moneta
5
5
  module Adapters
6
6
  # LMDB backend
7
7
  # @api public
8
- class LMDB
9
- include Defaults
10
-
8
+ class LMDB < Adapter
11
9
  supports :create, :increment, :each_key
12
- attr_reader :backend, :db
13
10
 
14
11
  PUT_FLAGS = %i[nooverwrite nodupdata current append appenddup].freeze
15
12
 
13
+ config :db, default: 'moneta'
14
+
15
+ backend do |dir:, **options|
16
+ FileUtils.mkpath(dir)
17
+ ::LMDB.new(dir, options)
18
+ end
19
+
16
20
  # @param [Hash] options
17
21
  # @option options [String] :dir Environment directory
18
22
  # @option options [::LMDB::Environment] :backend Use existing backend instance
19
- # @option options [String or nil] :db Database name
20
- def initialize(options)
21
- db = options.delete(:db)
22
- @backend = options.delete(:backend) ||
23
- begin
24
- raise ArgumentError, 'Option :dir is required' unless dir = options.delete(:dir)
25
- FileUtils.mkpath(dir)
26
- ::LMDB.new(dir, options)
27
- end
28
-
29
- @db = @backend.database(db, create: true)
23
+ # @option options [String or nil] :db ('moneta') Database name
24
+ def initialize(options = {})
25
+ super
26
+ @db = backend.database(config.db, create: true)
30
27
  end
31
28
 
32
29
  # (see Proxy#key?)
@@ -47,7 +44,7 @@ module Moneta
47
44
 
48
45
  # (see Proxy#delete)
49
46
  def delete(key, options = {})
50
- @backend.transaction do
47
+ backend.transaction do
51
48
  if value = @db.get(key)
52
49
  @db.delete(key)
53
50
  value
@@ -63,7 +60,7 @@ module Moneta
63
60
 
64
61
  # (see Proxy#increment)
65
62
  def increment(key, amount = 1, options = {})
66
- @backend.transaction do
63
+ backend.transaction do
67
64
  value = Integer(@db.get(key) || 0) + amount
68
65
  @db.put(key, value.to_s, Utils.only(options, *PUT_FLAGS))
69
66
  value
@@ -72,7 +69,7 @@ module Moneta
72
69
 
73
70
  # (see Defaults#create)
74
71
  def create(key, value, options = {})
75
- @backend.transaction do
72
+ backend.transaction do
76
73
  if @db.get(key)
77
74
  false
78
75
  else
@@ -84,7 +81,7 @@ module Moneta
84
81
 
85
82
  # (see Proxy#close)
86
83
  def close
87
- @backend.close
84
+ backend.close
88
85
  nil
89
86
  end
90
87
 
@@ -103,17 +100,17 @@ module Moneta
103
100
 
104
101
  # (see Proxy#values_at)
105
102
  def values_at(*keys, **options)
106
- @backend.transaction { super }
103
+ backend.transaction { super }
107
104
  end
108
105
 
109
106
  # (see Proxy#slice)
110
107
  def slice(*keys, **options)
111
- @backend.transaction { super }
108
+ backend.transaction { super }
112
109
  end
113
110
 
114
111
  # (see Proxy#merge!)
115
112
  def merge!(pairs, options = {})
116
- @backend.transaction { super }
113
+ backend.transaction { super }
117
114
  end
118
115
  end
119
116
  end
@@ -4,25 +4,19 @@ module Moneta
4
4
  module Adapters
5
5
  # LocalMemCache backend
6
6
  # @api public
7
- class LocalMemCache
8
- include Defaults
7
+ class LocalMemCache < Adapter
9
8
  include HashAdapter
10
9
 
11
- # @param [Hash] options
12
- # @option options [String] :file Database file
13
- # @option options [::LocalMemCache] :backend Use existing backend instance
14
- def initialize(options = {})
15
- @backend = options[:backend] ||
16
- begin
17
- raise ArgumentError, 'Option :file is required' unless options[:file]
18
- ::LocalMemCache.new(filename: options[:file])
19
- end
20
- end
10
+ # @!method initialize(options = {})
11
+ # @param [Hash] options
12
+ # @option options [String] :file Database file
13
+ # @option options [::LocalMemCache] :backend Use existing backend instance
14
+ backend { |file:| ::LocalMemCache.new(filename: file) }
21
15
 
22
16
  # (see Proxy#delete)
23
17
  def delete(key, options = {})
24
18
  value = load(key, options)
25
- @backend.delete(key)
19
+ backend.delete(key)
26
20
  value
27
21
  end
28
22
  end
@@ -6,70 +6,70 @@ module Moneta
6
6
  # both memory usage and hash size.
7
7
  #
8
8
  # @api public
9
- class LRUHash
10
- include Defaults
9
+ class LRUHash < Adapter
11
10
  include IncrementSupport
12
11
  include CreateSupport
13
12
 
14
- DEFAULT_MAX_SIZE = 1024000
15
- DEFAULT_MAX_COUNT = 10240
13
+ config :max_size, default: 1024000
14
+ config(:max_value) { |max_size:, max_value:, **| [max_value, max_size].compact.min }
15
+ config :max_count, default: 10240
16
16
 
17
17
  supports :each_key
18
18
 
19
+ backend { {} }
20
+
19
21
  # @param [Hash] options
20
22
  # @option options [Integer] :max_size (1024000) Maximum byte size of all values, nil disables the limit
21
23
  # @option options [Integer] :max_value (options[:max_size]) Maximum byte size of one value, nil disables the limit
22
24
  # @option options [Integer] :max_count (10240) Maximum number of values, nil disables the limit
23
25
  def initialize(options = {})
24
- @max_size = options.fetch(:max_size) { DEFAULT_MAX_SIZE }
25
- @max_count = options.fetch(:max_count) { DEFAULT_MAX_COUNT }
26
- @max_value = [options[:max_value], @max_size].compact.min
26
+ super
27
27
  clear
28
28
  end
29
29
 
30
30
  # (see Proxy#key?)
31
31
  def key?(key, options = {})
32
- @backend.key?(key)
32
+ backend.key?(key)
33
33
  end
34
34
 
35
35
  # (see Proxy#each_key)
36
36
  def each_key(&block)
37
- return enum_for(:each_key) { @backend.length } unless block_given?
37
+ return enum_for(:each_key) { backend.length } unless block_given?
38
38
 
39
39
  # The backend needs to be duplicated because reading mutates this
40
40
  # store.
41
- @backend.dup.each_key { |k| yield(k) }
41
+ backend.dup.each_key { |k| yield(k) }
42
42
  self
43
43
  end
44
44
 
45
45
  # (see Proxy#load)
46
46
  def load(key, options = {})
47
- if value = @backend.delete(key)
48
- @backend[key] = value
47
+ if value = backend.delete(key)
48
+ backend[key] = value
49
49
  value
50
50
  end
51
51
  end
52
52
 
53
53
  # (see Proxy#store)
54
54
  def store(key, value, options = {})
55
- if @max_value && value.bytesize > @max_value
55
+ if config.max_value && value.bytesize > config.max_value
56
56
  delete(key)
57
57
  else
58
- if @max_size
59
- if old_value = @backend.delete(key)
58
+ if config.max_size
59
+ if old_value = backend.delete(key)
60
60
  @size -= old_value.bytesize
61
61
  end
62
62
  @size += value.bytesize
63
63
  end
64
- @backend[key] = value
65
- drop while @max_size && @size > @max_size || @max_count && @backend.size > @max_count
64
+ backend[key] = value
65
+ drop while config.max_size && @size > config.max_size || config.max_count && backend.size > config.max_count
66
66
  end
67
67
  value
68
68
  end
69
69
 
70
70
  # (see Proxy#delete)
71
71
  def delete(key, options = {})
72
- if value = @backend.delete(key) and @max_size
72
+ if value = backend.delete(key) and config.max_size
73
73
  @size -= value.bytesize
74
74
  end
75
75
  value
@@ -77,7 +77,7 @@ module Moneta
77
77
 
78
78
  # (see Proxy#clear)
79
79
  def clear(options = {})
80
- @backend = {}
80
+ backend.clear
81
81
  @size = 0
82
82
  self
83
83
  end
@@ -87,7 +87,7 @@ module Moneta
87
87
  # @param [Hash] options Options to merge
88
88
  # @return [(Object, String), nil] The dropped pair, if any
89
89
  def drop(options = {})
90
- if key = @backend.keys.first
90
+ if key = backend.keys.first
91
91
  [key, delete(key)]
92
92
  end
93
93
  end
@@ -4,47 +4,39 @@ module Moneta
4
4
  module Adapters
5
5
  # Memcached backend (using gem dalli)
6
6
  # @api public
7
- class MemcachedDalli
8
- include Defaults
7
+ class MemcachedDalli < Adapter
9
8
  include ExpiresSupport
10
9
 
11
10
  supports :create, :increment
12
- attr_reader :backend
13
-
14
- # @param [Hash] options
15
- # @option options [String] :server ('127.0.0.1:11211') Memcached server
16
- # @option options [Integer] :expires Default expiration time
17
- # @option options [::Dalli::Client] :backend Use existing backend instance
18
- # @option options Other options passed to `Dalli::Client#new`
19
- def initialize(options = {})
20
- self.default_expires = options.delete(:expires)
21
- @backend = options[:backend] ||
22
- begin
23
- server = options.delete(:server) || '127.0.0.1:11211'
24
- ::Dalli::Client.new(server, options)
25
- end
26
- end
11
+
12
+ # @!method initialize(options = {})
13
+ # @param [Hash] options
14
+ # @option options [String] :server ('127.0.0.1:11211') Memcached server
15
+ # @option options [Integer] :expires Default expiration time
16
+ # @option options [::Dalli::Client] :backend Use existing backend instance
17
+ # @option options Other options passed to `Dalli::Client#new`
18
+ backend { |server: '127.0.0.1:11211', **options| ::Dalli::Client.new(server, options) }
27
19
 
28
20
  # (see Proxy#load)
29
21
  def load(key, options = {})
30
- value = @backend.get(key)
22
+ value = backend.get(key)
31
23
  if value
32
24
  expires = expires_value(options, nil)
33
- @backend.set(key, value, expires || nil, raw: true) if expires != nil
25
+ backend.set(key, value, expires || nil, raw: true) if expires != nil
34
26
  value
35
27
  end
36
28
  end
37
29
 
38
30
  # (see Proxy#store)
39
31
  def store(key, value, options = {})
40
- @backend.set(key, value, expires_value(options) || nil, raw: true)
32
+ backend.set(key, value, expires_value(options) || nil, raw: true)
41
33
  value
42
34
  end
43
35
 
44
36
  # (see Proxy#delete)
45
37
  def delete(key, options = {})
46
- value = @backend.get(key)
47
- @backend.delete(key)
38
+ value = backend.get(key)
39
+ backend.delete(key)
48
40
  value
49
41
  end
50
42
 
@@ -52,9 +44,9 @@ module Moneta
52
44
  def increment(key, amount = 1, options = {})
53
45
  result =
54
46
  if amount >= 0
55
- @backend.incr(key, amount, expires_value(options) || nil)
47
+ backend.incr(key, amount, expires_value(options) || nil)
56
48
  else
57
- @backend.decr(key, -amount, expires_value(options) || nil)
49
+ backend.decr(key, -amount, expires_value(options) || nil)
58
50
  end
59
51
  if result
60
52
  result
@@ -67,32 +59,32 @@ module Moneta
67
59
 
68
60
  # (see Proxy#clear)
69
61
  def clear(options = {})
70
- @backend.flush_all
62
+ backend.flush_all
71
63
  self
72
64
  end
73
65
 
74
66
  # (see Defaults#create)
75
67
  def create(key, value, options = {})
76
- !!@backend.add(key, value, expires_value(options) || nil, raw: true)
68
+ !!backend.add(key, value, expires_value(options) || nil, raw: true)
77
69
  end
78
70
 
79
71
  # (see Proxy#close)
80
72
  def close
81
- @backend.close
73
+ backend.close
82
74
  nil
83
75
  end
84
76
 
85
77
  # (see Defaults#slice)
86
78
  def slice(*keys, **options)
87
- @backend.get_multi(keys).tap do |pairs|
79
+ backend.get_multi(keys).tap do |pairs|
88
80
  next if pairs.empty?
89
81
  expires = expires_value(options, nil)
90
82
  next if expires == nil
91
83
  expires = expires.to_i if Numeric === expires
92
84
  expires ||= 0
93
- @backend.multi do
85
+ backend.multi do
94
86
  pairs.each do |key, value|
95
- @backend.set(key, value, expires, false)
87
+ backend.set(key, value, expires, false)
96
88
  end
97
89
  end
98
90
  end
@@ -112,7 +104,7 @@ module Moneta
112
104
 
113
105
  if block_given?
114
106
  keys = pairs.map { |key, _| key }.to_a
115
- old_pairs = @backend.get_multi(keys)
107
+ old_pairs = backend.get_multi(keys)
116
108
  pairs = pairs.map do |key, new_value|
117
109
  if old_pairs.key? key
118
110
  new_value = yield(key, old_pairs[key], new_value)
@@ -121,9 +113,9 @@ module Moneta
121
113
  end
122
114
  end
123
115
 
124
- @backend.multi do
116
+ backend.multi do
125
117
  pairs.each do |key, value|
126
- @backend.set(key, value, expires, raw: true)
118
+ backend.set(key, value, expires, raw: true)
127
119
  end
128
120
  end
129
121
 
@@ -4,30 +4,24 @@ module Moneta
4
4
  module Adapters
5
5
  # Memcached backend (using gem memcached)
6
6
  # @api public
7
- class MemcachedNative
8
- include Defaults
7
+ class MemcachedNative < Adapter
9
8
  include ExpiresSupport
10
9
 
11
10
  supports :create, :increment
12
- attr_reader :backend
13
11
 
14
- # @param [Hash] options
15
- # @option options [String] :server ('127.0.0.1:11211') Memcached server
16
- # @option options [String] :namespace Key namespace
17
- # @option options [Integer] :expires (604800) Default expiration time
18
- # @option options [::Memcached] :backend Use existing backend instance
19
- # @option options Other options passed to `Memcached#new`
20
- def initialize(options = {})
21
- server = options.delete(:server) || '127.0.0.1:11211'
22
- self.default_expires = options.delete(:expires)
23
- @backend = options[:backend] ||
24
- begin
25
- options[:prefix_key] = options.delete(:namespace) if options[:namespace]
26
- # We don't want a limitation on the key charset. Therefore we use the binary protocol.
27
- # It is also faster.
28
- options[:binary_protocol] = true unless options.include?(:binary_protocol)
29
- ::Memcached.new(server, options)
30
- end
12
+ # @!method initialize(options = {})
13
+ # @param [Hash] options
14
+ # @option options [String] :server ('127.0.0.1:11211') Memcached server
15
+ # @option options [String] :namespace Key namespace
16
+ # @option options [Integer] :expires (604800) Default expiration time
17
+ # @option options [::Memcached] :backend Use existing backend instance
18
+ # @option options Other options passed to `Memcached#new`
19
+ backend do |server: '127.0.0.1:11211', namespace: nil, **options|
20
+ options[:prefix_key] = namespace if namespace
21
+ # We don't want a limitation on the key charset. Therefore we use the binary protocol.
22
+ # It is also faster.
23
+ options[:binary_protocol] = true unless options.include?(:binary_protocol)
24
+ ::Memcached.new(server, options)
31
25
  end
32
26
 
33
27
  # (see Proxy#load)
@@ -2,19 +2,17 @@ module Moneta
2
2
  module Adapters
3
3
  # Memory backend using a hash to store the entries
4
4
  # @api public
5
- class Memory
6
- include Defaults
5
+ class Memory < Adapter
7
6
  include NilValues
8
7
  include HashAdapter
9
8
  include IncrementSupport
10
9
  include CreateSupport
11
10
  include EachKeySupport
12
11
 
13
- # @param [Hash] options Options hash
14
- # @option options [Hash] :backend Use existing backend instance
15
- def initialize(options = {})
16
- @backend = options[:backend] || {}
17
- end
12
+ # @!method initialize(options = {})
13
+ # @param [Hash] options Options hash
14
+ # @option options [Hash] :backend Use existing backend instance
15
+ backend { {} }
18
16
  end
19
17
  end
20
18
  end
@@ -14,14 +14,33 @@ module Moneta
14
14
  # db['key'] = {a: 1, b: 2}
15
15
  #
16
16
  # @api public
17
- class Mongo
18
- include Defaults
17
+ class Mongo < Adapter
19
18
  include ExpiresSupport
20
19
 
21
20
  supports :each_key, :create, :increment
22
- attr_reader :backend
23
21
 
24
- DEFAULT_PORT = 27017
22
+ config :collection, default: 'moneta'
23
+
24
+ config :db
25
+ config :database, default: 'moneta' do |database:, db:, **|
26
+ if db
27
+ warn('Moneta::Adapters::Mongo - the :db option is deprecated and will be removed in a future version. Use :database instead')
28
+ db
29
+ else
30
+ database
31
+ end
32
+ end
33
+
34
+ config :expires_field, default: 'expiresAt'
35
+ config :value_field, default: 'value'
36
+ config :type_field, default: 'type'
37
+
38
+ backend do |host: '127.0.0.1', port: 27017, **options|
39
+ options[:logger] ||= ::Logger.new(STDERR).tap do |logger|
40
+ logger.level = ::Logger::ERROR
41
+ end
42
+ ::Mongo::Client.new(["#{host}:#{port}"], options)
43
+ end
25
44
 
26
45
  # @param [Hash] options
27
46
  # @option options [String] :collection ('moneta') MongoDB collection name
@@ -37,31 +56,13 @@ module Moneta
37
56
  # @option options [::Mongo::Client] :backend Use existing backend instance
38
57
  # @option options Other options passed to `Mongo::MongoClient#new`
39
58
  def initialize(options = {})
40
- self.default_expires = options.delete(:expires)
41
- @expires_field = options.delete(:expires_field) || 'expiresAt'
42
- @value_field = options.delete(:value_field) || 'value'
43
- @type_field = options.delete(:type_field) || 'type'
59
+ super
44
60
 
45
- collection = options.delete(:collection) || 'moneta'
61
+ @database = backend.use(config.database)
62
+ @collection = @database[config.collection]
46
63
 
47
- if options.key?(:db)
48
- warn('Moneta::Adapters::Mongo - the :db option is deprecated and will be removed in a future version. Use :database instead')
49
- end
50
- database = options.delete(:database) || options.delete(:db) || 'moneta'
51
- backend = options[:backend] ||
52
- begin
53
- host = options.delete(:host) || '127.0.0.1'
54
- port = options.delete(:port) || DEFAULT_PORT
55
- options[:logger] ||= ::Logger.new(STDERR).tap do |logger|
56
- logger.level = ::Logger::ERROR
57
- end
58
- ::Mongo::Client.new(["#{host}:#{port}"], options)
59
- end
60
-
61
- @backend = backend.use(database)
62
- @collection = @backend[collection]
63
- if @backend.command(buildinfo: 1).documents.first['version'] >= '2.2'
64
- @collection.indexes.create_one({ @expires_field => 1 }, expire_after: 0)
64
+ if @database.command(buildinfo: 1).documents.first['version'] >= '2.2'
65
+ @collection.indexes.create_one({ config.expires_field => 1 }, expire_after: 0)
65
66
  else
66
67
  warn 'Moneta::Adapters::Mongo - You are using MongoDB version < 2.2, expired documents will not be deleted'
67
68
  end
@@ -78,7 +79,7 @@ module Moneta
78
79
 
79
80
  if doc
80
81
  update_expiry(options, nil) do |expires|
81
- view.update_one(:$set => { @expires_field => expires })
82
+ view.update_one(:$set => { config.expires_field => expires })
82
83
  end
83
84
 
84
85
  doc_to_value(doc)
@@ -105,7 +106,7 @@ module Moneta
105
106
  def delete(key, options = {})
106
107
  key = to_binary(key)
107
108
  if doc = @collection.find(_id: key).find_one_and_delete and
108
- !doc[@expires_field] || doc[@expires_field] >= Time.now
109
+ !doc[config.expires_field] || doc[config.expires_field] >= Time.now
109
110
  doc_to_value(doc)
110
111
  end
111
112
  end
@@ -113,9 +114,9 @@ module Moneta
113
114
  # (see Proxy#increment)
114
115
  def increment(key, amount = 1, options = {})
115
116
  @collection.find_one_and_update({ :$and => [{ _id: to_binary(key) }, not_expired] },
116
- { :$inc => { @value_field => amount } },
117
+ { :$inc => { config.value_field => amount } },
117
118
  return_document: :after,
118
- upsert: true)[@value_field]
119
+ upsert: true)[config.value_field]
119
120
  rescue ::Mongo::Error::OperationFailure
120
121
  tries ||= 0
121
122
  (tries += 1) < 3 ? retry : raise
@@ -126,8 +127,8 @@ module Moneta
126
127
  key = to_binary(key)
127
128
  @collection.insert_one(value_to_doc(key, value, options))
128
129
  true
129
- rescue ::Mongo::Error::OperationFailure => ex
130
- raise unless ex.message =~ /^E11000 / # duplicate key error
130
+ rescue ::Mongo::Error::OperationFailure => error
131
+ raise unless error.code == 11000 # duplicate key error
131
132
  false
132
133
  end
133
134
 
@@ -139,7 +140,7 @@ module Moneta
139
140
 
140
141
  # (see Proxy#close)
141
142
  def close
142
- @backend.close
143
+ @database.close
143
144
  nil
144
145
  end
145
146
 
@@ -152,7 +153,7 @@ module Moneta
152
153
  pairs = view.map { |doc| [from_binary(doc[:_id]), doc_to_value(doc)] }
153
154
 
154
155
  update_expiry(options, nil) do |expires|
155
- view.update_many(:$set => { @expires_field => expires })
156
+ view.update_many(:$set => { config.expires_field => expires })
156
157
  end
157
158
 
158
159
  pairs
@@ -198,18 +199,18 @@ module Moneta
198
199
  private
199
200
 
200
201
  def doc_to_value(doc)
201
- case doc[@type_field]
202
+ case doc[config.type_field]
202
203
  when 'Hash'
203
204
  doc = doc.dup
204
205
  doc.delete('_id')
205
- doc.delete(@type_field)
206
- doc.delete(@expires_field)
206
+ doc.delete(config.type_field)
207
+ doc.delete(config.expires_field)
207
208
  doc
208
209
  when 'Number'
209
- doc[@value_field]
210
+ doc[config.value_field]
210
211
  else
211
212
  # In ruby_bson version 2 (and probably up), #to_s no longer returns the binary data
212
- from_binary(doc[@value_field])
213
+ from_binary(doc[config.value_field])
213
214
  end
214
215
  end
215
216
 
@@ -217,22 +218,22 @@ module Moneta
217
218
  case value
218
219
  when Hash
219
220
  value.merge('_id' => key,
220
- @type_field => 'Hash',
221
- # @expires_field must be a Time object (BSON date datatype)
222
- @expires_field => expires_at(options) || nil)
221
+ config.type_field => 'Hash',
222
+ # expires_field must be a Time object (BSON date datatype)
223
+ config.expires_field => expires_at(options) || nil)
223
224
  when Float, Integer
224
225
  { '_id' => key,
225
- @type_field => 'Number',
226
- @value_field => value,
227
- # @expires_field must be a Time object (BSON date datatype)
228
- @expires_field => expires_at(options) || nil }
226
+ config.type_field => 'Number',
227
+ config.value_field => value,
228
+ # expires_field must be a Time object (BSON date datatype)
229
+ config.expires_field => expires_at(options) || nil }
229
230
  when String
230
231
  intvalue = value.to_i
231
232
  { '_id' => key,
232
- @type_field => 'String',
233
- @value_field => intvalue.to_s == value ? intvalue : to_binary(value),
233
+ config.type_field => 'String',
234
+ config.value_field => intvalue.to_s == value ? intvalue : to_binary(value),
234
235
  # @expires_field must be a Time object (BSON date datatype)
235
- @expires_field => expires_at(options) || nil }
236
+ config.expires_field => expires_at(options) || nil }
236
237
  else
237
238
  raise ArgumentError, "Invalid value type: #{value.class}"
238
239
  end
@@ -253,8 +254,8 @@ module Moneta
253
254
  def not_expired
254
255
  {
255
256
  :$or => [
256
- { @expires_field => nil },
257
- { @expires_field => { :$gte => Time.now } }
257
+ { config.expires_field => nil },
258
+ { config.expires_field => { :$gte => Time.now } }
258
259
  ]
259
260
  }
260
261
  end