moneta 1.4.2 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +35 -38
  3. data/CHANGES +9 -0
  4. data/CONTRIBUTORS +2 -0
  5. data/Gemfile +143 -55
  6. data/README.md +5 -4
  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 +1 -1
  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/moneta/adapters/client/client_helper.rb +4 -3
  55. data/spec/moneta/adapters/faraday_helper.rb +3 -2
  56. data/spec/moneta/adapters/lruhash/adapter_lruhash_spec.rb +10 -6
  57. data/spec/moneta/adapters/mongo/adapter_mongo_spec.rb +2 -2
  58. data/spec/moneta/config_spec.rb +219 -0
  59. data/spec/moneta/proxies/transformer/transformer_bson_spec.rb +3 -1
  60. data/spec/moneta/proxies/transformer/transformer_marshal_escape_spec.rb +2 -0
  61. data/spec/rack/session_moneta_spec.rb +44 -25
  62. data/spec/restserver.rb +3 -14
  63. metadata +24 -6
@@ -4,16 +4,31 @@ module Moneta
4
4
  module Adapters
5
5
  # Sequel backend
6
6
  # @api public
7
- class Sequel
8
- include Defaults
9
-
7
+ class Sequel < Adapter
10
8
  autoload :MySQL, 'moneta/adapters/sequel/mysql'
11
9
  autoload :Postgres, 'moneta/adapters/sequel/postgres'
12
10
  autoload :PostgresHStore, 'moneta/adapters/sequel/postgres_hstore'
13
11
  autoload :SQLite, 'moneta/adapters/sequel/sqlite'
14
12
 
15
13
  supports :create, :increment, :each_key
16
- attr_reader :backend, :key_column, :value_column
14
+
15
+ config :table, default: :moneta, coerce: :to_sym
16
+ config :optimize, default: true
17
+ config :create_table, default: true
18
+ config :key_column, default: :k
19
+ config :value_column, default: :v
20
+ config :hstore, coerce: :to_s
21
+ config :each_key_server
22
+
23
+ backend do |db:, extensions: [], connection_validation_timeout: nil, **options|
24
+ ::Sequel.connect(db, options).tap do |backend|
25
+ extensions.map(&:to_sym).each(&backend.method(:extension))
26
+
27
+ if connection_validation_timeout
28
+ backend.pool.connection_validation_timeout = connection_validation_timeout
29
+ end
30
+ end
31
+ end
17
32
 
18
33
  # @param [Hash] options
19
34
  # @option options [String] :db Sequel database
@@ -22,7 +37,7 @@ module Moneta
22
37
  # @option options [Integer] :connection_validation_timeout (nil) Sequel connection_validation_timeout
23
38
  # @option options [Sequel::Database] :backend Use existing backend instance
24
39
  # @option options [Boolean] :optimize (true) Set to false to prevent database-specific optimisations
25
- # @option options [Proc, Boolean] :create_table Provide a Proc for creating the table, or
40
+ # @option options [Proc, Boolean] :create_table (true) Provide a Proc for creating the table, or
26
41
  # set to false to disable table creation all together. If a Proc is given, it will be
27
42
  # called regardless of whether the table exists already.
28
43
  # @option options [Symbol] :key_column (:k) The name of the key column
@@ -37,32 +52,21 @@ module Moneta
37
52
  # in conjunction with Sequel's `:servers` option
38
53
  # @option options All other options passed to `Sequel#connect`
39
54
  def initialize(options = {})
40
- extensions = options.delete(:extensions)
41
- connection_validation_timeout = options.delete(:connection_validation_timeout)
42
- optimize = options.delete(:optimize)
43
- @backend = options.delete(:backend) ||
44
- connect(extensions: extensions, connection_validation_timeout: connection_validation_timeout, **options)
45
-
46
- if hstore = options.delete(:hstore)
47
- @row = hstore.to_s
55
+ super
56
+
57
+ if config.hstore
48
58
  extend Sequel::PostgresHStore
