moneta 0.8.0 → 0.8.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +9 -4
  3. data/CHANGES +15 -0
  4. data/CONTRIBUTORS +6 -0
  5. data/Gemfile +21 -14
  6. data/README.md +2 -2
  7. data/lib/moneta/adapters/file.rb +2 -1
  8. data/lib/moneta/adapters/lruhash.rb +14 -11
  9. data/lib/moneta/adapters/memcached/dalli.rb +1 -1
  10. data/lib/moneta/adapters/memcached/native.rb +6 -0
  11. data/lib/moneta/adapters/mongo/base.rb +16 -1
  12. data/lib/moneta/adapters/mongo/moped.rb +2 -8
  13. data/lib/moneta/adapters/mongo/official.rb +31 -35
  14. data/lib/moneta/adapters/sequel.rb +1 -1
  15. data/lib/moneta/adapters/tokyotyrant.rb +13 -4
  16. data/lib/moneta/builder.rb +1 -1
  17. data/lib/moneta/transformer/config.rb +2 -2
  18. data/lib/moneta/transformer/helper.rb +16 -2
  19. data/lib/moneta/transformer/helper/bson.rb +25 -0
  20. data/lib/moneta/version.rb +1 -1
  21. data/lib/rack/cache/moneta.rb +2 -2
  22. data/script/generate-specs +216 -89
  23. data/script/start-services +6 -6
  24. data/spec/helper.rb +1 -1
  25. data/spec/moneta/adapter_datamapper_spec.rb +1 -1
  26. data/spec/moneta/adapter_lruhash_spec.rb +94 -1
  27. data/spec/moneta/adapter_mongo_moped_spec.rb +12 -4
  28. data/spec/moneta/adapter_mongo_moped_with_default_expires_spec.rb +3 -1
  29. data/spec/moneta/adapter_mongo_official_spec.rb +12 -4
  30. data/spec/moneta/adapter_mongo_official_with_default_expires_spec.rb +3 -1
  31. data/spec/moneta/adapter_mongo_spec.rb +2 -1
  32. data/spec/moneta/adapter_mongo_with_default_expires_spec.rb +3 -1
  33. data/spec/moneta/mutex_spec.rb +12 -12
  34. data/spec/moneta/optionmerger_spec.rb +1 -1
  35. data/spec/moneta/semaphore_spec.rb +15 -15
  36. data/spec/moneta/shared_tcp_spec.rb +1 -1
  37. data/spec/moneta/shared_unix_spec.rb +1 -1
  38. data/spec/moneta/standard_mongo_moped_spec.rb +1 -1
  39. data/spec/moneta/standard_mongo_official_spec.rb +1 -1
  40. data/spec/moneta/standard_mongo_spec.rb +1 -1
  41. data/spec/moneta/transformer_bson_spec.rb +6 -1
  42. data/spec/moneta/transformer_bzip2_spec.rb +1 -1
  43. data/spec/monetaspecs.rb +2434 -2434
  44. data/spec/rack/cache_moneta_spec.rb +2 -2
  45. data/spec/rack/moneta_store_spec.rb +1 -1
  46. metadata +196 -12
  47. data/script/install-bundle +0 -38
  48. data/script/upload-bundle +0 -2
  49. data/script/wait-services +0 -15
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 642e4643f1753537b4510ce0a47cbdbdfb65ebf2
4
- data.tar.gz: 807acd8640b3ae0a78ae725062a6412a2e82b188
3
+ metadata.gz: 1ffd0417515470f90fc239f70af5f5f5c1458343
4
+ data.tar.gz: 1d20edcf756595fbf503741b41f4cc4ca4d6243a
5
5
  SHA512:
6
- metadata.gz: 043562b273cffcb3d165412bc9fb20524a88f05b7c39e3dc26e1982a3ad3f63c8583564ceeb169b553bd33979b821183f40edd1a5ce66a9840533655e84445ea
7
- data.tar.gz: 8d47b90c541c2917a4a05aa5ee896140052d94119aabdea1ba87d88865ed531d11488b8fbcf2efef11f88d5b805f6e5024be8ea58ce05233a0d25f11e0a0ff55
6
+ metadata.gz: 5ab6f8072a7800d0c1313a7e2bb17988b8f1f301dc48d6ba8b7749c13e00effad24beca9ac711d173c837fc2d392e654c12b5d1e65fc977360329b958c2cd598
7
+ data.tar.gz: 7a58e5765b1eca76c1d65863732c74b4d46d88fe1eb49dd67b482a028b071ef13ce8a0607509b9173d67fbafe7aba437152b4de32e31c7d3f51a556d43bb7267
@@ -5,14 +5,19 @@ rvm:
5
5
  - 1.9.3
