moneta 0.7.17 → 0.7.18
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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +15 -9
- data/CHANGES +12 -1
- data/CONTRIBUTORS +2 -2
- data/Gemfile +3 -0
- data/README.md +30 -5
- data/Rakefile +1 -1
- data/lib/active_support/cache/moneta_store.rb +5 -2
- data/lib/moneta/adapters/couch.rb +63 -5
- data/lib/moneta/adapters/file.rb +29 -12
- data/lib/moneta/adapters/fog.rb +1 -0
- data/lib/moneta/adapters/mongo.rb +74 -22
- data/lib/moneta/adapters/sqlite.rb +6 -5
- data/lib/moneta/pool.rb +28 -5
- data/lib/moneta/transformer/config.rb +37 -34
- data/lib/moneta/version.rb +1 -1
- data/script/contributors +7 -0
- data/script/generate-specs +89 -30
- data/script/install-bundle +1 -1
- data/script/start-services +6 -12
- data/script/wait-services +15 -0
- data/spec/active_support/cache_moneta_store_spec.rb +3 -3
- data/spec/moneta/adapter_couch_spec.rb +14 -6
- data/spec/moneta/adapter_memory_spec.rb +29 -0
- data/spec/moneta/adapter_mongo_spec.rb +7 -0
- data/spec/moneta/adapter_mongo_with_default_expires_spec.rb +7 -0
- data/spec/moneta/adapter_pstore_spec.rb +42 -0
- data/spec/moneta/expires_file_spec.rb +4 -0
- data/spec/moneta/expires_memory_spec.rb +29 -0
- data/spec/moneta/expires_memory_with_default_expires_spec.rb +29 -0
- data/spec/moneta/lock_spec.rb +29 -0
- data/spec/moneta/null_adapter_spec.rb +13 -0
- data/spec/moneta/proxy_expires_memory_spec.rb +29 -0
- data/spec/moneta/simple_activerecord_spec.rb +42 -0
- data/spec/moneta/simple_activerecord_with_expires_spec.rb +42 -0
- data/spec/moneta/simple_cassandra_spec.rb +42 -0
- data/spec/moneta/simple_client_tcp_spec.rb +42 -0
- data/spec/moneta/simple_client_unix_spec.rb +42 -0
- data/spec/moneta/simple_couch_spec.rb +45 -2
- data/spec/moneta/simple_couch_with_expires_spec.rb +46 -2
- data/spec/moneta/simple_datamapper_spec.rb +42 -0
- data/spec/moneta/simple_datamapper_with_expires_spec.rb +42 -0
- data/spec/moneta/simple_datamapper_with_repository_spec.rb +42 -0
- data/spec/moneta/simple_daybreak_spec.rb +42 -0
- data/spec/moneta/simple_daybreak_with_expires_spec.rb +42 -0
- data/spec/moneta/simple_dbm_spec.rb +42 -0
- data/spec/moneta/simple_dbm_with_expires_spec.rb +42 -0
- data/spec/moneta/simple_file_spec.rb +42 -0
- data/spec/moneta/simple_file_with_expires_spec.rb +42 -0
- data/spec/moneta/simple_fog_spec.rb +42 -0
- data/spec/moneta/simple_fog_with_expires_spec.rb +42 -0
- data/spec/moneta/simple_gdbm_spec.rb +42 -0
- data/spec/moneta/simple_gdbm_with_expires_spec.rb +42 -0
- data/spec/moneta/simple_hashfile_spec.rb +42 -0
- data/spec/moneta/simple_hashfile_with_expires_spec.rb +42 -0
- data/spec/moneta/simple_hbase_spec.rb +42 -0
- data/spec/moneta/simple_hbase_with_expires_spec.rb +42 -0
- data/spec/moneta/simple_kyotocabinet_spec.rb +42 -0
- data/spec/moneta/simple_kyotocabinet_with_expires_spec.rb +42 -0
- data/spec/moneta/simple_leveldb_spec.rb +42 -0
- data/spec/moneta/simple_leveldb_with_expires_spec.rb +42 -0
- data/spec/moneta/simple_localmemcache_spec.rb +42 -0
- data/spec/moneta/simple_localmemcache_with_expires_spec.rb +42 -0
- data/spec/moneta/simple_lruhash_spec.rb +29 -0
- data/spec/moneta/simple_lruhash_with_expires_spec.rb +29 -0
- data/spec/moneta/simple_memcached_dalli_spec.rb +42 -0
- data/spec/moneta/simple_memcached_native_spec.rb +42 -0
- data/spec/moneta/simple_memcached_spec.rb +42 -0
- data/spec/moneta/simple_memory_spec.rb +29 -0
- data/spec/moneta/simple_memory_with_compress_spec.rb +29 -0
- data/spec/moneta/simple_memory_with_expires_spec.rb +29 -0
- data/spec/moneta/simple_memory_with_json_key_serializer_spec.rb +6 -0
- data/spec/moneta/simple_memory_with_json_value_serializer_spec.rb +8 -0
- data/spec/moneta/simple_memory_with_prefix_spec.rb +29 -0
- data/spec/moneta/simple_memory_with_snappy_compress_spec.rb +29 -0
- data/spec/moneta/simple_mongo_spec.rb +42 -0
- data/spec/moneta/simple_null_spec.rb +16 -0
- data/spec/moneta/simple_pstore_spec.rb +42 -0
- data/spec/moneta/simple_pstore_with_expires_spec.rb +42 -0
- data/spec/moneta/simple_redis_spec.rb +42 -0
- data/spec/moneta/simple_restclient_spec.rb +42 -0
- data/spec/moneta/simple_riak_spec.rb +42 -0
- data/spec/moneta/simple_riak_with_expires_spec.rb +42 -0
- data/spec/moneta/simple_sdbm_spec.rb +42 -0
- data/spec/moneta/simple_sdbm_with_expires_spec.rb +42 -0
- data/spec/moneta/simple_sequel_spec.rb +42 -0
- data/spec/moneta/simple_sequel_with_expires_spec.rb +42 -0
- data/spec/moneta/simple_sqlite_spec.rb +42 -0
- data/spec/moneta/simple_sqlite_with_expires_spec.rb +42 -0
- data/spec/moneta/simple_tdb_spec.rb +42 -0
- data/spec/moneta/simple_tdb_with_expires_spec.rb +42 -0
- data/spec/moneta/simple_tokyocabinet_spec.rb +42 -0
- data/spec/moneta/simple_tokyocabinet_with_expires_spec.rb +42 -0
- data/spec/moneta/simple_tokyotyrant_spec.rb +42 -0
- data/spec/moneta/simple_tokyotyrant_with_expires_spec.rb +42 -0
- data/spec/moneta/simple_yaml_spec.rb +42 -0
- data/spec/moneta/simple_yaml_with_expires_spec.rb +42 -0
- data/spec/moneta/transformer_bzip2_spec.rb +3 -0
- data/spec/moneta/transformer_key_inspect_spec.rb +6 -0
- data/spec/moneta/transformer_key_marshal_spec.rb +29 -0
- data/spec/moneta/transformer_key_to_s_spec.rb +6 -0
- data/spec/moneta/transformer_key_yaml_spec.rb +29 -0
- data/spec/moneta/transformer_lz4_spec.rb +3 -0
- data/spec/moneta/transformer_lzma_spec.rb +3 -0
- data/spec/moneta/transformer_lzo_spec.rb +3 -0
- data/spec/moneta/transformer_marshal_base64_spec.rb +29 -0
- data/spec/moneta/transformer_marshal_city128_spec.rb +152 -0
- data/spec/moneta/transformer_marshal_city32_spec.rb +152 -0
- data/spec/moneta/transformer_marshal_city64_spec.rb +152 -0
- data/spec/moneta/transformer_marshal_escape_spec.rb +29 -0
- data/spec/moneta/transformer_marshal_hmac_spec.rb +29 -0
- data/spec/moneta/transformer_marshal_md5_spec.rb +29 -0
- data/spec/moneta/transformer_marshal_md5_spread_spec.rb +29 -0
- data/spec/moneta/transformer_marshal_prefix_spec.rb +29 -0
- data/spec/moneta/transformer_marshal_qp_spec.rb +29 -0
- data/spec/moneta/transformer_marshal_rmd160_spec.rb +29 -0
- data/spec/moneta/transformer_marshal_sha1_spec.rb +29 -0
- data/spec/moneta/transformer_marshal_sha256_spec.rb +29 -0
- data/spec/moneta/transformer_marshal_sha384_spec.rb +29 -0
- data/spec/moneta/transformer_marshal_sha512_spec.rb +29 -0
- data/spec/moneta/transformer_marshal_spec.rb +29 -0
- data/spec/moneta/transformer_marshal_truncate_spec.rb +29 -0
- data/spec/moneta/transformer_marshal_uuencode_spec.rb +29 -0
- data/spec/moneta/transformer_ox_spec.rb +29 -0
- data/spec/moneta/transformer_quicklz_spec.rb +3 -0
- data/spec/moneta/transformer_snappy_spec.rb +3 -0
- data/spec/moneta/transformer_value_marshal_spec.rb +29 -0
- data/spec/moneta/transformer_value_yaml_spec.rb +29 -0
- data/spec/moneta/transformer_yaml_spec.rb +29 -0
- data/spec/moneta/transformer_zlib_spec.rb +3 -0
- data/spec/moneta/weak_create_spec.rb +2 -1
- data/spec/moneta/weak_increment_spec.rb +2 -1
- data/spec/monetaspecs.rb +29879 -6167
- metadata +10 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 40e5bf4f97796468cef521c2b103f72d7be29811
|
|
4
|
+
data.tar.gz: d9ab4368e38146049f4e92a0cf2337b2148fcf10
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2fadbaee29f91f2259b44cf7140d64e3ab12196ee2e29c6c9ccc5db2518b0a06a4db0d81f654e7625dceaa3ead6a7636aeb2240d9cff0bd17161b2f1865a6f19
|
|
7
|
+
data.tar.gz: f1751faff2cef9302fa0b3125e421e6632fa580978ab548fb13afd53f7dc37fe0e586821a657b3c79298a44b9ba66ccf68edacbf6efcc89e3b134176dfa2b7c9
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
|
@@ -5,15 +5,16 @@ rvm:
|
|
|
5
5
|
- 1.8.7
|
|
6
6
|
- jruby-19mode
|
|
7
7
|
- jruby-18mode
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
- rbx-19mode
|
|
9
|
+
- rbx-18mode
|
|
10
10
|
before_install:
|
|
11
11
|
- script/kill-travis
|
|
12
12
|
#- script/install-kyotocabinet
|
|
13
|
-
- sudo apt-get install -qq libtokyocabinet8 libtokyocabinet-dev liblzo2-dev libtdb-dev tokyotyrant
|
|
13
|
+
- sudo apt-get install -qq libtokyocabinet8 libtokyocabinet-dev liblzo2-dev libtdb-dev libleveldb-dev tokyotyrant
|
|
14
14
|
- script/start-services
|
|
15
15
|
- script/install-bundle
|
|
16
16
|
- script/upload-bundle
|
|
17
|
+
- script/wait-services
|
|
17
18
|
install: 'echo "Bundle installed"'
|
|
18
19
|
before_script:
|
|
19
20
|
- mysql -e 'create database moneta;'
|
|
@@ -21,13 +22,18 @@ before_script:
|
|
|
21
22
|
- mysql -e 'create database moneta_activerecord2;'
|
|
22
23
|
env:
|
|
23
24
|
global:
|
|
24
|
-
- secure: "
|
|
25
|
+
- secure: "dtM4n7FP8P0UI9Iq+nsvQ7/yfDqsxhfCO9i8zMxm/f9Kxj5Z/4C7jsXsLA+e\n/7FZ9+ld2QjPSPU0LUiDpj/z81bxyZHwqocQ7Nb0DVvO3JRHpr4/iBQQQHd3\n0jvou3mRbu5mBlUjf1/ALaZA+b+vcnsF9fd86UnkY+ChriylGnM="
|
|
25
26
|
matrix:
|
|
26
|
-
- "TASK=test TEST_GROUP=1/
|
|
27
|
-
- "TASK=test TEST_GROUP=2/
|
|
28
|
-
- "TASK=test TEST_GROUP=3/
|
|
29
|
-
- "TASK=test TEST_GROUP=4/
|
|
30
|
-
- "TASK=test TEST_GROUP=5/
|
|
27
|
+
- "TASK=test TEST_GROUP=1/10"
|
|
28
|
+
- "TASK=test TEST_GROUP=2/10"
|
|
29
|
+
- "TASK=test TEST_GROUP=3/10"
|
|
30
|
+
- "TASK=test TEST_GROUP=4/10"
|
|
31
|
+
- "TASK=test TEST_GROUP=5/10"
|
|
32
|
+
- "TASK=test TEST_GROUP=6/10"
|
|
33
|
+
- "TASK=test TEST_GROUP=7/10"
|
|
34
|
+
- "TASK=test TEST_GROUP=8/10"
|
|
35
|
+
- "TASK=test TEST_GROUP=9/10"
|
|
36
|
+
- "TASK=test TEST_GROUP=10/10"
|
|
31
37
|
- "TASK=test TEST_GROUP=unstable"
|
|
32
38
|
- "TASK=benchmarks CONFIG=uniform_small"
|
|
33
39
|
- "TASK=benchmarks CONFIG=uniform_medium"
|
data/CHANGES
CHANGED
|
@@ -1,4 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
0.7.18
|
|
2
|
+
|
|
3
|
+
* Adapters::File#increment and #create fixed on JRuby
|
|
4
|
+
* Adapters::Couch and Adapters::Mongo can store hashes directly as documents.
|
|
5
|
+
It is not necessary to serialize values as strings anymore.
|
|
6
|
+
* Adapters::Couch#create added
|
|
7
|
+
* Pool thread safety improved
|
|
8
|
+
* Transformer: Add CityHash
|
|
9
|
+
|
|
10
|
+
0.7.17
|
|
11
|
+
|
|
12
|
+
* Transformer: LZ4 compression added
|
|
2
13
|
|
|
3
14
|
0.7.16
|
|
4
15
|
|
data/CONTRIBUTORS
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
Adrian Madrid <aemadrid@gmail.com>
|
|
2
2
|
Alejandro Crosa <acrosa@sharing.local>
|
|
3
3
|
Anthony Eden <anthonyeden@gmail.com>
|
|
4
|
-
Hendrik Beskow <hendrik-github@beskow.de>
|
|
5
4
|
Benjamin Yu <benjaminlyu@gmail.com>
|
|
6
5
|
Ben Schwarz <ben.schwarz@gmail.com>
|
|
7
6
|
Daniel Mendler <mail@daniel-mendler.de>
|
|
@@ -9,7 +8,7 @@ Derek Kastner <dkastner@gmail.com>
|
|
|
9
8
|
Dylan Egan <me@dylanegan.com>
|
|
10
9
|
Hampton Catlin <hcatlin@gmail.com>
|
|
11
10
|
Hannes Georg <hannes.georg@googlemail.com>
|
|
12
|
-
|
|
11
|
+
Hendrik Beskow <hendrik-github@beskow.de>
|
|
13
12
|
Jari Bakken <jari.bakken@gmail.com>
|
|
14
13
|
Jeremy Voorhis <jvoorhis@gmail.com>
|
|
15
14
|
Jon Crosby <jon@joncrosby.me>
|
|
@@ -17,6 +16,7 @@ lakshan <lakshan@web2media.net>
|
|
|
17
16
|
Piotr Murach <pmurach@gmail.com>
|
|
18
17
|
Potapov Sergey <blake131313@gmail.com>
|
|
19
18
|
Quin Hoxie <quin@aboutus.org>
|
|
19
|
+
Scott Wadden <scott.wadden@gmail.com>
|
|
20
20
|
Tom Meier <ozmeier@yahoo.co.uk>
|
|
21
21
|
Xavier Shay <xavier@rhnh.net>
|
|
22
22
|
Yehuda Katz <wycats@gmail.com>
|
data/Gemfile
CHANGED
data/README.md
CHANGED
|
@@ -2,7 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
[](http://rubygems.org/gems/moneta) [](http://travis-ci.org/minad/moneta) [](https://gemnasium.com/minad/moneta) [](https://codeclimate.com/github/minad/moneta)
|
|
4
4
|
|
|
5
|
-
Moneta provides a standard interface for interacting with various kinds of key/value stores.
|
|
5
|
+
Moneta provides a standard interface for interacting with various kinds of key/value stores. Moneta supports the well-known
|
|
6
|
+
NoSQL and document based stores.
|
|
7
|
+
|
|
8
|
+
A short overview of the features:
|
|
6
9
|
|
|
7
10
|
* Supports a lot of backends with consistent behaviour (See below)
|
|
8
11
|
* Allows a full configuration of the serialization -> compression -> adapter stack using proxies (Similar to [Rack middlewares](http://rack.github.com/))
|
|
@@ -170,14 +173,14 @@ __NOTE:__ <a name="backend-matrix">The backend matrix</a> is much more readable
|
|
|
170
173
|
|
|
171
174
|
<tr><td>DataMapper</td><td>dm-core, dm-migrations</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:#5F5">✓</td><td><a href="http://datamapper.org/">DataMapper</a> ORM</td></tr>
|
|
172
175
|
|
|
176
|
+
<tr><td>Couch</td><td>faraday, multi_json</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:#5F5">✓</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td><a href="http://couchdb.apache.org/">CouchDB</a> database</td></tr>
|
|
177
|
+
|
|
173
178
|
<tr><td>HBase</td><td>hbaserb</td><td style="text-align:center;background:#55F">?</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:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td><a href="http://hbase.apache.org/">HBase</a> database</td></tr>
|
|
174
179
|
|
|
175
180
|
<tr><td>Cassandra</td><td>cassandra</td><td style="text-align:center;background:#55F">?</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:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td><a href="http://cassandra.apache.org/">Cassandra</a> distributed database</td></tr>
|
|
176
181
|
|
|
177
182
|
<tr><td>LocalMemCache</td><td>localmemcache</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:#F44">✗</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td><a href="http://localmemcache.rubyforge.org/">LocalMemCache</a> database</td></tr>
|
|
178
183
|
|
|
179
|
-
<tr><td>Couch</td><td>faraday, multi_json</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:#5F5">✓</td><td><a href="http://couchdb.apache.org/">CouchDB</a> database</td></tr>
|
|
180
|
-
|
|
181
184
|
<tr><td>Fog</td><td>fog</td><td style="text-align:center;background:#55F">?</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:#5F5">✓</td><td><a href="http://fog.io/">Fog</a> cloud store</td></tr>
|
|
182
185
|
|
|
183
186
|
<tr><td>Riak</td><td>riak-client</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:#5F5">✓</td><td><a href="http://docs.basho.com/">Riak</a> database</td></tr>
|
|
@@ -258,7 +261,7 @@ Supported value compressors:
|
|
|
258
261
|
|
|
259
262
|
Special transformers:
|
|
260
263
|
|
|
261
|
-
* Digests (MD5, Shas, ...)
|
|
264
|
+
* Digests (MD5, Shas, CityHash, ...)
|
|
262
265
|
* Add prefix to keys (`:prefix`)
|
|
263
266
|
* HMAC to verify values (`:hmac`, useful for `Rack::MonetaCookies`)
|
|
264
267
|
|
|
@@ -312,10 +315,16 @@ Moneta does not support iteration or partial matches.
|
|
|
312
315
|
|
|
313
316
|
### Creating a Store
|
|
314
317
|
|
|
315
|
-
There is a simple interface to create a store using `Moneta.new
|
|
318
|
+
There is a simple interface to create a store using `Moneta.new`. You will
|
|
319
|
+
get automatic key and value serialization which is provided by `Moneta::Transformer`.
|
|
320
|
+
This allows you to store arbitrary Ruby objects. You can tune some options
|
|
321
|
+
when you call `Moneta.new`. However for very fine tuning use `Moneta.build`.
|
|
316
322
|
|
|
317
323
|
~~~ ruby
|
|
318
324
|
store = Moneta.new(:Memcached, :server => 'localhost:11211')
|
|
325
|
+
store['key'] = 'value'
|
|
326
|
+
store['hash_key'] = {:a => 1, :b => 2}
|
|
327
|
+
store['object_key'] = MarshallableRubyObject.new
|
|
319
328
|
~~~
|
|
320
329
|
|
|
321
330
|
If you want to have control over the proxies, you have to use `Moneta.build`:
|
|
@@ -335,6 +344,22 @@ store = Moneta.build do
|
|
|
335
344
|
end
|
|
336
345
|
~~~
|
|
337
346
|
|
|
347
|
+
You can also directly access the underlying adapters if you don't want
|
|
348
|
+
to use the Moneta stack.
|
|
349
|
+
|
|
350
|
+
~~~ ruby
|
|
351
|
+
db = Moneta::Adapters::File.new(:dir => 'directory')
|
|
352
|
+
db['key'] = {:a => 1, :b => 2} # This will fail since you can only store Strings
|
|
353
|
+
|
|
354
|
+
# However for Mongo and Couch this works
|
|
355
|
+
# The hash will be mapped directly to a Mongo/Couch document.
|
|
356
|
+
db = Moneta::Adapters::Couch.new
|
|
357
|
+
db['key'] = {:a => 1, :b => 2}
|
|
358
|
+
|
|
359
|
+
db = Moneta::Adapters::Mongo.new
|
|
360
|
+
db['key'] = {:a => 1, :b => 2}
|
|
361
|
+
~~~
|
|
362
|
+
|
|
338
363
|
### Expiration
|
|
339
364
|
|
|
340
365
|
The Cassandra, Memcached, Redis and Mongo backends support expiration natively.
|
data/Rakefile
CHANGED
|
@@ -10,18 +10,21 @@ module ActiveSupport
|
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
def increment(key, amount = 1, options = nil)
|
|
13
|
+
options = merged_options(options)
|
|
13
14
|
instrument(:increment, key, :amount => amount) do
|
|
14
|
-
@store.increment(key, amount, moneta_options(options))
|
|
15
|
+
@store.increment(namespaced_key(key, options), amount, moneta_options(options))
|
|
15
16
|
end
|
|
16
17
|
end
|
|
17
18
|
|
|
18
19
|
def decrement(key, amount = 1, options = nil)
|
|
20
|
+
options = merged_options(options)
|
|
19
21
|
instrument(:decrement, key, :amount => amount) do
|
|
20
|
-
@store.increment(key, -amount, moneta_options(options))
|
|
22
|
+
@store.increment(namespaced_key(key, options), -amount, moneta_options(options))
|
|
21
23
|
end
|
|
22
24
|
end
|
|
23
25
|
|
|
24
26
|
def clear(options = nil)
|
|
27
|
+
options = merged_options(options)
|
|
25
28
|
instrument(:clear, nil, nil) do
|
|
26
29
|
@store.clear(moneta_options(options))
|
|
27
30
|
end
|
|
@@ -4,18 +4,31 @@ require 'multi_json'
|
|
|
4
4
|
module Moneta
|
|
5
5
|
module Adapters
|
|
6
6
|
# CouchDB backend
|
|
7
|
+
#
|
|
8
|
+
# You can store hashes directly using this adapter.
|
|
9
|
+
#
|
|
10
|
+
# @example Store hashes
|
|
11
|
+
# db = Moneta::Adapters::Mongo.new
|
|
12
|
+
# db['key'] = {a: 1, b: 2}
|
|
13
|
+
#
|
|
7
14
|
# @api public
|
|
8
15
|
class Couch
|
|
9
16
|
include Defaults
|
|
10
17
|
|
|
11
18
|
attr_reader :backend
|
|
12
19
|
|
|
20
|
+
supports :create
|
|
21
|
+
|
|
13
22
|
# @param [Hash] options
|
|
14
23
|
# @option options [String] :host ('127.0.0.1') Couch host
|
|
15
24
|
# @option options [String] :port (5984) Couch port
|
|
16
25
|
# @option options [String] :db ('moneta') Couch database
|
|
26
|
+
# @option options [String] :value_field ('value') Document field to store value
|
|
27
|
+
# @option options [String] :type_field ('type') Document field to store value type
|
|
17
28
|
# @option options [Faraday connection] :backend Use existing backend instance
|
|
18
29
|
def initialize(options = {})
|
|
30
|
+
@value_field = options[:value_field] || 'value'
|
|
31
|
+
@type_field = options[:type_field] || 'type'
|
|
19
32
|
url = "http://#{options[:host] || '127.0.0.1'}:#{options[:port] || 5984}/#{options[:db] || 'moneta'}"
|
|
20
33
|
@backend = options[:backend] || ::Faraday.new(:url => url)
|
|
21
34
|
create_db
|
|
@@ -29,15 +42,14 @@ module Moneta
|
|
|
29
42
|
# (see Proxy#load)
|
|
30
43
|
def load(key, options = {})
|
|
31
44
|
response = @backend.get(key)
|
|
32
|
-
response.status == 200 ?
|
|
45
|
+
response.status == 200 ? body_to_value(response.body) : nil
|
|
33
46
|
end
|
|
34
47
|
|
|
35
48
|
# (see Proxy#store)
|
|
36
49
|
def store(key, value, options = {})
|
|
37
50
|
response = @backend.head(key)
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
response = @backend.put(key, MultiJson.dump(doc), 'Content-Type' => 'application/json')
|
|
51
|
+
body = value_to_body(value, response.status == 200 && response['etag'][1..-2])
|
|
52
|
+
response = @backend.put(key, body, 'Content-Type' => 'application/json')
|
|
41
53
|
raise "HTTP error #{response.status}" unless response.status == 201
|
|
42
54
|
value
|
|
43
55
|
rescue
|
|
@@ -49,7 +61,7 @@ module Moneta
|
|
|
49
61
|
def delete(key, options = {})
|
|
50
62
|
response = @backend.get(key)
|
|
51
63
|
if response.status == 200
|
|
52
|
-
value =
|
|
64
|
+
value = body_to_value(response.body)
|
|
53
65
|
response = @backend.delete("#{key}?rev=#{response['etag'][1..-2]}")
|
|
54
66
|
raise "HTTP error #{response.status}" unless response.status == 200
|
|
55
67
|
value
|
|
@@ -66,8 +78,54 @@ module Moneta
|
|
|
66
78
|
self
|
|
67
79
|
end
|
|
68
80
|
|
|
81
|
+
# (see Proxy#create)
|
|
82
|
+
def create(key, value, options = {})
|
|
83
|
+
body = value_to_body(value, nil)
|
|
84
|
+
response = @backend.put(key, body, 'Content-Type' => 'application/json')
|
|
85
|
+
case response.status
|
|
86
|
+
when 201
|
|
87
|
+
true
|
|
88
|
+
when 409
|
|
89
|
+
false
|
|
90
|
+
else
|
|
91
|
+
raise "HTTP error #{response.status}"
|
|
92
|
+
end
|
|
93
|
+
rescue
|
|
94
|
+
tries ||= 0
|
|
95
|
+
(tries += 1) < 10 ? retry : raise
|
|
96
|
+
end
|
|
97
|
+
|
|
69
98
|
private
|
|
70
99
|
|
|
100
|
+
def body_to_value(body)
|
|
101
|
+
doc = MultiJson.load(body)
|
|
102
|
+
case doc[@type_field]
|
|
103
|
+
when 'Hash'
|
|
104
|
+
doc = doc.dup
|
|
105
|
+
doc.delete('_id')
|
|
106
|
+
doc.delete('_rev')
|
|
107
|
+
doc.delete(@type_field)
|
|
108
|
+
doc
|
|
109
|
+
else
|
|
110
|
+
doc[@value_field]
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def value_to_body(value, rev)
|
|
115
|
+
case value
|
|
116
|
+
when Hash
|
|
117
|
+
doc = value.merge(@type_field => 'Hash')
|
|
118
|
+
when String
|
|
119
|
+
doc = { @value_field => value, @type_field => 'String' }
|
|
120
|
+
when Float, Fixnum
|
|
121
|
+
doc = { @value_field => value, @type_field => 'Number' }
|
|
122
|
+
else
|
|
123
|
+
raise ArgumentError, "Invalid value type: #{value.class}"
|
|
124
|
+
end
|
|
125
|
+
doc['_rev'] = rev if rev
|
|
126
|
+
MultiJson.dump(doc)
|
|
127
|
+
end
|
|
128
|
+
|
|
71
129
|
def create_db
|
|
72
130
|
response = @backend.put '', ''
|
|
73
131
|
raise "HTTP error #{response.status}" unless response.status == 201 || response.status == 412
|
data/lib/moneta/adapters/file.rb
CHANGED
|
@@ -66,24 +66,41 @@ module Moneta
|
|
|
66
66
|
FileUtils.mkpath(::File.dirname(path))
|
|
67
67
|
::File.open(path, ::File::RDWR | ::File::CREAT) do |f|
|
|
68
68
|
Thread.pass until f.flock(::File::LOCK_EX)
|
|
69
|
-
content =
|
|
69
|
+
content = f.read
|
|
70
70
|
amount += Utils.to_int(content) unless content.empty?
|
|
71
|
-
|
|
71
|
+
content = amount.to_s
|
|
72
|
+
f.pos = 0
|
|
73
|
+
f.write(content)
|
|
74
|
+
f.truncate(content.bytesize)
|
|
72
75
|
amount
|
|
73
76
|
end
|
|
74
77
|
end
|
|
75
78
|
|
|
76
|
-
#
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
79
|
+
# HACK: The implementation using File::EXCL is not atomic under JRuby 1.7.4
|
|
80
|
+
# See https://github.com/jruby/jruby/issues/827
|
|
81
|
+
if defined?(JRUBY_VERSION)
|
|
82
|
+
# (see Proxy#create)
|
|
83
|
+
def create(key, value, options = {})
|
|
84
|
+
path = store_path(key)
|
|
85
|
+
FileUtils.mkpath(::File.dirname(path))
|
|
86
|
+
# Call native java.io.File#createNewFile
|
|
87
|
+
return false unless ::Java::JavaIo::File.new(path).createNewFile
|
|
88
|
+
::File.open(path, 'wb+') {|f| f.write(value) }
|
|
89
|
+
true
|
|
90
|
+
end
|
|
91
|
+
else
|
|
92
|
+
# (see Proxy#create)
|
|
93
|
+
def create(key, value, options = {})
|
|
94
|
+
path = store_path(key)
|
|
95
|
+
FileUtils.mkpath(::File.dirname(path))
|
|
96
|
+
::File.open(path, ::File::WRONLY | ::File::CREAT | ::File::EXCL) do |f|
|
|
97
|
+
f.binmode
|
|
98
|
+
f.write(value)
|
|
99
|
+
end
|
|
100
|
+
true
|
|
101
|
+
rescue Errno::EEXIST
|
|
102
|
+
false
|
|
83
103
|
end
|
|
84
|
-
true
|
|
85
|
-
rescue Errno::EEXIST
|
|
86
|
-
false
|
|
87
104
|
end
|
|
88
105
|
|
|
89
106
|
protected
|
data/lib/moneta/adapters/fog.rb
CHANGED
|
@@ -7,6 +7,12 @@ module Moneta
|
|
|
7
7
|
# Supports expiration, documents will be automatically removed starting
|
|
8
8
|
# with mongodb >= 2.2 (see {http://docs.mongodb.org/manual/tutorial/expire-data/}).
|
|
9
9
|
#
|
|
10
|
+
# You can store hashes directly using this adapter.
|
|
11
|
+
#
|
|
12
|
+
# @example Store hashes
|
|
13
|
+
# db = Moneta::Adapters::Mongo.new
|
|
14
|
+
# db['key'] = {a: 1, b: 2}
|
|
15
|
+
#
|
|
10
16
|
# @api public
|
|
11
17
|
class Mongo
|
|
12
18
|
include Defaults
|
|
@@ -23,11 +29,18 @@ module Moneta
|
|
|
23
29
|
# @option options [Integer] :port (MongoDB default port) MongoDB server port
|
|
24
30
|
# @option options [String] :db ('moneta') MongoDB database
|
|
25
31
|
# @option options [Integer] :expires Default expiration time
|
|
32
|
+
# @option options [String] :expires_field ('expiresAt') Document field to store expiration time
|
|
33
|
+
# @option options [String] :value_field ('value') Document field to store value
|
|
34
|
+
# @option options [String] :type_field ('type') Document field to store value type
|
|
26
35
|
# @option options [::Mongo::MongoClient] :backend Use existing backend instance
|
|
36
|
+
# @option options Other options passed to `Mongo::MongoClient#new`
|
|
27
37
|
def initialize(options = {})
|
|
28
38
|
self.default_expires = options.delete(:expires)
|
|
29
39
|
collection = options.delete(:collection) || 'moneta'
|
|
30
40
|
db = options.delete(:db) || 'moneta'
|
|
41
|
+
@expires_field = options.delete(:expires_field) || 'expiresAt'
|
|
42
|
+
@value_field = options.delete(:value_field) || 'value'
|
|
43
|
+
@type_field = options.delete(:type_field) || 'type'
|
|
31
44
|
@backend = options[:backend] ||
|
|
32
45
|
begin
|
|
33
46
|
host = options.delete(:host) || '127.0.0.1'
|
|
@@ -40,7 +53,7 @@ module Moneta
|
|
|
40
53
|
db.authenticate(user, password, true) if user && password
|
|
41
54
|
@collection = db.collection(collection)
|
|
42
55
|
if @backend.server_version >= '2.2'
|
|
43
|
-
@collection.ensure_index([[
|
|
56
|
+
@collection.ensure_index([[@expires_field, ::Mongo::ASCENDING]], :expireAfterSeconds => 0)
|
|
44
57
|
else
|
|
45
58
|
warn 'Moneta::Adapters::Mongo - You are using MongoDB version < 2.2, expired documents will not be deleted'
|
|
46
59
|
end
|
|
@@ -48,26 +61,22 @@ module Moneta
|
|
|
48
61
|
|
|
49
62
|
# (see Proxy#load)
|
|
50
63
|
def load(key, options = {})
|
|
51
|
-
key =
|
|
64
|
+
key = to_binary(key)
|
|
52
65
|
doc = @collection.find_one('_id' => key)
|
|
53
|
-
if doc && (!doc[
|
|
66
|
+
if doc && (!doc[@expires_field] || doc[@expires_field] >= Time.now)
|
|
54
67
|
expires = expires_at(options, nil)
|
|
55
68
|
@collection.update({ '_id' => key },
|
|
56
|
-
#
|
|
57
|
-
{ '$set' => {
|
|
58
|
-
doc
|
|
69
|
+
# @expires_field must be a Time object (BSON date datatype)
|
|
70
|
+
{ '$set' => { @expires_field => expires || nil } }) if expires != nil
|
|
71
|
+
doc_to_value(doc)
|
|
59
72
|
end
|
|
60
73
|
end
|
|
61
74
|
|
|
62
75
|
# (see Proxy#store)
|
|
63
76
|
def store(key, value, options = {})
|
|
64
|
-
key =
|
|
65
|
-
intvalue = value.to_i
|
|
77
|
+
key = to_binary(key)
|
|
66
78
|
@collection.update({ '_id' => key },
|
|
67
|
-
|
|
68
|
-
'value' => intvalue.to_s == value ? intvalue : ::BSON::Binary.new(value),
|
|
69
|
-
# expiresAt must be a Time object (BSON date datatype)
|
|
70
|
-
'expiresAt' => expires_at(options) || nil },
|
|
79
|
+
value_to_doc(key, value, options),
|
|
71
80
|
{ :upsert => true })
|
|
72
81
|
value
|
|
73
82
|
end
|
|
@@ -75,26 +84,22 @@ module Moneta
|
|
|
75
84
|
# (see Proxy#delete)
|
|
76
85
|
def delete(key, options = {})
|
|
77
86
|
value = load(key, options)
|
|
78
|
-
@collection.remove('_id' =>
|
|
87
|
+
@collection.remove('_id' => to_binary(key)) if value
|
|
79
88
|
value
|
|
80
89
|
end
|
|
81
90
|
|
|
82
91
|
# (see Proxy#increment)
|
|
83
92
|
def increment(key, amount = 1, options = {})
|
|
84
|
-
@collection.find_and_modify(:query => { '_id' =>
|
|
85
|
-
:update => { '$inc' => {
|
|
93
|
+
@collection.find_and_modify(:query => { '_id' => to_binary(key) },
|
|
94
|
+
:update => { '$inc' => { @value_field => amount } },
|
|
86
95
|
:new => true,
|
|
87
|
-
:upsert => true)[
|
|
96
|
+
:upsert => true)[@value_field]
|
|
88
97
|
end
|
|
89
98
|
|
|
90
99
|
# (see Proxy#create)
|
|
91
100
|
def create(key, value, options = {})
|
|
92
|
-
key =
|
|
93
|
-
|
|
94
|
-
@collection.insert('_id' => key,
|
|
95
|
-
'value' => intvalue.to_s == value ? intvalue : ::BSON::Binary.new(value),
|
|
96
|
-
# expiresAt must be a Time object (BSON date datatype)
|
|
97
|
-
'expiresAt' => expires_at(options) || nil)
|
|
101
|
+
key = to_binary(key)
|
|
102
|
+
@collection.insert(value_to_doc(key, value, options))
|
|
98
103
|
true
|
|
99
104
|
rescue ::Mongo::OperationFailure
|
|
100
105
|
# FIXME: This catches too many errors
|
|
@@ -113,6 +118,53 @@ module Moneta
|
|
|
113
118
|
@backend.close
|
|
114
119
|
nil
|
|
115
120
|
end
|
|
121
|
+
|
|
122
|
+
protected
|
|
123
|
+
|
|
124
|
+
def doc_to_value(doc)
|
|
125
|
+
case doc[@type_field]
|
|
126
|
+
when 'Hash'
|
|
127
|
+
doc = doc.dup
|
|
128
|
+
doc.delete('_id')
|
|
129
|
+
doc.delete(@type_field)
|
|
130
|
+
doc.delete(@expires_field)
|
|
131
|
+
doc
|
|
132
|
+
when 'Number'
|
|
133
|
+
doc[@value_field]
|
|
134
|
+
else
|
|
135
|
+
doc[@value_field].to_s
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def value_to_doc(key, value, options)
|
|
140
|
+
case value
|
|
141
|
+
when Hash
|
|
142
|
+
value.merge('_id' => key,
|
|
143
|
+
@type_field => 'Hash',
|
|
144
|
+
# @expires_field must be a Time object (BSON date datatype)
|
|
145
|
+
@expires_field => expires_at(options) || nil)
|
|
146
|
+
when Float, Fixnum
|
|
147
|
+
{ '_id' => key,
|
|
148
|
+
@type_field => 'Number',
|
|
149
|
+
@value_field => value,
|
|
150
|
+
# @expires_field must be a Time object (BSON date datatype)
|
|
151
|
+
@expires_field => expires_at(options) || nil }
|
|
152
|
+
when String
|
|
153
|
+
intvalue = value.to_i
|
|
154
|
+
{ '_id' => key,
|
|
155
|
+
@type_field => 'String',
|
|
156
|
+
@value_field => intvalue.to_s == value ? intvalue : to_binary(value),
|
|
157
|
+
# @expires_field must be a Time object (BSON date datatype)
|
|
158
|
+
@expires_field => expires_at(options) || nil }
|
|
159
|
+
else
|
|
160
|
+
raise ArgumentError, "Invalid value type: #{value.class}"
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def to_binary(s)
|
|
165
|
+
s = s.dup if s.frozen? # HACK: BSON::Binary needs unfrozen string
|
|
166
|
+
::BSON::Binary.new(s)
|
|
167
|
+
end
|
|
116
168
|
end
|
|
117
169
|
end
|
|
118
170
|
end
|