49
- elsif optimize == nil || optimize
59
+ elsif config.optimize
50
60
  add_optimizations
51
61
  end
52
62
 
53
- @table_name = (options.delete(:table) || :moneta).to_sym
54
- @key_column = options.delete(:key_column) || :k
55
- @value_column = options.delete(:value_column) || :v
56
- @each_key_server = options.delete(:each_key_server)
57
-
58
- create_proc = options.delete(:create_table)
59
- if create_proc == nil
63
+ if config.create_table.respond_to?(:call)
64
+ config.create_table.call(backend)
65
+ elsif config.create_table
60
66
  create_table
61
- elsif create_proc
62
- create_proc.call(@backend)
63
67
  end
64
68
 
65
- @table = @backend[@table_name]
69
+ @table = backend[config.table]
66
70
  prepare_statements
67
71
  end
68
72
 
@@ -74,7 +78,7 @@ module Moneta
74
78
  # (see Proxy#load)
75
79
  def load(key, options = {})
76
80
  if row = @load.call(key: key)
77
- row[value_column]
81
+ row[config.value_column]
78
82
  end
79
83
  end
80
84
 
@@ -100,9 +104,9 @@ module Moneta
100
104
 
101
105
  # (see Proxy#increment)
102
106
  def increment(key, amount = 1, options = {})
103
- @backend.transaction do
107
+ backend.transaction do
104
108
  if existing = @load_for_update.call(key: key)
105
- existing_value = existing[value_column]
109
+ existing_value = existing[config.value_column]
106
110
  amount += Integer(existing_value)
