moneta 0.7.9 → 0.7.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. data/.travis.yml +2 -2
  2. data/CHANGES +6 -0
  3. data/Gemfile +2 -0
  4. data/README.md +7 -4
  5. data/Rakefile +2 -2
  6. data/lib/moneta.rb +1 -0
  7. data/lib/moneta/adapters/activerecord.rb +1 -2
  8. data/lib/moneta/adapters/cassandra.rb +31 -26
  9. data/lib/moneta/adapters/cookie.rb +2 -2
  10. data/lib/moneta/adapters/couch.rb +5 -3
  11. data/lib/moneta/adapters/daybreak.rb +13 -9
  12. data/lib/moneta/adapters/dbm.rb +7 -3
  13. data/lib/moneta/adapters/file.rb +4 -3
  14. data/lib/moneta/adapters/fog.rb +5 -2
  15. data/lib/moneta/adapters/gdbm.rb +7 -3
  16. data/lib/moneta/adapters/hbase.rb +11 -9
  17. data/lib/moneta/adapters/kyotocabinet.rb +13 -8
  18. data/lib/moneta/adapters/leveldb.rb +9 -5
  19. data/lib/moneta/adapters/localmemcache.rb +7 -3
  20. data/lib/moneta/adapters/memcached/dalli.rb +16 -11
  21. data/lib/moneta/adapters/memcached/native.rb +20 -15
  22. data/lib/moneta/adapters/memory.rb +2 -1
  23. data/lib/moneta/adapters/mongo.rb +13 -8
  24. data/lib/moneta/adapters/pstore.rb +24 -21
  25. data/lib/moneta/adapters/redis.rb +14 -12
  26. data/lib/moneta/adapters/restclient.rb +10 -7
  27. data/lib/moneta/adapters/riak.rb +5 -1
  28. data/lib/moneta/adapters/sdbm.rb +7 -3
  29. data/lib/moneta/adapters/sequel.rb +13 -8
  30. data/lib/moneta/adapters/sqlite.rb +15 -10
  31. data/lib/moneta/adapters/tdb.rb +8 -4
  32. data/lib/moneta/adapters/tokyocabinet.rb +15 -10
  33. data/lib/moneta/adapters/tokyotyrant.rb +107 -0
  34. data/lib/moneta/cache.rb +17 -17
  35. data/lib/moneta/mixins.rb +7 -5
  36. data/lib/moneta/version.rb +1 -1
  37. data/lib/rack/moneta_store.rb +1 -1
  38. data/lib/rack/session/moneta.rb +6 -3
  39. data/script/benchmarks +28 -28
  40. data/script/generate-specs +96 -41
  41. data/script/memusage +40 -0
  42. data/script/start-services +1 -0
  43. data/spec/helper.rb +4 -1
  44. data/spec/moneta/adapter_tokyotyrant_spec.rb +30 -0
  45. data/spec/moneta/cache_file_memory_spec.rb +3 -3
  46. data/spec/moneta/cache_memory_null_spec.rb +1 -1
  47. data/spec/moneta/simple_tokyotyrant_spec.rb +155 -0
  48. data/spec/moneta/simple_tokyotyrant_with_expires_spec.rb +157 -0
  49. data/spec/monetaspecs.rb +79 -37
  50. data/spec/rack/moneta_store_spec.rb +1 -1
  51. data/spec/rack/session_moneta_spec.rb +27 -0
  52. metadata +10 -3
@@ -7,31 +7,36 @@ module Moneta
7
7
  class KyotoCabinet < Memory
8
8
  # @param [Hash] options
9
9
  # @option options [String] :file Database file
10
+ # @option options [::KyotoCabinet::DB] :backend Use existing backend instance
10
11
  def initialize(options = {})
