moneta 0.8.0 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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