moneta 1.2.1 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.rubocop.yml +1 -1
- data/.travis.yml +10 -4
- data/CHANGES +9 -0
- data/Gemfile +7 -5
- data/README.md +9 -6
- data/feature_matrix.yaml +2 -1
- data/lib/moneta/adapters/client.rb +56 -19
- data/lib/moneta/adapters/couch.rb +5 -0
- data/lib/moneta/adapters/mongo/moped.rb +4 -1
- data/lib/moneta/builder.rb +2 -2
- data/lib/moneta/lock.rb +6 -1
- data/lib/moneta/pool.rb +12 -0
- data/lib/moneta/proxy.rb +1 -1
- data/lib/moneta/server.rb +215 -61
- data/lib/moneta/shared.rb +13 -7
- data/lib/moneta/transformer.rb +50 -8
- data/lib/moneta/transformer/config.rb +59 -40
- data/lib/moneta/version.rb +1 -1
- data/moneta.gemspec +2 -2
- data/script/benchmarks +6 -1
- data/script/contributors +1 -2
- data/script/start-couchdb +27 -0
- data/script/start-hbase +2 -2
- data/script/start-services +3 -3
- data/spec/features/store.rb +3 -3
- data/spec/features/transform_value.rb +27 -21
- data/spec/helper.rb +52 -53
- data/spec/moneta/adapters/activerecord/standard_activerecord_spec.rb +1 -1
- data/spec/moneta/adapters/activerecord/standard_activerecord_with_expires_spec.rb +1 -1
- data/spec/moneta/adapters/cassandra/standard_cassandra_spec.rb +1 -1
- data/spec/moneta/adapters/client/adapter_client_spec.rb +6 -6
- data/spec/moneta/adapters/client/client_helper.rb +24 -0
- data/spec/moneta/adapters/client/standard_client_tcp_spec.rb +8 -8
- data/spec/moneta/adapters/client/standard_client_unix_spec.rb +23 -7
- data/spec/moneta/adapters/couch/adapter_couch_spec.rb +1 -1
- data/spec/moneta/adapters/couch/standard_couch_spec.rb +2 -2
- data/spec/moneta/adapters/couch/standard_couch_with_expires_spec.rb +2 -2
- data/spec/moneta/adapters/daybreak/standard_daybreak_spec.rb +1 -1
- data/spec/moneta/adapters/daybreak/standard_daybreak_with_expires_spec.rb +1 -1
- data/spec/moneta/adapters/dbm/standard_dbm_spec.rb +1 -1
- data/spec/moneta/adapters/dbm/standard_dbm_with_expires_spec.rb +1 -1
- data/spec/moneta/adapters/file/standard_file_spec.rb +2 -2
- data/spec/moneta/adapters/file/standard_file_with_expires_spec.rb +1 -1
- data/spec/moneta/adapters/gdbm/standard_gdbm_spec.rb +1 -1
- data/spec/moneta/adapters/gdbm/standard_gdbm_with_expires_spec.rb +1 -1
- data/spec/moneta/adapters/kyotocabinet/adapter_kyotocabinet_spec.rb +1 -1
- data/spec/moneta/adapters/kyotocabinet/standard_kyotocabinet_spec.rb +2 -2
- data/spec/moneta/adapters/kyotocabinet/standard_kyotocabinet_with_expires_spec.rb +2 -2
- data/spec/moneta/adapters/leveldb/standard_leveldb_spec.rb +1 -1
- data/spec/moneta/adapters/leveldb/standard_leveldb_with_expires_spec.rb +1 -1
- data/spec/moneta/adapters/lmdb/standard_lmdb_spec.rb +1 -1
- data/spec/moneta/adapters/lmdb/standard_lmdb_with_expires_spec.rb +1 -1
- data/spec/moneta/adapters/lruhash/standard_lruhash_spec.rb +1 -1
- data/spec/moneta/adapters/lruhash/standard_lruhash_with_expires_spec.rb +1 -1
- data/spec/moneta/adapters/memory/standard_memory_spec.rb +1 -1
- data/spec/moneta/adapters/memory/standard_memory_with_compress_spec.rb +1 -1
- data/spec/moneta/adapters/memory/standard_memory_with_expires_spec.rb +1 -1
- data/spec/moneta/adapters/memory/standard_memory_with_json_key_serializer_spec.rb +1 -1
- data/spec/moneta/adapters/memory/standard_memory_with_json_serializer_spec.rb +1 -1
- data/spec/moneta/adapters/memory/standard_memory_with_json_value_serializer_spec.rb +2 -2
- data/spec/moneta/adapters/memory/standard_memory_with_prefix_spec.rb +39 -2
- data/spec/moneta/adapters/memory/standard_memory_with_snappy_compress_spec.rb +2 -2
- data/spec/moneta/adapters/mongo/adapter_mongo_moped_spec.rb +4 -3
- data/spec/moneta/adapters/mongo/adapter_mongo_moped_with_default_expires_spec.rb +5 -3
- data/spec/moneta/adapters/mongo/adapter_mongo_official_spec.rb +4 -2
- data/spec/moneta/adapters/mongo/adapter_mongo_official_with_default_expires_spec.rb +5 -3
- data/spec/moneta/adapters/mongo/adapter_mongo_spec.rb +3 -2
- data/spec/moneta/adapters/mongo/adapter_mongo_with_default_expires_spec.rb +5 -3
- data/spec/moneta/adapters/mongo/standard_mongo_moped_spec.rb +2 -2
- data/spec/moneta/adapters/mongo/standard_mongo_official_spec.rb +2 -2
- data/spec/moneta/adapters/mongo/standard_mongo_spec.rb +2 -2
- data/spec/moneta/adapters/pstore/standard_pstore_spec.rb +1 -1
- data/spec/moneta/adapters/pstore/standard_pstore_with_expires_spec.rb +1 -1
- data/spec/moneta/adapters/redis/standard_redis_spec.rb +1 -1
- data/spec/moneta/adapters/sdbm/standard_sdbm_spec.rb +1 -1
- data/spec/moneta/adapters/sdbm/standard_sdbm_with_expires_spec.rb +1 -1
- data/spec/moneta/adapters/sequel/standard_sequel_spec.rb +1 -1
- data/spec/moneta/adapters/sequel/standard_sequel_with_expires_spec.rb +1 -1
- data/spec/moneta/adapters/sqlite/standard_sqlite_spec.rb +1 -1
- data/spec/moneta/adapters/sqlite/standard_sqlite_with_expires_spec.rb +1 -1
- data/spec/moneta/adapters/tdb/standard_tdb_spec.rb +1 -1
- data/spec/moneta/adapters/tdb/standard_tdb_with_expires_spec.rb +1 -1
- data/spec/moneta/adapters/tokyocabinet/standard_tokyocabinet_spec.rb +1 -1
- data/spec/moneta/adapters/tokyocabinet/standard_tokyocabinet_with_expires_spec.rb +1 -1
- data/spec/moneta/adapters/yaml/standard_yaml_spec.rb +1 -1
- data/spec/moneta/adapters/yaml/standard_yaml_with_expires_spec.rb +1 -1
- data/spec/moneta/builder_spec.rb +22 -0
- data/spec/moneta/proxies/expires/expires_file_spec.rb +1 -1
- data/spec/moneta/proxies/shared/shared_tcp_spec.rb +14 -4
- data/spec/moneta/proxies/shared/shared_unix_spec.rb +4 -4
- data/spec/moneta/proxies/transformer/transformer_bencode_spec.rb +1 -1
- data/spec/moneta/proxies/transformer/transformer_bert_spec.rb +3 -3
- data/spec/moneta/proxies/transformer/transformer_bson_spec.rb +2 -2
- data/spec/moneta/proxies/transformer/transformer_json_spec.rb +1 -1
- data/spec/moneta/proxies/transformer/transformer_key_marshal_spec.rb +1 -1
- data/spec/moneta/proxies/transformer/transformer_key_yaml_spec.rb +1 -1
- data/spec/moneta/proxies/transformer/transformer_marshal_base64_spec.rb +1 -1
- data/spec/moneta/proxies/transformer/transformer_marshal_escape_spec.rb +1 -1
- data/spec/moneta/proxies/transformer/transformer_marshal_hex_spec.rb +1 -1
- data/spec/moneta/proxies/transformer/transformer_marshal_hmac_spec.rb +1 -1
- data/spec/moneta/proxies/transformer/transformer_marshal_prefix_base64_spec.rb +33 -0
- data/spec/moneta/proxies/transformer/transformer_marshal_prefix_spec.rb +1 -1
- data/spec/moneta/proxies/transformer/transformer_marshal_qp_spec.rb +1 -1
- data/spec/moneta/proxies/transformer/transformer_marshal_spec.rb +1 -1
- data/spec/moneta/proxies/transformer/transformer_marshal_urlsafe_base64_spec.rb +1 -1
- data/spec/moneta/proxies/transformer/transformer_marshal_uuencode_spec.rb +1 -1
- data/spec/moneta/proxies/transformer/transformer_msgpack_spec.rb +1 -1
- data/spec/moneta/proxies/transformer/transformer_ox_spec.rb +1 -1
- data/spec/moneta/proxies/transformer/transformer_php_spec.rb +1 -1
- data/spec/moneta/proxies/transformer/transformer_tnet_spec.rb +1 -1
- data/spec/moneta/proxies/transformer/transformer_yaml_spec.rb +2 -2
- data/spec/moneta/proxies/weak_each_key/weak_each_key_spec.rb +0 -2
- data/spec/support/mongo_helper.rb +12 -0
- metadata +18 -12
- data/script/reconfigure-couchdb +0 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9aebec0b5bcf8b12d295aff540c30c453e88883e5d5d498f92f3666adcbf4eeb
|
4
|
+
data.tar.gz: f62cbb548556e6d4a36e0465edb468a7421262620469d7329c34cb7d160553bc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e9544cff0b2b3550776646d83131b8c7db4c3a9e79083ddb56af23a4cffaa9ce5a3de4a8c1db2db3571e768fe00c409692c3a2787ac9e7e8312a3f145d36f270
|
7
|
+
data.tar.gz: 96cf85c80a0dbb86c820351e711470f873139e6544ec450e427a5cba92cf23f615bedd7f2ff5fda7eca8f005631e0dbcb5e79550ef001234b6d231fcaa71c924
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
data/.travis.yml
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
dist: xenial
|
2
2
|
language: ruby
|
3
3
|
rvm:
|
4
|
+
- 2.7
|
4
5
|
- 2.6
|
5
6
|
- 2.5
|
6
7
|
- 2.4
|
7
8
|
- 2.3
|
8
|
-
- 2.
|
9
|
-
- jruby-9.2
|
9
|
+
- jruby-9.2.9.0
|
10
10
|
- rbx-3
|
11
11
|
services:
|
12
12
|
- mysql
|
@@ -26,7 +26,6 @@ addons:
|
|
26
26
|
key_url: https://packagecloud.io/basho/riak/gpgkey
|
27
27
|
packages:
|
28
28
|
- cassandra
|
29
|
-
- couchdb
|
30
29
|
- libkyotocabinet-dev
|
31
30
|
- libleveldb-dev
|
32
31
|
- liblzo2-dev
|
@@ -36,6 +35,7 @@ addons:
|
|
36
35
|
- riak
|
37
36
|
postgresql: '9.6'
|
38
37
|
before_install:
|
38
|
+
- gem install bundler
|
39
39
|
- script/start-services
|
40
40
|
cache:
|
41
41
|
bundler: true
|
@@ -47,6 +47,10 @@ before_script:
|
|
47
47
|
- psql -c 'create database moneta1;' -U postgres
|
48
48
|
- psql -c 'create extension hstore;' -U postgres moneta1
|
49
49
|
- psql -c 'create database moneta2;' -U postgres
|
50
|
+
# FIXME: remove this once moneta no longer generates hundreds of warnings
|
51
|
+
# in Ruby 2.7
|
52
|
+
- if echo $RUBY_VERSION | grep -q 'ruby-2.7'; then export RUBYOPT='-W0'; fi
|
53
|
+
- export
|
50
54
|
env:
|
51
55
|
matrix:
|
52
56
|
- SCRIPT='script/parallel-tests ~unstable --
|
@@ -120,6 +124,8 @@ matrix:
|
|
120
124
|
- rvm: rbx-3
|
121
125
|
- env: SCRIPT='script/parallel-tests unstable'
|
122
126
|
exclude:
|
127
|
+
- rvm: 2.6
|
128
|
+
env: SCRIPT='rubocop lib'
|
123
129
|
- rvm: 2.5
|
124
130
|
env: SCRIPT='rubocop lib'
|
125
131
|
- rvm: 2.4
|
@@ -128,7 +134,7 @@ matrix:
|
|
128
134
|
env: SCRIPT='rubocop lib'
|
129
135
|
- rvm: 2.2
|
130
136
|
env: SCRIPT='rubocop lib'
|
131
|
-
- rvm: jruby-9.2
|
137
|
+
- rvm: jruby-9.2.9.0
|
132
138
|
env: SCRIPT='rubocop lib'
|
133
139
|
- rvm: rbx-3
|
134
140
|
env: SCRIPT='rubocop lib'
|
data/CHANGES
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
1.3.0
|
2
|
+
|
3
|
+
* Transformer - add :each_key support (#170)
|
4
|
+
* Server - add :each_key support, use non-blocking IO (#165)
|
5
|
+
* Builder - dup options before passing to adapter/proxy (#174)
|
6
|
+
* Adapter::Couch - add HTTP basic auth support
|
7
|
+
* Support MRI 2.7.0 (#172)
|
8
|
+
* Minimum required MRI version is now 2.3.0 (#172)
|
9
|
+
|
1
10
|
1.2.1
|
2
11
|
|
3
12
|
* Transformer - fix :escape transformer deserialize implementation (#168)
|
data/Gemfile
CHANGED
@@ -23,7 +23,7 @@ group :msgpack do
|
|
23
23
|
end
|
24
24
|
|
25
25
|
# Compressors used by Transformer
|
26
|
-
gem 'rbzip2', '
|
26
|
+
gem 'rbzip2', '>= 0.3.0', group: :bzip2
|
27
27
|
gem 'lz4-ruby', platforms: :ruby, group: :lz4
|
28
28
|
gem 'ruby-lzma', platforms: :ruby, group: :lzma
|
29
29
|
gem 'lzoruby', platforms: :ruby, group: :lzo
|
@@ -37,8 +37,8 @@ gem 'cityhash', platforms: :ruby, group: :city
|
|
37
37
|
gem 'daybreak', group: :daybreak
|
38
38
|
gem 'activerecord', '~> 5.2', group: :activerecord
|
39
39
|
gem 'redis', '~> 4.0.0', group: :redis
|
40
|
-
gem 'mongo', '
|
41
|
-
gem 'moped', '>= 2
|
40
|
+
gem 'mongo', '>= 2', group: :mongo_official
|
41
|
+
gem 'moped', '>= 2', group: :mongo_moped
|
42
42
|
gem 'sequel', group: :sequel
|
43
43
|
gem 'dalli', group: :memcached_dalli
|
44
44
|
gem 'riak-client', group: :riak
|
@@ -50,7 +50,7 @@ gem 'tdb', platforms: :ruby, group: :tdb
|
|
50
50
|
gem 'leveldb-ruby', platforms: :ruby, group: :leveldb
|
51
51
|
gem 'lmdb', platforms: :mri, group: :lmdb
|
52
52
|
gem 'tokyocabinet', platforms: :ruby, group: :tokyocabinet
|
53
|
-
gem 'kyotocabinet-ruby-reanimated', platforms: :
|
53
|
+
gem 'kyotocabinet-ruby-reanimated', platforms: [:ruby_23, :ruby_24, :ruby_25, :ruby_26], group: :kyotocabinet
|
54
54
|
gem 'memcached', platforms: :ruby, group: :memcached_native
|
55
55
|
gem 'jruby-memcached', platforms: :jruby, group: :memcached_native
|
56
56
|
gem 'activerecord-jdbch2-adapter', platforms: :jruby, group: :h2, github: 'jruby/activerecord-jdbc-adapter', glob: 'activerecord-jdbch2-adapter/*.gemspec', branch: '52-stable'
|
@@ -94,7 +94,9 @@ end
|
|
94
94
|
|
95
95
|
# Rails integration testing
|
96
96
|
group :rails do
|
97
|
-
|
97
|
+
git 'https://github.com/rails/rails.git', branch: '5-2-stable' do
|
98
|
+
gem 'actionpack'
|
99
|
+
end
|
98
100
|
gem 'minitest', '~> 5.0'
|
99
101
|
end
|
100
102
|
|
data/README.md
CHANGED
@@ -214,7 +214,7 @@ __NOTE:__ <a name="backend-matrix"></a>The backend matrix is much more readable
|
|
214
214
|
|
215
215
|
<tr><th colspan="2">Network clients</th><th colspan="12"></th></tr>
|
216
216
|
|
217
|
-
<tr><td>Client</td><td>-</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#55F">?<sup>13</sup></td><td style="text-align:center;background:#55F">?<sup>13</sup></td><td style="text-align:center;background:#55F">?<sup>13</sup></td><td style="text-align:center;background:#55F">?<sup>13</sup></td><td style="text-align:center;background:#
|
217
|
+
<tr><td>Client</td><td>-</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#55F">?<sup>13</sup></td><td style="text-align:center;background:#55F">?<sup>13</sup></td><td style="text-align:center;background:#55F">?<sup>13</sup></td><td style="text-align:center;background:#55F">?<sup>13</sup></td><td style="text-align:center;background:#55F">?<sup>13</sup></td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#F44">✗</td><td>Moneta client adapter</td></tr>
|
218
218
|
|
219
219
|
<tr><td>RestClient</td><td>-</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#55F">?<sup>13</sup></td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#F44">✗</td><td>Moneta REST client adapter</td></tr>
|
220
220
|
|
@@ -913,12 +913,15 @@ Person.adapter :memory, Moneta.new(:Redis)
|
|
913
913
|
|
914
914
|
## Testing and Benchmarks
|
915
915
|
|
916
|
-
Testing is done using [Travis-CI](http://travis-ci.org/moneta-rb/moneta).
|
916
|
+
Testing is done using [Travis-CI](http://travis-ci.org/moneta-rb/moneta).
|
917
|
+
Currently we support MRI Ruby >= 2.3.0 and the JRuby >= 9.2.9.0.
|
917
918
|
|
918
|
-
Benchmarks for each store are done on
|
919
|
-
|
920
|
-
|
921
|
-
|
919
|
+
Benchmarks for each store are done on
|
920
|
+
[Travis-CI](http://travis-ci.org/moneta-rb/moneta) for each build. Take a look
|
921
|
+
there to compare the speed of the different key value stores for different
|
922
|
+
key/value sizes and size distributions. Feel free to add your own
|
923
|
+
configurations! The impact of Moneta should be minimal since it is only a thin
|
924
|
+
layer on top of the different stores.
|
922
925
|
|
923
926
|
|
924
927
|
------
|
data/feature_matrix.yaml
CHANGED
@@ -220,13 +220,14 @@ backends:
|
|
220
220
|
- adapter: Client
|
221
221
|
platforms: [ MRI, JRuby ]
|
222
222
|
features: [multiprocess]
|
223
|
-
unknown: [ increment, create, expires, persist ]
|
223
|
+
unknown: [ increment, create, expires, persist, each_key ]
|
224
224
|
description: "Moneta client adapter"
|
225
225
|
notes:
|
226
226
|
increment: depends on server
|
227
227
|
create: depends on server
|
228
228
|
expires: depends on server
|
229
229
|
persist: depends on server
|
230
|
+
each_key: depends on server
|
230
231
|
- adapter: RestClient
|
231
232
|
platforms: [ MRI, JRuby ]
|
232
233
|
features: [ multiprocess ]
|
@@ -23,44 +23,44 @@ module Moneta
|
|
23
23
|
# (see Proxy#key?)
|
24
24
|
def key?(key, options = {})
|
25
25
|
write(:key?, key, options)
|
26
|
-
|
26
|
+
read_msg
|
27
27
|
end
|
28
28
|
|
29
29
|
# (see Proxy#load)
|
30
30
|
def load(key, options = {})
|
31
31
|
write(:load, key, options)
|
32
|
-
|
32
|
+
read_msg
|
33
33
|
end
|
34
34
|
|
35
35
|
# (see Proxy#store)
|
36
36
|
def store(key, value, options = {})
|
37
37
|
write(:store, key, value, options)
|
38
|
-
|
38
|
+
read_msg
|
39
39
|
value
|
40
40
|
end
|
41
41
|
|
42
42
|
# (see Proxy#delete)
|
43
43
|
def delete(key, options = {})
|
44
44
|
write(:delete, key, options)
|
45
|
-
|
45
|
+
read_msg
|
46
46
|
end
|
47
47
|
|
48
48
|
# (see Proxy#increment)
|
49
49
|
def increment(key, amount = 1, options = {})
|
50
50
|
write(:increment, key, amount, options)
|
51
|
-
|
51
|
+
read_msg
|
52
52
|
end
|
53
53
|
|
54
54
|
# (see Proxy#create)
|
55
55
|
def create(key, value, options = {})
|
56
56
|
write(:create, key, value, options)
|
57
|
-
|
57
|
+
read_msg
|
58
58
|
end
|
59
59
|
|
60
60
|
# (see Proxy#clear)
|
61
61
|
def clear(options = {})
|
62
62
|
write(:clear, options)
|
63
|
-
|
63
|
+
read_msg
|
64
64
|
self
|
65
65
|
end
|
66
66
|
|
@@ -70,12 +70,43 @@ module Moneta
|
|
70
70
|
nil
|
71
71
|
end
|
72
72
|
|
73
|
+
# (see Proxy#each_key)
|
74
|
+
def each_key
|
75
|
+
raise NotImplementedError, 'each_key is not supported' unless supports?(:each_key)
|
76
|
+
return enum_for(:each_key) unless block_given?
|
77
|
+
|
78
|
+
begin
|
79
|
+
write(:each_key)
|
80
|
+
yield_break = false
|
81
|
+
|
82
|
+
loop do
|
83
|
+
write('NEXT')
|
84
|
+
|
85
|
+
# A StopIteration error will be raised by this call if the server
|
86
|
+
# reached the end of the enumeration. This will stop the loop
|
87
|
+
# automatically.
|
88
|
+
result = read_msg
|
89
|
+
|
90
|
+
# yield_break will be true in the ensure block (below) if anything
|
91
|
+
# happened during the yield to stop further enumeration.
|
92
|
+
yield_break = true
|
93
|
+
yield result
|
94
|
+
yield_break = false
|
95
|
+
end
|
96
|
+
ensure
|
97
|
+
write('BREAK') if yield_break
|
98
|
+
read_msg # nil return from each_key
|
99
|
+
end
|
100
|
+
|
101
|
+
self
|
102
|
+
end
|
103
|
+
|
73
104
|
# (see Default#features)
|
74
105
|
def features
|
75
106
|
@features ||=
|
76
107
|
begin
|
77
108
|
write(:features)
|
78
|
-
|
109
|
+
read_msg.freeze
|
79
110
|
end
|
80
111
|
end
|
81
112
|
|
@@ -86,18 +117,24 @@ module Moneta
|
|
86
117
|
@socket.write([s.bytesize].pack('N') << s)
|
87
118
|
end
|
88
119
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
120
|
+
# JRuby doesn't support socket#recv with flags
|
121
|
+
if defined?(JRUBY_VERSION)
|
122
|
+
def read(bytes)
|
123
|
+
received = @socket.read(bytes)
|
124
|
+
raise EOFError, "Server closed socket" unless received && received.bytesize == bytes
|
125
|
+
received
|
126
|
+
end
|
127
|
+
else
|
128
|
+
def read(bytes)
|
129
|
+
received = @socket.recv(bytes, Socket::MSG_WAITALL)
|
130
|
+
raise EOFError, "Server closed socket" unless received && received.bytesize == bytes
|
131
|
+
received
|
132
|
+
end
|
133
|
+
end
|
100
134
|
|
135
|
+
def read_msg
|
136
|
+
size = read(4).unpack('N').first
|
137
|
+
result = Marshal.load(read(size))
|
101
138
|
raise result if Exception === result
|
102
139
|
result
|
103
140
|
end
|
@@ -39,6 +39,8 @@ module Moneta
|
|
39
39
|
# @option options [String] :scheme ('http') HTTP scheme to use
|
40
40
|
# @option options [String] :value_field ('value') Document field to store value
|
41
41
|
# @option options [String] :type_field ('type') Document field to store value type
|
42
|
+
# @option options [String] :login Login name to use for HTTP basic authentication
|
43
|
+
# @option options [String] :password Password to use for HTTP basic authentication
|
42
44
|
# @option options [Symbol] :adapter Adapter to use with Faraday
|
43
45
|
# @option options [Faraday::Connecton] :backend Use existing backend instance
|
44
46
|
# @option options Other options passed to {Faraday::new} (unless
|
@@ -46,6 +48,8 @@ module Moneta
|
|
46
48
|
def initialize(options = {})
|
47
49
|
@value_field = options.delete(:value_field) || 'value'
|
48
50
|
@type_field = options.delete(:type_field) || 'type'
|
51
|
+
login = options.delete(:login)
|
52
|
+
password = options.delete(:password)
|
49
53
|
@backend = options.delete(:backend) || begin
|
50
54
|
host = options.delete(:host) || '127.0.0.1'
|
51
55
|
port = options.delete(:port) || 5984
|
@@ -56,6 +60,7 @@ module Moneta
|
|
56
60
|
end
|
57
61
|
::Faraday.new("#{scheme}://#{host}:#{port}/#{db}", options, &block)
|
58
62
|
end
|
63
|
+
@backend.basic_auth(login, password) if login && password
|
59
64
|
@rev_cache = Moneta.build do
|
60
65
|
use :Lock
|
61
66
|
adapter :LRUHash
|
@@ -44,7 +44,10 @@ module Moneta
|
|
44
44
|
@backend.use(db)
|
45
45
|
@backend.login(user, password) if user && password
|
46
46
|
@collection = @backend[collection]
|
47
|
-
if @backend.command(buildinfo: 1)['version'] >= '
|
47
|
+
if @backend.command(buildinfo: 1)['version'] >= '3.0'
|
48
|
+
# Moped creates indexes in the system.indexes collection which is not writable anymore since Mongo v3
|
49
|
+
warn 'Moneta::Adapters::MongoMoped - You are using the unmaintained Moped gem, expired documents will not be deleted'
|
50
|
+
elsif @backend.command(buildinfo: 1)['version'] >= '2.2'
|
48
51
|
@collection.indexes.create({ @expires_field => 1 }, expireAfterSeconds: 0)
|
49
52
|
else
|
50
53
|
warn 'Moneta::Adapters::Mongo - You are using MongoDB version < 2.2, expired documents will not be deleted'
|
data/lib/moneta/builder.rb
CHANGED
@@ -17,12 +17,12 @@ module Moneta
|
|
17
17
|
adapter = @proxies.first
|
18
18
|
if Array === adapter
|
19
19
|
klass, options, block = adapter
|
20
|
-
adapter = new_proxy(klass, options, &block)
|
20
|
+
adapter = new_proxy(klass, options.dup, &block)
|
21
21
|
check_arity(klass, adapter, 1)
|
22
22
|
end
|
23
23
|
@proxies[1..-1].inject([adapter]) do |result, proxy|
|
24
24
|
klass, options, block = proxy
|
25
|
-
proxy = new_proxy(klass, result.last, options, &block)
|
25
|
+
proxy = new_proxy(klass, result.last, options.dup, &block)
|
26
26
|
check_arity(klass, proxy, 2)
|
27
27
|
result << proxy
|
28
28
|
end
|
data/lib/moneta/lock.rb
CHANGED
@@ -15,6 +15,7 @@ module Moneta
|
|
15
15
|
protected
|
16
16
|
|
17
17
|
def wrap(name, *args, &block)
|
18
|
+
self.locks ||= Set.new
|
18
19
|
if locked?
|
19
20
|
yield
|
20
21
|
else
|
@@ -22,8 +23,12 @@ module Moneta
|
|
22
23
|
end
|
23
24
|
end
|
24
25
|
|
26
|
+
def locks=(locks)
|
27
|
+
Thread.current.thread_variable_set('Moneta::Lock', locks)
|
28
|
+
end
|
29
|
+
|
25
30
|
def locks
|
26
|
-
Thread.current
|
31
|
+
Thread.current.thread_variable_get('Moneta::Lock')
|
27
32
|
end
|
28
33
|
|
29
34
|
def lock!(&block)
|
data/lib/moneta/pool.rb
CHANGED
@@ -298,6 +298,18 @@ module Moneta
|
|
298
298
|
# by the manager after the ttl
|
299
299
|
def close; end
|
300
300
|
|
301
|
+
def each_key(&block)
|
302
|
+
wrap(:each_key) do
|
303
|
+
raise NotImplementedError, "each_key is not supported on this proxy" \
|
304
|
+
unless supports? :each_key
|
305
|
+
|
306
|
+
return enum_for(:each_key) { adapter ? adapter.each_key.size : check_out! { adapter.each_key.size } } unless block_given?
|
307
|
+
|
308
|
+
adapter.each_key(&block)
|
309
|
+
self
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
301
313
|
# Tells the manager to close all stores. It will not be possible to use
|
302
314
|
# the store after this.
|
303
315
|
def stop
|
data/lib/moneta/proxy.rb
CHANGED
@@ -22,7 +22,7 @@ module Moneta
|
|
22
22
|
raise NotImplementedError, "each_key is not supported on this proxy" \
|
23
23
|
unless supports? :each_key
|
24
24
|
|
25
|
-
return enum_for(:each_key) unless block_given?
|
25
|
+
return enum_for(:each_key) { adapter.each_key.size } unless block_given?
|
26
26
|
adapter.each_key(&block)
|
27
27
|
self
|
28
28
|
end
|
data/lib/moneta/server.rb
CHANGED
@@ -4,6 +4,154 @@ module Moneta
|
|
4
4
|
# Moneta server to be used together with Moneta::Adapters::Client
|
5
5
|
# @api public
|
6
6
|
class Server
|
7
|
+
TIMEOUT = 1
|
8
|
+
MAXSIZE = 0x100000
|
9
|
+
|
10
|
+
# @api private
|
11
|
+
class Connection
|
12
|
+
def initialize(io, store)
|
13
|
+
@io = io
|
14
|
+
@store = store
|
15
|
+
@fiber = Fiber.new { run }
|
16
|
+
end
|
17
|
+
|
18
|
+
def resume(result = nil)
|
19
|
+
@fiber.resume result
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
# The return value of this function will be sent to the reactor.
|
25
|
+
#
|
26
|
+
# @return [:closed,Exception]
|
27
|
+
def run
|
28
|
+
catch :closed do
|
29
|
+
loop { write_dispatch(read_msg) }
|
30
|
+
end
|
31
|
+
:closed
|
32
|
+
rescue => ex
|
33
|
+
ex
|
34
|
+
ensure
|
35
|
+
@io.close unless @io.closed?
|
36
|
+
end
|
37
|
+
|
38
|
+
def dispatch(method, args)
|
39
|
+
case method
|
40
|
+
when :key?, :load, :delete, :increment, :create, :features
|
41
|
+
@store.public_send(method, *args)
|
42
|
+
when :store, :clear
|
43
|
+
@store.public_send(method, *args)
|
44
|
+
nil
|
45
|
+
when :each_key
|
46
|
+
yield_each(@store.each_key)
|
47
|
+
nil
|
48
|
+
end
|
49
|
+
rescue => ex
|
50
|
+
ex
|
51
|
+
end
|
52
|
+
|
53
|
+
def write_dispatch(msg)
|
54
|
+
method, *args = msg
|
55
|
+
result = dispatch(method, args)
|
56
|
+
write(result)
|
57
|
+
end
|
58
|
+
|
59
|
+
def read_msg
|
60
|
+
size = read(4).unpack('N').first
|
61
|
+
throw :closed, 'Message too big' if size > MAXSIZE
|
62
|
+
Marshal.load(read(size))
|
63
|
+
end
|
64
|
+
|
65
|
+
def read(len)
|
66
|
+
buffer = ''
|
67
|
+
loop do
|
68
|
+
begin
|
69
|
+
case received = @io.recv_nonblock(len)
|
70
|
+
when '', nil
|
71
|
+
throw :closed, 'Closed during read'
|
72
|
+
else
|
73
|
+
buffer << received
|
74
|
+
len -= received.bytesize
|
75
|
+
end
|
76
|
+
rescue IO::WaitReadable, IO::WaitWritable
|
77
|
+
yield_to_reactor(:read)
|
78
|
+
rescue Errno::ECONNRESET
|
79
|
+
throw :closed, 'Closed during read'
|
80
|
+
rescue IOError => ex
|
81
|
+
if ex.message =~ /closed stream/
|
82
|
+
throw :closed, 'Closed during read'
|
83
|
+
else
|
84
|
+
raise
|
85
|
+
end
|
86
|
+
end
|
87
|
+
break if len == 0
|
88
|
+
end
|
89
|
+
buffer
|
90
|
+
end
|
91
|
+
|
92
|
+
def write(obj)
|
93
|
+
buffer = pack(obj)
|
94
|
+
until buffer.empty?
|
95
|
+
begin
|
96
|
+
len = sendmsg(buffer)
|
97
|
+
buffer = buffer.byteslice(len...buffer.length)
|
98
|
+
rescue IO::WaitWritable, Errno::EINTR
|
99
|
+
yield_to_reactor(:write)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
nil
|
103
|
+
end
|
104
|
+
|
105
|
+
# Detect support for socket#sendmsg_nonblock
|
106
|
+
Socket.new(Socket::AF_INET, Socket::SOCK_STREAM).tap do |socket|
|
107
|
+
begin
|
108
|
+
socket.sendmsg_nonblock('probe')
|
109
|
+
rescue Errno::EPIPE, Errno::ENOTCONN
|
110
|
+
def sendmsg(msg)
|
111
|
+
@io.sendmsg_nonblock(msg)
|
112
|
+
end
|
113
|
+
rescue NotImplementedError
|
114
|
+
def sendmsg(msg)
|
115
|
+
@io.write_nonblock(msg)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def yield_to_reactor(mode = :read)
|
121
|
+
if Fiber.yield(mode) == :close
|
122
|
+
throw :closed, 'Closed by reactor'
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def pack(obj)
|
127
|
+
s = Marshal.dump(obj)
|
128
|
+
[s.bytesize].pack('N') << s
|
129
|
+
end
|
130
|
+
|
131
|
+
def yield_each(enumerator)
|
132
|
+
received_break = false
|
133
|
+
loop do
|
134
|
+
case msg = read_msg
|
135
|
+
when %w{NEXT}
|
136
|
+
# This will raise a StopIteration at the end of the enumeration,
|
137
|
+
# which will exit the loop.
|
138
|
+
write(enumerator.next)
|
139
|
+
when %w{BREAK}
|
140
|
+
# This is received when the client wants to stop the enumeration.
|
141
|
+
received_break = true
|
142
|
+
break
|
143
|
+
else
|
144
|
+
# Otherwise, the client is attempting to call another method within
|
145
|
+
# an `each` block.
|
146
|
+
write_dispatch(msg)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
ensure
|
150
|
+
# This tells the client to stop enumerating
|
151
|
+
write(StopIteration.new("Server initiated stop")) unless received_break
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
7
155
|
# @param [Hash] options
|
8
156
|
# @option options [Integer] :port (9000) TCP port
|
9
157
|
# @option options [String] :socket Alternative Unix socket file name
|
@@ -11,7 +159,9 @@ module Moneta
|
|
11
159
|
@store = store
|
12
160
|
@server = start(options)
|
13
161
|
@ios = [@server]
|
14
|
-
@
|
162
|
+
@reads = @ios.dup
|
163
|
+
@writes = []
|
164
|
+
@connections = {}
|
15
165
|
@running = false
|
16
166
|
end
|
17
167
|
|
@@ -26,94 +176,89 @@ module Moneta
|
|
26
176
|
#
|
27
177
|
# @note This method blocks!
|
28
178
|
def run
|
29
|
-
raise 'Already running' if
|
179
|
+
raise 'Already running' if running?
|
30
180
|
@stop = false
|
31
181
|
@running = true
|
32
182
|
begin
|
33
183
|
mainloop until @stop
|
34
184
|
ensure
|
35
|
-
|
36
|
-
@
|
185
|
+
@running = false
|
186
|
+
@server.close unless @server.closed?
|
187
|
+
@ios
|
188
|
+
.reject { |io| io == @server }
|
189
|
+
.each { |io| close_connection(io) }
|
190
|
+
File.unlink(@socket) if @socket rescue nil
|
37
191
|
end
|
38
192
|
end
|
39
193
|
|
40
194
|
# Stop the server
|
41
195
|
def stop
|
42
|
-
raise 'Not running' unless
|
196
|
+
raise 'Not running' unless running?
|
43
197
|
@stop = true
|
44
198
|
@server.close
|
45
|
-
|
199
|
+
nil
|
46
200
|
end
|
47
201
|
|
48
202
|
private
|
49
203
|
|
50
|
-
TIMEOUT = 1
|
51
|
-
MAXSIZE = 0x100000
|
52
|
-
|
53
204
|
def mainloop
|
54
|
-
if
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
if client = @server.accept
|
62
|
-
@ios << client
|
63
|
-
@clients[client] = ''
|
64
|
-
end
|
65
|
-
elsif io.closed? || io.eof?
|
66
|
-
delete_client(io)
|
67
|
-
else
|
68
|
-
handle(io, @clients[io] << io.readpartial(0xFFFF))
|
69
|
-
end
|
205
|
+
if ready = IO.select(@reads, @writes, @ios, TIMEOUT)
|
206
|
+
reads, writes, errors = ready
|
207
|
+
errors.each { |io| close_connection(io) }
|
208
|
+
|
209
|
+
@reads -= reads
|
210
|
+
reads.each do |io|
|
211
|
+
io == @server ? accept_connection : resume(io)
|
70
212
|
end
|
213
|
+
|
214
|
+
@writes -= writes
|
215
|
+
writes.each { |io| resume(io) }
|
71
216
|
end
|
72
|
-
rescue SignalException =>
|
73
|
-
warn "Moneta::Server - #{
|
74
|
-
|
75
|
-
|
217
|
+
rescue SignalException => signal
|
218
|
+
warn "Moneta::Server - received #{signal}"
|
219
|
+
case signal.signo
|
220
|
+
when Signal.list['INT'], Signal.list['TERM']
|
221
|
+
@stop = true # graceful exit
|
222
|
+
end
|
223
|
+
rescue IOError => ex
|
224
|
+
# We get a lot of these "closed stream" errors, which we ignore
|
225
|
+
raise unless ex.message =~ /closed stream/
|
226
|
+
rescue Errno::EBADF => ex
|
76
227
|
warn "Moneta::Server - #{ex.message}"
|
77
228
|
end
|
78
229
|
|
79
|
-
def
|
230
|
+
def accept_connection
|
231
|
+
io = @server.accept
|
232
|
+
@connections[io] = Connection.new(io, @store)
|
233
|
+
@ios << io
|
234
|
+
resume(io)
|
235
|
+
ensure
|
236
|
+
@reads << @server
|
237
|
+
end
|
238
|
+
|
239
|
+
def delete_connection(io)
|
80
240
|
@ios.delete(io)
|
81
|
-
@
|
241
|
+
@reads.delete(io)
|
242
|
+
@writes.delete(io)
|
82
243
|
end
|
83
244
|
|
84
|
-
def
|
85
|
-
|
86
|
-
|
245
|
+
def close_connection(io)
|
246
|
+
delete_connection(io)
|
247
|
+
@connections.delete(io).resume(:close)
|
87
248
|
end
|
88
249
|
|
89
|
-
def
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
when :key?, :load, :delete, :increment, :create
|
101
|
-
io.write(pack(@store.send(method, *args)))
|
102
|
-
when :features
|
103
|
-
# all features except each_key are supported
|
104
|
-
io.write(pack(@store.features - [:each_key]))
|
105
|
-
when :store, :clear
|
106
|
-
@store.send(method, *args)
|
107
|
-
io.write(@nil ||= pack(nil))
|
108
|
-
else
|
109
|
-
raise 'Invalid method call'
|
250
|
+
def resume(io)
|
251
|
+
case result = @connections[io].resume
|
252
|
+
when :closed # graceful exit
|
253
|
+
delete_connection(io)
|
254
|
+
when Exception # messy exit
|
255
|
+
delete_connection(io)
|
256
|
+
raise result
|
257
|
+
when :read
|
258
|
+
@reads << io
|
259
|
+
when :write
|
260
|
+
@writes << io
|
110
261
|
end
|
111
|
-
rescue IOError => ex
|
112
|
-
warn "Moneta::Server - #{ex.message}" unless ex.message =~ /closed/
|
113
|
-
delete_client(io)
|
114
|
-
rescue => ex
|
115
|
-
warn "Moneta::Server - #{ex.message}"
|
116
|
-
io.write(pack(Exception.new(ex.message)))
|
117
262
|
end
|
118
263
|
|
119
264
|
def start(options)
|
@@ -133,5 +278,14 @@ module Moneta
|
|
133
278
|
TCPServer.open(options[:host] || '127.0.0.1', options[:port] || 9000)
|
134
279
|
end
|
135
280
|
end
|
281
|
+
|
282
|
+
def stats
|
283
|
+
{
|
284
|
+
connections: @connections.length,
|
285
|
+
reading: @reads.length,
|
286
|
+
writing: @writes.length,
|
287
|
+
total: @ios.length
|
288
|
+
}
|
289
|
+
end
|
136
290
|
end
|
137
291
|
end
|