11
- raise ArgumentError, 'Option :file is required' unless options[:file]
12
- @hash = ::KyotoCabinet::DB.new
13
- raise @hash.error.to_s unless @hash.open(options[:file],
14
- ::KyotoCabinet::DB::OWRITER | ::KyotoCabinet::DB::OCREATE)
12
+ if options[:backend]
13
+ @backend = options[:backend]
14
+ else
15
+ raise ArgumentError, 'Option :file is required' unless options[:file]
16
+ @backend = ::KyotoCabinet::DB.new
17
+ raise @backend.error.to_s unless @backend.open(options[:file],
18
+ ::KyotoCabinet::DB::OWRITER | ::KyotoCabinet::DB::OCREATE)
19
+ end
15
20
  end
16
21
 
17
22
  # (see Proxy#key?)
18
23
  def key?(key, options = {})
19
- @hash.check(key) >= 0
24
+ @backend.check(key) >= 0
20
25
  end
21
26
 
22
27
  # (see Proxy#delete)
23
28
  def delete(key, options = {})
24
- @hash.seize(key)
29
+ @backend.seize(key)
25
30
  end
26
31
 
27
32
  # (see Proxy#create)
28
33
  def create(key, value, options = {})
29
- @hash.add(key, value)
34
+ @backend.add(key, value)
30
35
  end
31
36
 
32
37
  # (see Proxy#close)
33
38
  def close
34
- @hash.close
39
+ @backend.close
35
40
  nil
36
41
  end
37
42
  end
@@ -8,25 +8,29 @@ module Moneta
8
8
  # @param [Hash] options
9
9
  # @option options [String] :dir - Database path
10
10
  # @option options All other options passed to `LevelDB::DB#new`
11
+ # @option options [::LevelDB::DB] :backend Use existing backend instance
11
12
  def initialize(options = {})
12
- raise ArgumentError, 'Option :dir is required' unless options[:dir]
13
- @hash = ::LevelDB::DB.new(options[:dir])
13
+ @backend = options[:backend] ||
14
+ begin
15
+ raise ArgumentError, 'Option :dir is required' unless options[:dir]
16
+ ::LevelDB::DB.new(options[:dir])
17
+ end
14
18
  end
15
19
 
16
20
  # (see Proxy#key?)
17
21
  def key?(key, options = {})
18
- @hash.includes?(key)
22
+ @backend.includes?(key)
19
23
  end
20
24
 
21
25
  # (see Proxy#clear)
22
26
  def clear(options = {})
23
- @hash.each {|k,v| delete(k, options) }
27
+ @backend.each {|k,v| delete(k, options) }
24
28
  self
25
29
  end
26
30
 
27
31
  # (see Proxy#close)
28
32
  def close
29
- @hash.close
33
+ @backend.close
30
34
  nil
31
35
  end
32
36
  end
@@ -10,15 +10,19 @@ module Moneta
10
10
 
11
11
  # @param [Hash] options
12
12
  # @option options [String] :file Database file
13
+ # @option options [::LocalMemCache] :backend Use existing backend instance
13
14
  def initialize(options = {})
14
- raise ArgumentError, 'Option :file is required' unless options[:file]
15
- @hash = ::LocalMemCache.new(:filename => options[:file])
15
+ @backend = options[:backend] ||
16
+ begin
17
+ raise ArgumentError, 'Option :file is required' unless options[:file]
18
+ ::LocalMemCache.new(:filename => options[:file])
19
+ end
16
20
  end
17
21
 
18
22
  # (see Proxy#delete)
19
23
  def delete(key, options = {})
20
24
  value = load(key, options)
21
- @hash.delete(key)
25
+ @backend.delete(key)
22
26
  value
23
27
  end
24
28
  end
@@ -9,37 +9,42 @@ module Moneta
9
9
  include ExpiresSupport
10
10
 
11
11
  supports :create, :increment
12
+ attr_reader :backend
12
13
 
13
14
  # @param [Hash] options
14
15
  # @option options [String] :server ('127.0.0.1:11211') Memcached server
15
16
  # @option options [Integer] :expires Default expiration time
17
+ # @option options [::Dalli::Client] :backend Use existing backend instance
16
18
  # @option options Other options passed to `Dalli::Client#new`
17
19
  def initialize(options = {})
18
20
  self.default_expires = options.delete(:expires)