107
111
  raise IncrementError, "no update" unless @increment_update.call(
108
112
  key: key,
@@ -135,13 +139,13 @@ module Moneta
135
139
 
136
140
  # (see Proxy#close)
137
141
  def close
138
- @backend.disconnect
142
+ backend.disconnect
139
143
  nil
140
144
  end
141
145
 
142
146
  # (see Proxy#slice)
143
147
  def slice(*keys, **options)
144
- @slice.all(keys).map! { |row| [row[key_column], row[value_column]] }
148
+ @slice.all(keys).map! { |row| [row[config.key_column], row[config.value_column]] }
145
149
  end
146
150
 
147
151
  # (see Proxy#values_at)
@@ -165,10 +169,10 @@ module Moneta
165
169
 
166
170
  # (see Proxy#merge!)
167
171
  def merge!(pairs, options = {})
168
- @backend.transaction do
172
+ backend.transaction do
169
173
  existing = Hash[slice_for_update(pairs)]
170
174
  update_pairs, insert_pairs = pairs.partition { |k, _| existing.key?(k) }
171
- @table.import([key_column, value_column], blob_pairs(insert_pairs))
175
+ @table.import([config.key_column, config.value_column], blob_pairs(insert_pairs))
172
176
 
173
177
  if block_given?
174
178
  update_pairs.map! do |key, new_value|
@@ -187,8 +191,10 @@ module Moneta
187
191
  # (see Proxy#each_key)
188
192
  def each_key
189
193
  return enum_for(:each_key) { @table.count } unless block_given?
190
- if @each_key_server
191
- @table.server(@each_key_server).order(key_column).select(key_column).paged_each do |row|
194
+
195
+ key_column = config.key_column
196
+ if config.each_key_server
197
+ @table.server(config.each_key_server).order(key_column).select(key_column).paged_each do |row|
192
198
  yield row[key_column]
193
199
  end
194
200
  else
@@ -201,21 +207,6 @@ module Moneta
201
207
 
202
208
  protected
203
209
 
204
- # @api private
205
- def connect(db:, extensions: nil, connection_validation_timeout: nil, **options)
206
- other_cols = [:table, :create_table, :key_column, :value_column, :hstore]
207
- ::Sequel.connect(db, options.reject { |k,| other_cols.member?(k) }).tap do |backend|
208
- if extensions
209
- raise ArgumentError, 'Option :extensions must be an Array' unless extensions.is_a?(Array)
210
- extensions.map(&:to_sym).each(&backend.method(:extension))
211
- end
212
-
213
- if connection_validation_timeout
214
- backend.pool.connection_validation_timeout = connection_validation_timeout
215
- end
216
- end
217
- end
218
-
219
210
  # @api private
220
211
  def add_optimizations
221
212
  case backend.database_type
@@ -243,9 +234,9 @@ module Moneta
243
234
  end
244
235
 
245
236
  def create_table
246
- key_column = self.key_column
247
- value_column = self.value_column
248
- @backend.create_table?(@table_name) do
237
+ key_column = config.key_column
238
+ value_column = config.value_column
239
+ backend.create_table?(config.table) do
249
240
  String key_column, null: false, primary_key: true
250
241
  File value_column
251
242
  end
@@ -253,7 +244,7 @@ module Moneta
253
244
 
254
245
  def slice_for_update(pairs)
255
246
  @slice_for_update.all(pairs.map { |k, _| k }.to_a).map! do |row|
256
- [row[key_column], row[value_column]]
247
+ [row[config.key_column], row[config.value_column]]
257
248
  end
258
249
  end
259
250
 
@@ -266,7 +257,7 @@ module Moneta
266
257
  end
267
258
 
268
259
  def statement_id(id)
269
- "moneta_#{@table_name}_#{id}".to_sym
260
+ "moneta_#{config.table}_#{id}".to_sym
270
261
  end
271
262
 
272
263
  def prepare_statements
@@ -281,49 +272,49 @@ module Moneta
281
272
 
282
273
  def prepare_key
283
274
  @key = @table
284
- .where(key_column => :$key).select(1)
275
+ .where(config.key_column => :$key).select(1)
285
276
  .prepare(:first, statement_id(:key))
286
277
  end
287
278
 
288
279
  def prepare_load
289
280
  @load = @table
290
- .where(key_column => :$key).select(value_column)
281
+ .where(config.key_column => :$key).select(config.value_column)
291
282
  .prepare(:first, statement_id(:load))
292
283
  end
293
284
 
294
285
  def prepare_store
295
286
  @store_update = @table
296
- .where(key_column => :$key)
297
- .prepare(:update, statement_id(:store_update), value_column => :$value)
287
+ .where(config.key_column => :$key)
288
+ .prepare(:update, statement_id(:store_update), config.value_column => :$value)
298
289
  end
299
290
 
300
291
  def prepare_create
301
292
  @create = @table
302
- .prepare(:insert, statement_id(:create), key_column => :$key, value_column => :$value)
293
+ .prepare(:insert, statement_id(:create), config.key_column => :$key, config.value_column => :$value)
303
294
  end
304
295
 
305
296
  def prepare_increment
306
297
  @load_for_update = @table
307
- .where(key_column => :$key).for_update
308
- .select(value_column)
298
+ .where(config.key_column => :$key).for_update
299
+ .select(config.value_column)
309
300
  .prepare(:first, statement_id(:load_for_update))
310
301
  @increment_update ||= @table
311
- .where(key_column => :$key, value_column => :$value)
312
- .prepare(:update, statement_id(:increment_update), value_column => :$new_value)
302
+ .where(config.key_column => :$key, config.value_column => :$value)
303
+ .prepare(:update, statement_id(:increment_update), config.value_column => :$new_value)
313
304
  end
314
305
 
315
306
  def prepare_delete
316
- @delete = @table.where(key_column => :$key)
307
+ @delete = @table.where(config.key_column => :$key)
317
308
  .prepare(:delete, statement_id(:delete))
318
309
  end
319
310
 
320
311
  def prepare_slice
321
312
  @slice_for_update = ::Sequel::Dataset::PlaceholderLiteralizer.loader(@table) do |pl, ds|
322
- ds.filter(key_column => pl.arg).select(key_column, value_column).for_update
313
+ ds.filter(config.key_column => pl.arg).select(config.key_column, config.value_column).for_update
323
314
  end
324
315
 
325
316
  @slice = ::Sequel::Dataset::PlaceholderLiteralizer.loader(@table) do |pl, ds|
326
- ds.filter(key_column => pl.arg).select(key_column, value_column)
317
+ ds.filter(config.key_column => pl.arg).select(config.key_column, config.value_column)
327
318
  end
328
319
  end
329
320
 
@@ -4,12 +4,16 @@ module Moneta
4
4
  module Adapters
5
5
  # Sqlite3 backend
6
6
  # @api public
7
- class Sqlite
8
- include Defaults
7
+ class Sqlite < Adapter
9
8
  include IncrementSupport
10
9
 
11
10
  supports :create, :each_key
12
- attr_reader :backend
11
+
12
+ config :table, default: 'moneta'
13
+ config :busy_timeout, default: 1000
14
+ config :journal_mode
15
+
16
+ backend { |file:| ::SQLite3::Database.new(file) }
13
17
 
14
18
  # @param [Hash] options
15
19
  # @option options [String] :file Database file
@@ -18,31 +22,29 @@ module Moneta
18
22
  # @option options [::Sqlite3::Database] :backend Use existing backend instance
19
23
  # @option options [String, Symbol] :journal_mode Set the journal mode for the connection
20
24
  def initialize(options = {})
21
- @table = options[:table] || 'moneta'
22
- @backend = options[:backend] ||
23
- begin
24
- raise ArgumentError, 'Option :file is required' unless options[:file]
25
- ::SQLite3::Database.new(options[:file])
26
- end
27
- @backend.busy_timeout(options[:busy_timeout] || 1000)
28
- @backend.execute("create table if not exists #{@table} (k blob not null primary key, v blob)")
29
- if journal_mode = options[:journal_mode]
30
- @backend.journal_mode = journal_mode.to_s
25
+ super
26
+
27
+ backend.busy_timeout(config.busy_timeout)
28
+ backend.execute("create table if not exists #{config.table} (k blob not null primary key, v blob)")
29
+
30
+ if journal_mode = config.journal_mode
31
+ backend.journal_mode = journal_mode.to_s
31
32
  end
33
+
32
34
  @stmts =
33
- [@exists = @backend.prepare("select exists(select 1 from #{@table} where k = ?)"),
34
- @select = @backend.prepare("select v from #{@table} where k = ?"),
35
- @replace = @backend.prepare("replace into #{@table} values (?, ?)"),
36
- @delete = @backend.prepare("delete from #{@table} where k = ?"),
37
- @clear = @backend.prepare("delete from #{@table}"),
38
- @create = @backend.prepare("insert into #{@table} values (?, ?)"),
39
- @keys = @backend.prepare("select k from #{@table}"),
40
- @count = @backend.prepare("select count(*) from #{@table}")]
41
-
42
- version = @backend.execute("select sqlite_version()").first.first
35
+ [@exists = backend.prepare("select exists(select 1 from #{config.table} where k = ?)"),
36
+ @select = backend.prepare("select v from #{config.table} where k = ?"),
37
+ @replace = backend.prepare("replace into #{config.table} values (?, ?)"),
38
+ @delete = backend.prepare("delete from #{config.table} where k = ?"),
39
+ @clear = backend.prepare("delete from #{config.table}"),
40
+ @create = backend.prepare("insert into #{config.table} values (?, ?)"),
41
+ @keys = backend.prepare("select k from #{config.table}"),
42
+ @count = backend.prepare("select count(*) from #{config.table}")]
43
+
44
+ version = backend.execute("select sqlite_version()").first.first
43
45
  if @can_upsert = ::Gem::Version.new(version) >= ::Gem::Version.new('3.24.0')
44
- @stmts << (@increment = @backend.prepare <<-SQL)
45
- insert into #{@table} values (?, ?)
46
+ @stmts << (@increment = backend.prepare <<-SQL)
47
+ insert into #{config.table} values (?, ?)
46
48
  on conflict (k)
47
49
  do update set v = cast(cast(v as integer) + ? as blob)
48
50
  where v = '0' or v = X'30' or cast(v as integer) != 0
@@ -76,8 +78,8 @@ module Moneta
76
78
 
77
79
  # (see Proxy#increment)
78
80
  def increment(key, amount = 1, options = {})
79
- @backend.transaction(:exclusive) { return super } unless @can_upsert
80
- @backend.transaction do
81
+ backend.transaction(:exclusive) { return super } unless @can_upsert
82
+ backend.transaction do
81
83
  @increment.execute!(key, amount.to_s, amount)
82
84
  return Integer(load(key))
83
85
  end
@@ -103,14 +105,14 @@ module Moneta
103
105
  # (see Proxy#close)
104
106
  def close
105
107
  @stmts.each { |s| s.close }
106
- @backend.close
108
+ backend.close
107
109
  nil
108
110
  end
109
111
 
110
112
  # (see Proxy#slice)
111
113
  def slice(*keys, **options)
112
- query = "select k, v from #{@table} where k in (#{(['?'] * keys.length).join(',')})"
113
- @backend.execute(query, keys)
114
+ query = "select k, v from #{config.table} where k in (#{(['?'] * keys.length).join(',')})"
115
+ backend.execute(query, keys)
114
116
  end
115
117
 
116
118
  # (see Proxy#values_at)
@@ -134,7 +136,7 @@ module Moneta
134
136
 
135
137
  # (see Proxy#merge!)
136
138
  def merge!(pairs, options = {})
137
- transaction = @backend.transaction if block_given?
139
+ transaction = backend.transaction if block_given?
138
140
 
139
141
  if block_given?
140
142
  existing = Hash[slice(*pairs.map { |k, _| k }.to_a)]
@@ -146,13 +148,13 @@ module Moneta
146
148
  pairs = pairs.to_a
147
149
  end
148
150
 
149
- query = "replace into #{@table} (k, v) values" + (['(?, ?)'] * pairs.length).join(',')
150
- @backend.query(query, pairs.flatten).close
151
+ query = "replace into #{config.table} (k, v) values" + (['(?, ?)'] * pairs.length).join(',')
152
+ backend.query(query, pairs.flatten).close
151
153
  rescue
152
- @backend.rollback if transaction
154
+ backend.rollback if transaction
153
155
  raise
154
156
  else
155
- @backend.commit if transaction
157
+ backend.commit if transaction
156
158
  self
157
159
  end
158
160
 
@@ -4,34 +4,28 @@ module Moneta
4
4
  module Adapters
5
5
  # TDB backend
6
6
  # @api public
7
- class TDB
8
- include Defaults
7
+ class TDB < Adapter
9
8
  include HashAdapter
10
9
  include IncrementSupport
11
10
  include EachKeySupport
12
11
 
13
12
  supports :create
14
13
 
15
- # @param [Hash] options
16
- # @option options [String] :file Database file
17
- # @option options [::TDB] :backend Use existing backend instance
18
- def initialize(options)
19
- @backend = options[:backend] ||
20
- begin
21
- raise ArgumentError, 'Option :file is required' unless file = options.delete(:file)
22
- ::TDB.new(file, options)
23
- end
24
- end
14
+ # @!method initialize(options = {})
15
+ # @param [Hash] options
16
+ # @option options [String] :file Database file
17
+ # @option options [::TDB] :backend Use existing backend instance
18
+ backend { |file:, **options| ::TDB.new(file, options) }
25
19
 
26
20
  # (see Proxy#close)
27
21
  def close
28
- @backend.close
22
+ backend.close
29
23
  nil
30
24
  end
31
25
 
32
26
  # (see Proxy#create)
33
27
  def create(key, value, options = {})
34
- @backend.insert!(key, value)
28
+ backend.insert!(key, value)
35
29
  true
36
30
  rescue ::TDB::ERR::EXISTS
37
31
  false
@@ -4,29 +4,31 @@ module Moneta
4
4
  module Adapters
5
5
  # TokyoCabinet backend
6
6
  # @api public
7
- class TokyoCabinet
8
- include Defaults
7
+ class TokyoCabinet < Adapter
9
8
  include HashAdapter
10
9
  include IncrementSupport
11
10
  include CreateSupport
12
11
  include EachKeySupport
13
12
 
14
- # @param [Hash] options
15
- # @option options [String] :file Database file
16
- # @option options [Symbol] :type (:hdb) Database type (:bdb and :hdb possible)
17
- # @option options [::TokyoCabinet::*DB] :backend Use existing backend instance
18
- def initialize(options = {})
19
- if options[:backend]
20
- @backend = options[:backend]
13
+ # @!method initialize(options = {})
14
+ # @param [Hash] options
15
+ # @option options [String] :file Database file
16
+ # @option options [Symbol] :type (:hdb) Database type (:bdb and :hdb possible)
17
+ # @option options [::TokyoCabinet::*DB] :backend Use existing backend instance
18
+ backend do |file:, type: :hdb|
19
+ case type
20
+ when :bdb
21
+ ::TokyoCabinet::BDB.new.tap do |backend|
22
+ backend.open(file, ::TokyoCabinet::BDB::OWRITER | ::TokyoCabinet::BDB::OCREAT) or
23
+ raise backend.errmsg(backend.ecode)
24
+ end
25
+ when :hdb
26
+ ::TokyoCabinet::HDB.new.tap do |backend|
27
+ backend.open(file, ::TokyoCabinet::HDB::OWRITER | ::TokyoCabinet::HDB::OCREAT) or
28
+ raise backend.errmsg(backend.ecode)
29
+ end
21
30
  else
22
- raise ArgumentError, 'Option :file is required' unless options[:file]
23
- if options[:type] == :bdb
24
- @backend = ::TokyoCabinet::BDB.new
25
- @backend.open(options[:file], ::TokyoCabinet::BDB::OWRITER | ::TokyoCabinet::BDB::OCREAT)
26
- else
27
- @backend = ::TokyoCabinet::HDB.new
28
- @backend.open(options[:file], ::TokyoCabinet::HDB::OWRITER | ::TokyoCabinet::HDB::OCREAT)
29
- end or raise @backend.errmsg(@backend.ecode)
31
+ raise ArgumentError, ":type must be :bdb or :hdb"
30
32
  end
31
33
  end
32
34
 
@@ -10,51 +10,50 @@ module Moneta
10
10
  module Adapters
11
11
  # TokyoTyrant backend
12
12
  # @api public
13
- class TokyoTyrant
14
- include Defaults
13
+ class TokyoTyrant < Adapter
15
14
  include HashAdapter
16
15
 
17
16
  # error code: no record found
18
17
  ENOREC = 7
19
18
 
20
19
  supports :create, :increment
21
- attr_reader :backend
20
+
21
+ backend do |host: '127.0.0.1', port: 1978|
22
+ if defined?(::TokyoTyrant::RDB)
23
+ # Use ruby client
24
+ ::TokyoTyrant::RDB.new.tap do |backend|
25
+ backend.open(host, port) or raise backend.errmsg
26
+ end
27
+ else
28
+ # Use native client
29
+ ::TokyoTyrant::DB.new(host, port)
30
+ end
31
+ end
22
32
 
23
33
  # @param [Hash] options
24
34
  # @option options [String] :host ('127.0.0.1') Server host name
25
35
  # @option options [Integer] :port (1978) Server port
26
36
  # @option options [::TokyoTyrant::RDB] :backend Use existing backend instance
27
37
  def initialize(options = {})
28
- options[:host] ||= '127.0.0.1'
29
- options[:port] ||= 1978
30
- if options[:backend]
31
- @backend = options[:backend]
32
- elsif defined?(::TokyoTyrant::RDB)
33
- # Use ruby client
34
- @backend = ::TokyoTyrant::RDB.new
35
- @backend.open(options[:host], options[:port]) or error
36
- else
37
- # Use native client
38
- @backend = ::TokyoTyrant::DB.new(options[:host], options[:port])
39
- end
40
- @native = @backend.class.name != 'TokyoTyrant::RDB'
38
+ super
39
+ @native = backend.class.name != 'TokyoTyrant::RDB'
41
40
  probe = '__tokyotyrant_endianness_probe'
42
- @backend.delete(probe)
43
- @backend.addint(probe, 1)
44
- @pack = @backend.delete(probe) == [1].pack('l>') ? 'l>' : 'l<'
41
+ backend.delete(probe)
42
+ backend.addint(probe, 1)
43
+ @pack = backend.delete(probe) == [1].pack('l>') ? 'l>' : 'l<'
45
44
  end
46
45
 
47
46
  # (see Proxy#load)
48
47
  def load(key, options = {})
49
- value = @backend[key]
48
+ value = backend[key]
50
49
  # raise if there is an error and the error is not "no record"
51
- error if value == nil && @backend.ecode != ENOREC
50
+ error if value == nil && backend.ecode != ENOREC
52
51
  value && unpack(value)
53
52
  end
54
53
 
55
54
  # (see Proxy#store)
56
55
  def store(key, value, options = {})
57
- @backend.put(key, pack(value)) or error
56
+ backend.put(key, pack(value)) or error
58
57
  value
59
58
  end
60
59
 
@@ -62,14 +61,14 @@ module Moneta
62
61
  def delete(key, options = {})
63
62
  value = load(key, options)
64
63
  if value
65
- @backend.delete(key) or error
64
+ backend.delete(key) or error
66
65
  value
67
66
  end
68
67
  end
69
68
 
70
69
  # (see Proxy#increment)
71
70
  def increment(key, amount = 1, options = {})
72
- @backend.addint(key, amount) or error
71
+ backend.addint(key, amount) or error
73
72
  end
74
73
 
75
74
  # (see Proxy#create)
@@ -77,18 +76,18 @@ module Moneta
77
76
  if @native
78
77
  begin
79
78
  # Native client throws an exception
80
- @backend.putkeep(key, pack(value))
79
+ backend.putkeep(key, pack(value))
81
80
  rescue TokyoTyrantError
82
81
  false
83
82
  end
84
83
  else
85
- @backend.putkeep(key, pack(value))
84
+ backend.putkeep(key, pack(value))
86
85
  end
87
86
  end
88
87
 
89
88
  # (see Proxy#close)
90
89
  def close
91
- @backend.close
90
+ backend.close
92
91
  nil
93
92
  end
94
93
 
@@ -96,10 +95,10 @@ module Moneta
96
95
  def slice(*keys, **options)
97
96
  hash =
98
97
  if @native
99
- @backend.mget(*keys)
98
+ backend.mget(*keys)
100
99
  else
101
100
  hash = Hash[keys.map { |key| [key] }]
102
- raise unless @backend.mget(hash) >= 0
101
+ raise unless backend.mget(hash) >= 0
103
102
  hash
104
103
  end
105
104
 
@@ -142,7 +141,7 @@ module Moneta
142
141
  end
143
142
 
144
143
  def error
145
- raise "#{@backend.class.name} error: #{@backend.errmsg}"
144
+ raise "#{backend.class.name} error: #{backend.errmsg}"
146
145
  end
147
146
  end
148
147
  end
@@ -5,11 +5,7 @@ module Moneta
5
5
  # YAML::Store backend
6
6
  # @api public
7
7
  class YAML < PStore
8
- protected
9
-
10
- def new_store(options)
11
- ::YAML::Store.new(options[:file])
12
- end
8
+ backend { |file:| ::YAML::Store.new(file) }
13
9
  end
14
10
  end
15
11
  end