6
6
  - jruby-19mode
7
7
  - rbx-19mode
8
+ services:
9
+ - riak
10
+ - couchdb
11
+ - redis
12
+ - cassandra
13
+ - memcached
14
+ - mongodb
8
15
  before_install:
16
+ - gem install bundler -v '~> 1.10'
9
17
  #- script/install-kyotocabinet
10
18
  - sudo apt-get install -qq libtokyocabinet8 libtokyocabinet-dev liblzo2-dev libtdb-dev libleveldb-dev tokyotyrant
11
19
  - script/start-services
12
- - script/install-bundle
13
- - script/upload-bundle
14
- - script/wait-services
15
- install: 'echo "Bundle installed"'
20
+ cache: bundler
16
21
  before_script:
17
22
  - mysql -e 'create database moneta;'
18
23
  - mysql -e 'create database moneta_activerecord1;'
data/CHANGES CHANGED
@@ -1,3 +1,18 @@
1
+ 0.8.1
2
+
3
+ * Adapters::TokyoTyrant - more consistent error handling
4
+ * Adapters::MongoMoped - support for moped gem v2.0
5
+ * Adapters::MongoOfficial - support for mongo gem versions 2-4
6
+ * Adapters::File - fix a bug in #load (#74)
7
+ * Adapters::LRUHash - allow to disable the limits by passing nil for max_size, max_count
8
+ * Transformer - don't use OpenSSL::Digest::Digest namespace
9
+ * Adapters::Sequel - fix issue with unknown "blob" type
10
+ * Rack::Cache - fix deprecated require paths
11
+ * Adapters::MemcachedNative - properly close connections
12
+ * Transformer - support bson gem versions 2-4
13
+ * Transformer - switch to rbzip2 gem for bzip2 support
14
+ * Adapters::MemcachedDalli - #create returns a boolean
15
+
1
16
  0.8.0
2
17
 
3
18
  * Rename Moneta::Adapters::Mongo to Moneta::Adapters::MongoOfficial
@@ -1,6 +1,9 @@
1
1
  Adrian Madrid <aemadrid@gmail.com>
2
+ Alastair Pharo <asppsa@gmail.com>
2
3
  Alejandro Crosa <acrosa@sharing.local>
4
+ Alessio Signorini <alessio@signorini.us>
3
5
  Anthony Eden <anthonyeden@gmail.com>
6
+ Atoxhybrid <atoxhybrid@gmail.com>
4
7
  AtoxIO <atoxhybrid@gmail.com>
5
8
  Benjamin Yu <benjaminlyu@gmail.com>
6
9
  Ben Schwarz <ben.schwarz@gmail.com>
@@ -12,9 +15,12 @@ Hampton Catlin <hcatlin@gmail.com>
12
15
  Hannes Georg <hannes.georg@googlemail.com>
13
16
  Hendrik Beskow <hendrik-github@beskow.de>
14
17
  Jari Bakken <jari.bakken@gmail.com>
18
+ Jay Mitchell <jaybmitchell@gmail.com>
15
19
  Jeremy Voorhis <jvoorhis@gmail.com>
16
20
  Jon Crosby <jon@joncrosby.me>
17
21
  lakshan <lakshan@web2media.net>
22
+ Mal McKay <mal.mckay@gmail.com>
23
+ Nathaniel Bibler <git@nathanielbibler.com>
18
24
  Piotr Murach <pmurach@gmail.com>
19
25
  Potapov Sergey <blake131313@gmail.com>
20
26
  Quin Hoxie <quin@aboutus.org>
data/Gemfile CHANGED
@@ -2,15 +2,15 @@ source 'https://rubygems.org'
2
2
  gemspec