19
- server = options.delete(:server) || '127.0.0.1:11211'
20
- @cache = ::Dalli::Client.new(server, options)
21
+ @backend = options[:backend] ||
22
+ begin
23
+ server = options.delete(:server) || '127.0.0.1:11211'
24
+ ::Dalli::Client.new(server, options)
25
+ end
21
26
  end
22
27
 
23
28
  # (see Proxy#load)
24
29
  def load(key, options = {})
25
- value = @cache.get(key)
30
+ value = @backend.get(key)
26
31
  if value
27
32
  expires = expires_value(options, nil)
28
- @cache.set(key, value, expires || nil, :raw => true) if expires != nil
33
+ @backend.set(key, value, expires || nil, :raw => true) if expires != nil
29
34
  value
30
35
  end
31
36
  end
32
37
 
33
38
  # (see Proxy#store)
34
39
  def store(key, value, options = {})
35
- @cache.set(key, value, expires_value(options) || nil, :raw => true)
40
+ @backend.set(key, value, expires_value(options) || nil, :raw => true)
36
41
  value
37
42
  end
38
43
 
39
44
  # (see Proxy#delete)
40
45
  def delete(key, options = {})
41
- value = @cache.get(key)
42
- @cache.delete(key)
46
+ value = @backend.get(key)
47
+ @backend.delete(key)
43
48
  value
44
49
  end
45
50
 
@@ -48,7 +53,7 @@ module Moneta
48
53
  # FIXME: There is a Dalli bug, load(key) returns a wrong value after increment
49
54
  # therefore we set default = nil and create the counter manually
50
55
  # See https://github.com/mperham/dalli/issues/309
51
- result = amount >= 0 ? @cache.incr(key, amount, nil, nil) : @cache.decr(key, -amount, nil, nil)
56
+ result = amount >= 0 ? @backend.incr(key, amount, nil, nil) : @backend.decr(key, -amount, nil, nil)
52
57
  if result
53
58
  result
54
59
  elsif create(key, amount.to_s, options)
@@ -60,18 +65,18 @@ module Moneta
60
65
 
61
66
  # (see Proxy#clear)
62
67
  def clear(options = {})
63
- @cache.flush_all
68
+ @backend.flush_all
64
69
  self
65
70
  end
66
71
 
67
72
  # (see Defaults#create)
68
73
  def create(key, value, options = {})
69
- @cache.add(key, value, expires_value(options) || nil, :raw => true)
74
+ @backend.add(key, value, expires_value(options) || nil, :raw => true)
70
75
  end
71
76
 
72
77
  # (see Proxy#close)
73
78
  def close
74
- @cache.close
79
+ @backend.close
75
80
  nil
76
81
  end
77
82
  end
@@ -9,28 +9,33 @@ module Moneta
9
9
  include ExpiresSupport
10
10
 
11
11
  supports :create, :increment
12
+ attr_reader :backend
12
13
 
13
14
  # @param [Hash] options
14
15
  # @option options [String] :server ('127.0.0.1:11211') Memcached server
15
16
  # @option options [String] :namespace Key namespace
16
17
  # @option options [Integer] :expires (604800) Default expiration time
18
+ # @option options [::Memcached] :backend Use existing backend instance
17
19
  # @option options Other options passed to `Memcached#new`
18
20
  def initialize(options = {})
19
21
  server = options.delete(:server) || '127.0.0.1:11211'
20
22
  self.default_expires = options.delete(:expires)