3
3
 
4
4
  # Testing
5
- gem 'rspec'
6
- gem 'rspec-retry'
5
+ gem 'rspec', '~> 2.0'
6
+ gem 'rspec-retry', '0.4.4' # 0.4.5 does not work with rspec 2
7
7
 
8
8
  # Serializer used by Transformer
9
9
  gem 'tnetstring'
10
10
  gem 'bencode'
11
11
  gem 'multi_json'
12
12
  gem 'bson_ext', platforms: :ruby
13
- gem 'bson', platforms: :jruby
13
+ gem 'bson', '>= 2.0.0'
14
14
  gem 'ox', platforms: :ruby
15
15
  gem 'msgpack', platforms: :ruby
16
16
  gem 'msgpack-jruby', platforms: :jruby
@@ -18,9 +18,7 @@ gem 'bert', platforms: :ruby
18
18
  gem 'php_serialize'
19
19
 
20
20
  # Compressors used by Transformer
21
- if RUBY_VERSION < '2.0'
22
- gem 'bzip2-ruby', platforms: :mri # Only on mri currently
23
- end
21
+ gem 'rbzip2'
24
22
  gem 'lz4-ruby', platforms: :ruby
25
23
  gem 'ruby-lzma', platforms: :ruby
26
24
  gem 'lzoruby', platforms: :ruby
@@ -36,20 +34,29 @@ gem 'daybreak'
36
34
  gem 'dm-core'
37
35
  gem 'dm-migrations'
38
36
  gem 'dm-mysql-adapter'
39
- # FIXME: Use fog master because of failing tests, fixed after 1.11.1
40
- gem 'fog', github: 'fog/fog'
41
- gem 'activerecord', '>= 3.2.11'
37
+ if RUBY_VERSION < '2.0'
38
+ gem 'fog', '~> 1.12'
39
+ gem 'mime-types', '~> 2.0'
40
+ gem 'addressable', '~> 2.4.0'
41
+ else
42
+ gem 'fog', '>= 1.11.1'
43
+ gem 'mime-types'
44
+ end
45
+ gem 'activerecord', '~> 4.0.0'
42
46
  gem 'redis'
43
- gem 'mongo'
44
- gem 'moped'
47
+ gem 'mongo', '~> 2.1.0'
48
+ gem 'moped', '>= 2.0.0'
45
49
  gem 'sequel'
46
50
  gem 'dalli'
47
51
  gem 'riak-client'
48
52
  gem 'cassandra'
53
+ if RUBY_VERSION < '2.0'
54
+ gem 'json', '~> 1.0'
55
+ end
49
56
  gem 'tokyotyrant'
50
57
  #gem 'ruby-tokyotyrant', platforms: :ruby
51
58
  #gem 'hbaserb'
52
- #gem 'localmemcache'
59
+ gem 'localmemcache'
53
60
  gem 'tdb', platforms: :ruby
54
61
  gem 'leveldb-ruby', platforms: :ruby
55
62
  gem 'lmdb', platforms: :mri
@@ -66,7 +73,7 @@ gem 'jruby-memcached', platforms: :jruby
66
73
  gem 'sqlite3', platforms: :ruby
67
74
  gem 'activerecord-jdbc-adapter', platforms: :jruby
68
75
  gem 'activerecord-jdbcmysql-adapter', platforms: :jruby
69
- gem 'mysql2', '>= 0.3.12b5', platforms: :ruby
76
+ gem 'mysql2', '~> 0.3.12b5', platforms: :ruby
70
77
  # gdbm for jruby needs ffi
71
78
  gem 'ffi', platforms: :jruby
72
79
  gem 'gdbm', platforms: :jruby
@@ -76,5 +83,5 @@ gem 'rack'
76
83
  gem 'rack-cache'
77
84
 
78
85
  # Rails integration testing
79
- gem 'actionpack', '>= 3.2.11'
86
+ gem 'actionpack', '~> 4.0.0'
80
87
  gem 'minitest', '~> 4.7.4'
data/README.md CHANGED
@@ -717,7 +717,7 @@ run lambda { |env|
717
717
  Add the session store in your application configuration `config/environments/*.rb`.
718
718
 
719
719
  ~~~ ruby
720
- require 'moneta'
720
+ require 'action_dispatch/middleware/session/moneta_store'
721
721
 
722
722
  # Only by adapter name
723
723
  config.cache_store :moneta_store, store: :Memory
@@ -738,7 +738,7 @@ Add the cache store in your application configuration `config/environments/*.rb`
738
738
  Moneta cache store doesn't support matchers. If you need these features use a different server-specific implementation.
739
739
 
740
740
  ~~~ ruby
741
- require 'moneta'
741
+ require 'active_support/cache/moneta_store'
742
742
 
743
743
  # Only by adapter name
744
744
  config.cache_store :moneta_store, store: :Memory
@@ -23,7 +23,7 @@ module Moneta
23
23
 
24
24
  # (see Proxy#load)
25
25
  def load(key, options = {})
26
- ::File.read(store_path(key))
26
+ ::File.read(store_path(key), mode: 'rb')
27
27
  rescue Errno::ENOENT
28
28
  end
29
29
 
@@ -69,6 +69,7 @@ module Moneta
69
69
  content = f.read
70
70
  amount += Utils.to_int(content) unless content.empty?
71
71
  content = amount.to_s
72
+ f.binmode
72
73
  f.pos = 0
73
74
  f.write(content)
74
75
  f.truncate(content.bytesize)
@@ -10,14 +10,17 @@ module Moneta
10
10
  include IncrementSupport
11
11
  include CreateSupport
12
12
 
13
+ DEFAULT_MAX_SIZE = 1024000
14
+ DEFAULT_MAX_COUNT = 10240
15
+
13
16
  # @param [Hash] options
14
- # @option options [Integer] :max_size (1024000) Maximum byte size of all values
15
- # @option options [Integer] :max_value (options[:max_size]) Maximum byte size of one value
16
- # @option options [Integer] :max_count (10240) Maximum number of values
17
+ # @option options [Integer] :max_size (1024000) Maximum byte size of all values, nil disables the limit
18
+ # @option options [Integer] :max_value (options[:max_size]) Maximum byte size of one value, nil disables the limit
19
+ # @option options [Integer] :max_count (10240) Maximum number of values, nil disables the limit
17
20
  def initialize(options = {})
18
- @max_size = options[:max_size] || 1024000
19
- @max_count = options[:max_count] || 10240
20
- @max_value = options[:max_value] || @max_size
21
+ @max_size = options.fetch(:max_size) { DEFAULT_MAX_SIZE }
22
+ @max_count = options.fetch(:max_count) { DEFAULT_MAX_COUNT }
23
+ @max_value = [options[:max_value], @max_size].compact.min
21
24
  clear
22
25
  end
23
26
 
@@ -36,19 +39,19 @@ module Moneta
36
39
 
37
40
  # (see Proxy#store)
38
41
  def store(key, value, options = {})
39
- if value.bytesize > @max_value
42
+ if @max_value && value.bytesize > @max_value
40
43
  delete(key)
41
44
  else
42
45
  if entry = @entry[key]
43
- @size -= entry.value.bytesize
46
+ @size -= entry.value.bytesize if @max_size
44
47
  else
45
48
  @entry[key] = entry = Entry.new
46
49
  entry.key = key
47
50
  end
48
51
  entry.value = value
49
- @size += entry.value.bytesize
52
+ @size += entry.value.bytesize if @max_size
50
53
  entry.insert_after(@list)
51
- delete(@list.prev.key) while @list.next != @list.prev && (@size > @max_size || @entry.size > @max_count)
54
+ delete(@list.prev.key) while @list.next != @list.prev && (@max_size && @size > @max_size || @max_count && @entry.size > @max_count)
52
55
  end
53
56
  value
54
57
  end
@@ -56,7 +59,7 @@ module Moneta
56
59
  # (see Proxy#delete)
57
60
  def delete(key, options = {})
58
61
  if entry = @entry.delete(key)
59
- @size -= entry.value.bytesize
62
+ @size -= entry.value.bytesize if @max_size
60
63
  entry.unlink
61
64
  entry.value
62
65
  end
@@ -76,7 +76,7 @@ module Moneta
76
76
 
77
77
  # (see Defaults#create)
78
78
  def create(key, value, options = {})
79
- @backend.add(key, value, expires_value(options) || nil, raw: true)
79
+ !!@backend.add(key, value, expires_value(options) || nil, raw: true)
80
80
  end
81
81
 
82
82
  # (see Proxy#close)
@@ -85,6 +85,12 @@ module Moneta
85
85
  @backend.flush
86
86
  self
87
87
  end
88
+
89
+ # (see Proxy#close)
90
+ def close
91
+ @backend.reset
92
+ nil
93
+ end
88
94
  end
89
95
  end
90
96
  end
@@ -1,3 +1,5 @@
1
+ require 'bson'
2
+
1
3
  module Moneta
2
4
  module Adapters
3
5
  # @api private
@@ -30,7 +32,12 @@ module Moneta
30
32
  when 'Number'
31
33
  doc[@value_field]
32
34
  else
33
- doc[@value_field].to_s
35
+ # In ruby_bson version 2 (and probably up), #to_s no longer returns the binary data
36
+ if doc[@value_field].is_a? ::BSON::Binary and defined? ::BSON::VERSION and ::BSON::VERSION[0].to_i >= 2
37
+ doc[@value_field].data
38
+ else
39
+ doc[@value_field].to_s
40
+ end
34
41
  end
35
42
  end
36
43
 
@@ -58,6 +65,14 @@ module Moneta
58
65
  raise ArgumentError, "Invalid value type: #{value.class}"
59
66
  end
60
67
  end
68
+
69
+ # BSON will use String#force_encoding to make the string 8-bit
70
+ # ASCII. This could break unicode text so we should dup in this
71
+ # case, and it also fails with frozen strings.
72
+ def to_binary(s)
73
+ s = s.dup if s.frozen? || s.encoding != Encoding::ASCII_8BIT
74
+ ::BSON::Binary.new(s)
75
+ end
61
76
  end
62
77
  end
63
78
  end
@@ -38,7 +38,7 @@ module Moneta
38
38
  @backend = options[:backend] ||
39
39
  begin
40
40
  host = options.delete(:host) || '127.0.0.1'
41
- port = options.delete(:port) || 27017
41
+ port = options.delete(:port) || DEFAULT_PORT
42
42
  ::Moped::Session.new(["#{host}:#{port}"])
43
43
  end
44
44
  @backend.use(db)
@@ -99,15 +99,9 @@ module Moneta
99
99
 
100
100
  # (see Proxy#clear)
101
101
  def clear(options = {})
102
- @collection.drop
102
+ @collection.find.remove_all
103
103
  self
104
104
  end
105
-
106
- protected
107
-
108
- def to_binary(s)
109
- ::Moped::BSON::Binary.new(:generic, s)
110
- end
111
105
  end
112
106
  end
113
107
  end
@@ -27,25 +27,25 @@ module Moneta
27
27
  # @option options [String] :expires_field ('expiresAt') Document field to store expiration time
28
28
  # @option options [String] :value_field ('value') Document field to store value
29
29
  # @option options [String] :type_field ('type') Document field to store value type
30
- # @option options [::Mongo::MongoClient] :backend Use existing backend instance
30
+ # @option options [::Mongo::Client] :backend Use existing backend instance
31
31
  # @option options Other options passed to `Mongo::MongoClient#new`
32
32
  def initialize(options = {})
33
33
  super(options)
34
34
  collection = options.delete(:collection) || 'moneta'
35
35
  db = options.delete(:db) || 'moneta'
36
- user = options.delete(:user)
37
- password = options.delete(:password)
38
36
  @backend = options[:backend] ||
39
37
  begin
40
38
  host = options.delete(:host) || '127.0.0.1'
41
- port = options.delete(:port) || ::Mongo::MongoClient::DEFAULT_PORT
42
- ::Mongo::MongoClient.new(host, port, options)
39
+ port = options.delete(:port) || DEFAULT_PORT
40
+ options[:logger] ||= ::Logger.new(STDERR).tap do |logger|
41
+ logger.level = ::Logger::ERROR
42
+ end
43
+ ::Mongo::Client.new(["#{host}:#{port}"], options)
43
44
  end
44
- db = @backend.db(db)
45
- db.authenticate(user, password, true) if user && password
46
- @collection = db.collection(collection)
47
- if @backend.server_version >= '2.2'
48
- @collection.ensure_index([[@expires_field, ::Mongo::ASCENDING]], expireAfterSeconds: 0)
45
+ @backend.use(db)
46
+ @collection = @backend[collection]
47
+ if @backend.command(buildinfo: 1).documents.first['version'] >= '2.2'
48
+ @collection.indexes.create_one({@expires_field => 1}, expire_after: 0)
49
49
  else
50
50
  warn 'Moneta::Adapters::Mongo - You are using MongoDB version < 2.2, expired documents will not be deleted'
51
51
  end
@@ -54,12 +54,12 @@ module Moneta
54
54
  # (see Proxy#load)
55
55
  def load(key, options = {})
56
56
  key = to_binary(key)
57
- doc = @collection.find_one('_id' => key)
57
+ doc = @collection.find(_id: key).limit(1).first
58
58
  if doc && (!doc[@expires_field] || doc[@expires_field] >= Time.now)
59
59
  expires = expires_at(options, nil)
60
- @collection.update({ '_id' => key },
61
- # @expires_field must be a Time object (BSON date datatype)
62
- { '$set' => { @expires_field => expires || nil } }) if expires != nil
60
+ # @expires_field must be a Time object (BSON date datatype)
61
+ @collection.update_one({ _id: key },
62
+ '$set' => { @expires_field => expires }) unless expires.nil?
63
63
  doc_to_value(doc)
64
64
  end
65
65
  end
@@ -67,40 +67,43 @@ module Moneta
67
67
  # (see Proxy#store)
68
68
  def store(key, value, options = {})
69
69
  key = to_binary(key)
70
- @collection.update({ '_id' => key },
71
- value_to_doc(key, value, options),
72
- { upsert: true })
70
+ @collection.replace_one({ _id: key },
71
+ value_to_doc(key, value, options),
72
+ upsert: true)
73
73
  value
74
74
  end
75
75
 
76
76
  # (see Proxy#delete)
77
77
  def delete(key, options = {})
78
- value = load(key, options)
79
- @collection.remove('_id' => to_binary(key)) if value
80
- value
78
+ key = to_binary(key)
79
+ if doc = @collection.find(_id: key).find_one_and_delete and
80
+ !doc[@expires_field] || doc[@expires_field] >= Time.now
81
+ then
82
+ doc_to_value(doc)
83
+ end
81
84
  end
82
85
 
83
86
  # (see Proxy#increment)
84
87
  def increment(key, amount = 1, options = {})
85
- @collection.find_and_modify(query: { '_id' => to_binary(key) },
86
- update: { '$inc' => { @value_field => amount } },
87
- new: true,
88
- upsert: true)[@value_field]
88
+ @collection.find_one_and_update({ _id: to_binary(key) },
89
+ { '$inc' => { @value_field => amount } },
90
+ :return_document => :after,
91
+ :upsert => true)[@value_field]
89
92
  end
90
93
 
91
94
  # (see Proxy#create)
92
95
  def create(key, value, options = {})
93
96
  key = to_binary(key)
94
- @collection.insert(value_to_doc(key, value, options))
97
+ @collection.insert_one(value_to_doc(key, value, options))
95
98
  true
96
- rescue ::Mongo::OperationFailure => ex
97
- raise if ex.error_code != 11000 # duplicate key error
99
+ rescue ::Mongo::Error::OperationFailure => ex
100
+ raise unless ex.message =~ /^E11000 / # duplicate key error
98
101
  false
99
102
  end
100
103
 
101
104
  # (see Proxy#clear)
102
105
  def clear(options = {})
103
- @collection.remove
106
+ @collection.delete_many
104
107
  self
105
108
  end
106
109
 
@@ -109,13 +112,6 @@ module Moneta
109
112
  @backend.close
110
113
  nil
111
114
  end
112
-
113
- protected
114
-
115
- def to_binary(s)
116
- s = s.dup if s.frozen? # HACK: BSON::Binary needs unfrozen string
117
- ::BSON::Binary.new(s)
118
- end
119
115
  end
120
116
  end
121
117
  end