21
- options.merge!(:prefix_key => options.delete(:namespace)) if options[:namespace]
22
- # We don't want a limitation on the key charset. Therefore we use the binary protocol.
23
- # It is also faster.
24
- options[:binary_protocol] = true unless options.include?(:binary_protocol)
25
- @cache = ::Memcached.new(server, options)
23
+ @backend = options[:backend] ||
24
+ begin
25
+ options.merge!(: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
26
31
  end
27
32
 
28
33
  # (see Proxy#load)
29
34
  def load(key, options = {})
30
- value = @cache.get(key, false)
35
+ value = @backend.get(key, false)
31
36
  if value
32
37
  expires = expires_value(options, nil)
33
- @cache.set(key, value, expires || 0, false) if expires != nil
38
+ @backend.set(key, value, expires || 0, false) if expires != nil
34
39
  value
35
40
  end
36
41
  rescue ::Memcached::NotFound
@@ -39,14 +44,14 @@ module Moneta
39
44
  # (see Proxy#store)
40
45
  def store(key, value, options = {})
41
46
  # TTL must be Fixnum
42
- @cache.set(key, value, expires_value(options) || 0, false)
47
+ @backend.set(key, value, expires_value(options) || 0, false)
43
48
  value
44
49
  end
45
50
 
46
51
  # (see Proxy#delete)
47
52
  def delete(key, options = {})
48
- value = @cache.get(key, false)
49
- @cache.delete(key)
53
+ value = @backend.get(key, false)
54
+ @backend.delete(key)
50
55
  value
51
56
  rescue ::Memcached::NotFound
52
57
  end
@@ -54,13 +59,13 @@ module Moneta
54
59
  # (see Proxy#increment)
55
60
  def increment(key, amount = 1, options = {})
56
61
  result = if amount >= 0
57
- @cache.increment(key, amount)
62
+ @backend.increment(key, amount)
58
63
  else
59
- @cache.decrement(key, -amount)
64
+ @backend.decrement(key, -amount)
60
65
  end
61
66
  # HACK: Throw error if applied to invalid value
62
67
  # see https://github.com/evan/memcached/issues/110
63
- Utils.to_int((@cache.get(key, false) rescue nil)) if result == 0
68
+ Utils.to_int((@backend.get(key, false) rescue nil)) if result == 0
64
69
  result
65
70
  rescue ::Memcached::NotFound => ex
66
71
  retry unless create(key, amount.to_s, options)
@@ -69,7 +74,7 @@ module Moneta
69
74
 
70
75
  # (see Defaults#create)
71
76
  def create(key, value, options = {})
72
- @cache.add(key, value, expires_value(options) || 0, false)
77
+ @backend.add(key, value, expires_value(options) || 0, false)
73
78
  true
74
79
  rescue ::Memcached::ConnectionDataExists
75
80
  false
@@ -77,7 +82,7 @@ module Moneta
77
82
 
78
83
  # (see Proxy#clear)
79
84
  def clear(options = {})
80
- @cache.flush
85
+ @backend.flush
81
86
  self
82
87
  end
83
88
  end
@@ -9,8 +9,9 @@ module Moneta
9
9
  include CreateSupport
10
10
 
11
11
  # @param [Hash] options Options hash
12
+ # @option options [Hash] :backend Use existing backend instance
12
13
  def initialize(options = {})
13
- @hash = {}
14
+ @backend = options[:backend] || {}
14
15
  end
15
16
  end
16
17
  end
@@ -13,6 +13,7 @@ module Moneta
13
13
  include ExpiresSupport
14
14
 
15
15
  supports :create, :increment
16
+ attr_reader :backend
16
17
 
17
18
  # @param [Hash] options
18
19
  # @option options [String] :collection ('moneta') MongoDB collection name
@@ -22,19 +23,23 @@ module Moneta
22
23
  # @option options [Integer] :port (MongoDB default port) MongoDB server port
23
24
  # @option options [String] :db ('moneta') MongoDB database
24
25
  # @option options [Integer] :expires Default expiration time
26
+ # @option options [::Mongo::MongoClient] :backend Use existing backend instance
25
27
  def initialize(options = {})
26
28
  self.default_expires = options.delete(:expires)
27
29
  collection = options.delete(:collection) || 'moneta'
28
- host = options.delete(:host) || '127.0.0.1'
29
- port = options.delete(:port) || ::Mongo::MongoClient::DEFAULT_PORT
30
30
  db = options.delete(:db) || 'moneta'
31
- user = options.delete(:user)
32
- password = options.delete(:password)
33
- client = ::Mongo::MongoClient.new(host, port, options)
34
- db = client.db(db)
31
+ @backend = options[:backend] ||
32
+ begin
33
+ host = options.delete(:host) || '127.0.0.1'
34
+ port = options.delete(:port) || ::Mongo::MongoClient::DEFAULT_PORT
35
+ user = options.delete(:user)
36
+ password = options.delete(:password)
37
+ ::Mongo::MongoClient.new(host, port, options)
38
+ end
39
+ db = @backend.db(db)
35
40
  db.authenticate(user, password, true) if user && password
36
41
  @collection = db.collection(collection)
37
- if client.server_version >= '2.2'
42
+ if @backend.server_version >= '2.2'
38
43
  @collection.ensure_index([['expiresAt', ::Mongo::ASCENDING]], :expireAfterSeconds => 0)
39
44
  else
40
45
  warn 'Moneta::Adapters::Mongo - You are using MongoDB version < 2.2, expired documents will not be deleted'
@@ -105,7 +110,7 @@ module Moneta
105
110
 
106
111
  # (see Proxy#close)
107
112
  def close
108
- @collection.db.connection.close
113
+ @backend.close
109
114
  nil
110
115
  end
111
116
  end
@@ -8,51 +8,56 @@ module Moneta
8
8
  include Defaults
9
9
 
10
10
  supports :create, :increment
11
+ attr_reader :backend
11
12
 
12
13
  # @param [Hash] options
13
14
  # @option options [String] :file PStore file
15
+ # @option options [::PStore] :backend Use existing backend instance
14
16
  def initialize(options = {})
15
- raise ArgumentError, 'Option :file is required' unless options[:file]
16
- FileUtils.mkpath(::File.dirname(options[:file]))
17
- @pstore = new_store(options)
17
+ @backend = options[:backend] ||
18
+ begin
19
+ raise ArgumentError, 'Option :file is required' unless options[:file]
20
+ FileUtils.mkpath(::File.dirname(options[:file]))
21
+ new_store(options)
22
+ end
18
23
  end
19
24
 
20
25
  # (see Proxy#key?)
21
26
  def key?(key, options = {})
22
- @pstore.transaction(true) { @pstore.root?(key) }
27
+ @backend.transaction(true) { @backend.root?(key) }
23
28
  end
24
29
 
25
30
  # (see Proxy#load)
26
31
  def load(key, options = {})
27
- @pstore.transaction(true) { @pstore[key] }
32
+ @backend.transaction(true) { @backend[key] }
28
33
  end
29
34
 
30
35
  # (see Proxy#store)
31
36
  def store(key, value, options = {})
32
- @pstore.transaction { @pstore[key] = value }
37
+ @backend.transaction { @backend[key] = value }
33
38
  end
34
39
 
35
40
  # (see Proxy#delete)
36
41
  def delete(key, options = {})
37
- @pstore.transaction { @pstore.delete(key) }
42
+ @backend.transaction { @backend.delete(key) }
38
43
  end
39
44
 
40
45
  # (see Proxy#increment)
41
46
  def increment(key, amount = 1, options = {})
42
- @pstore.transaction do
43
- value = Utils.to_int(@pstore[key]) + amount
44
- @pstore[key] = value.to_s
47
+ @backend.transaction do
48
+ value = Utils.to_int(@backend[key]) + amount
49
+ @backend[key] = value.to_s
45
50
  value
46
51
  end
47
52
  end
48
53
 
49
54
  # (see Proxy#create)
50
55
  def create(key, value, options = {})
51
- @pstore.transaction do
52
- if @pstore.root?(key)
56
+ @backend.transaction do
57
+ if @backend.root?(key)
53
58
  false
54
59
  else
55
- @pstore[key] = value
60
+ @backend[key] = value
56
61
  true
57
62
  end
58
63
  end
@@ -60,9 +65,9 @@ module Moneta
60
65
 
61
66
  # (see Proxy#clear)
62
67
  def clear(options = {})
63
- @pstore.transaction do
64
- @pstore.roots.each do |key|
65
- @pstore.delete(key)
68
+ @backend.transaction do
69
+ @backend.roots.each do |key|
70
+ @backend.delete(key)
66
71
  end
67
72
  end
68
73
  self
@@ -70,12 +75,10 @@ module Moneta
70
75
 
71
76
  protected
72
77
 
73
- if RUBY_VERSION > '1.9'
74
- def new_store(options)
78
+ def new_store(options)
79
+ if RUBY_VERSION > '1.9'
75
80
  ::PStore.new(options[:file], options[:threadsafe])
76
- end
77
- else
78
- def new_store(options)
81
+ else
79
82
  ::PStore.new(options[:file])
80
83
  end
81
84
  end
@@ -9,13 +9,15 @@ module Moneta
9
9
  include ExpiresSupport
10
10
 
11
11
  supports :create, :increment
12
+ attr_reader :backend
12
13
 
13
14
  # @param [Hash] options
14
15
  # @option options [Integer] :expires Default expiration time
16
+ # @option options [::Redis] :backend Use existing backend instance
15
17
  # @option options Other options passed to `Redis#new`
16
18
  def initialize(options = {})
17
19
  self.default_expires = options.delete(:expires)
18
- @redis = ::Redis.new(options)
20
+ @backend = options[:backend] || ::Redis.new(options)
19
21
  end
20
22
 
21
23
  # (see Proxy#key?)
@@ -23,7 +25,7 @@ module Moneta
23
25
  # This method considers false and 0 as "no-expire" and every positive
24
26
  # number as a time to live in seconds.
25
27
  def key?(key, options = {})
26
- if @redis.exists(key)
28
+ if @backend.exists(key)
27
29
  update_expires(key, options, nil)
28
30
  true
29
31
  else
@@ -33,7 +35,7 @@ module Moneta
33
35
 
34
36
  # (see Proxy#load)
35
37
  def load(key, options = {})
36
- value = @redis.get(key)
38
+ value = @backend.get(key)
37
39
  update_expires(key, options, nil)
38
40
  value
39
41
  end
@@ -41,9 +43,9 @@ module Moneta
41
43
  # (see Proxy#store)
42
44
  def store(key, value, options = {})
43
45
  if expires = expires_value(options)
44
- @redis.setex(key, expires, value)
46
+ @backend.setex(key, expires, value)
45
47
  else
46
- @redis.set(key, value)
48
+ @backend.set(key, value)
47
49
  end
48
50
  value
49
51
  end
@@ -51,25 +53,25 @@ module Moneta
51
53
  # (see Proxy#delete)
52
54
  def delete(key, options = {})
53
55
  if value = load(key, options)
54
- @redis.del(key)
56
+ @backend.del(key)
55
57
  value
56
58
  end
57
59
  end
58
60
 
59
61
  # (see Proxy#increment)
60
62
  def increment(key, amount = 1, options = {})
61
- @redis.incrby(key, amount)
63
+ @backend.incrby(key, amount)
62
64
  end
63
65
 
64
66
  # (see Proxy#clear)
65
67
  def clear(options = {})
66
- @redis.flushdb
68
+ @backend.flushdb
67
69
  self
68
70
  end
69
71
 
70
72
  # (see Defaults#create)
71
73
  def create(key, value, options = {})
72
- if @redis.setnx(key, value)
74
+ if @backend.setnx(key, value)
73
75
  update_expires(key, options)
74
76
  true
75
77
  else
@@ -79,7 +81,7 @@ module Moneta
79
81
 
80
82
  # (see Proxy#close)
81
83
  def close
82
- @redis.quit
84
+ @backend.quit
83
85
  nil
84
86
  end
85
87
 
@@ -88,9 +90,9 @@ module Moneta
88
90
  def update_expires(key, options, default = @default_expires)
89
91
  case expires = expires_value(options, default)
90
92
  when false
91
- @redis.persist(key)
93
+ @backend.persist(key)
92
94
  when Numeric
93
- @redis.expire(key, expires)
95
+ @backend.expire(key, expires)
94
96
  end
95
97
  end
96
98
  end