moneta 0.7.3 → 0.7.4
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.
- data/.travis.yml +17 -51
- data/CHANGES +13 -0
- data/Gemfile +4 -4
- data/README.md +79 -40
- data/Rakefile +40 -25
- data/benchmarks/run.rb +35 -5
- data/lib/moneta.rb +5 -5
- data/lib/moneta/adapters/activerecord.rb +4 -6
- data/lib/moneta/adapters/cassandra.rb +8 -11
- data/lib/moneta/adapters/couch.rb +3 -1
- data/lib/moneta/adapters/daybreak.rb +28 -0
- data/lib/moneta/adapters/fog.rb +3 -3
- data/lib/moneta/adapters/hbase.rb +2 -4
- data/lib/moneta/adapters/memcached/dalli.rb +8 -7
- data/lib/moneta/adapters/memcached/native.rb +8 -9
- data/lib/moneta/adapters/mongo.rb +42 -11
- data/lib/moneta/adapters/pstore.rb +4 -6
- data/lib/moneta/adapters/redis.rb +17 -10
- data/lib/moneta/adapters/restclient.rb +19 -10
- data/lib/moneta/adapters/sequel.rb +4 -6
- data/lib/moneta/adapters/tdb.rb +22 -0
- data/lib/moneta/expires.rb +28 -12
- data/lib/moneta/mixins.rb +64 -3
- data/lib/moneta/pool.rb +37 -0
- data/lib/moneta/proxy.rb +18 -7
- data/lib/moneta/server.rb +1 -1
- data/lib/moneta/shared.rb +2 -2
- data/lib/moneta/transformer/helper.rb +1 -1
- data/lib/moneta/version.rb +1 -1
- data/{spec/generate.rb → script/generate-specs.rb} +195 -91
- data/script/install-bundle.rb +35 -0
- data/spec/helper.rb +6 -0
- data/spec/moneta/adapter_activerecord_spec.rb +1 -1
- data/spec/moneta/adapter_cassandra_spec.rb +1 -12
- data/spec/moneta/adapter_cassandra_with_default_expires_spec.rb +21 -0
- data/spec/moneta/adapter_client_spec.rb +1 -1
- data/spec/moneta/adapter_cookie_spec.rb +1 -1
- data/spec/moneta/adapter_couch_spec.rb +1 -1
- data/spec/moneta/adapter_datamapper_spec.rb +1 -1
- data/spec/moneta/adapter_daybreak_spec.rb +19 -0
- data/spec/moneta/adapter_dbm_spec.rb +1 -1
- data/spec/moneta/adapter_file_spec.rb +1 -1
- data/spec/moneta/adapter_fog_spec.rb +1 -1
- data/spec/moneta/adapter_gdbm_spec.rb +1 -1
- data/spec/moneta/adapter_hbase_spec.rb +1 -1
- data/spec/moneta/adapter_leveldb_spec.rb +1 -1
- data/spec/moneta/adapter_localmemcache_spec.rb +1 -1
- data/spec/moneta/adapter_lruhash_spec.rb +1 -1
- data/spec/moneta/adapter_memcached_dalli_spec.rb +1 -12
- data/spec/moneta/adapter_memcached_dalli_with_default_expires_spec.rb +21 -0
- data/spec/moneta/adapter_memcached_native_spec.rb +1 -13
- data/spec/moneta/adapter_memcached_native_with_default_expires_spec.rb +21 -0
- data/spec/moneta/adapter_memcached_spec.rb +1 -12
- data/spec/moneta/adapter_memcached_with_default_expires_spec.rb +21 -0
- data/spec/moneta/adapter_memory_spec.rb +1 -1
- data/spec/moneta/adapter_mongo_spec.rb +9 -2
- data/spec/moneta/adapter_mongo_with_default_expires_spec.rb +21 -0
- data/spec/moneta/adapter_pstore_spec.rb +1 -1
- data/spec/moneta/adapter_redis_spec.rb +1 -12
- data/spec/moneta/adapter_redis_with_default_expires_spec.rb +21 -0
- data/spec/moneta/adapter_restclient_spec.rb +1 -1
- data/spec/moneta/adapter_riak_spec.rb +1 -1
- data/spec/moneta/adapter_sdbm_spec.rb +1 -1
- data/spec/moneta/adapter_sequel_spec.rb +1 -1
- data/spec/moneta/adapter_sqlite_spec.rb +1 -1
- data/spec/moneta/adapter_tdb_spec.rb +19 -0
- data/spec/moneta/adapter_tokyocabinet_bdb_spec.rb +1 -1
- data/spec/moneta/adapter_tokyocabinet_hdb_spec.rb +1 -1
- data/spec/moneta/adapter_yaml_spec.rb +1 -1
- data/spec/moneta/cache_file_memory_spec.rb +1 -1
- data/spec/moneta/cache_memory_null_spec.rb +1 -1
- data/spec/moneta/expires_file_spec.rb +1 -1
- data/spec/moneta/expires_memory_spec.rb +1 -12
- data/spec/moneta/expires_memory_with_default_expires_spec.rb +111 -0
- data/spec/moneta/lock_spec.rb +1 -1
- data/spec/moneta/null_adapter_spec.rb +1 -1
- data/spec/moneta/optionmerger_spec.rb +1 -1
- data/spec/moneta/pool_spec.rb +23 -0
- data/spec/moneta/proxy_expires_memory_spec.rb +1 -1
- data/spec/moneta/proxy_redis_spec.rb +1 -1
- data/spec/moneta/shared_spec.rb +1 -1
- data/spec/moneta/simple_activerecord_spec.rb +1 -1
- data/spec/moneta/simple_activerecord_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_cassandra_spec.rb +1 -1
- data/spec/moneta/simple_client_tcp_spec.rb +1 -1
- data/spec/moneta/simple_client_unix_spec.rb +1 -1
- data/spec/moneta/simple_couch_spec.rb +1 -1
- data/spec/moneta/simple_couch_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_datamapper_spec.rb +1 -1
- data/spec/moneta/simple_datamapper_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_datamapper_with_repository_spec.rb +1 -1
- data/spec/moneta/simple_daybreak_spec.rb +144 -0
- data/spec/moneta/simple_daybreak_with_expires_spec.rb +145 -0
- data/spec/moneta/simple_dbm_spec.rb +1 -1
- data/spec/moneta/simple_dbm_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_file_spec.rb +1 -1
- data/spec/moneta/simple_file_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_fog_spec.rb +1 -1
- data/spec/moneta/simple_fog_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_gdbm_spec.rb +1 -1
- data/spec/moneta/simple_gdbm_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_hashfile_spec.rb +1 -1
- data/spec/moneta/simple_hashfile_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_hbase_spec.rb +1 -1
- data/spec/moneta/simple_hbase_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_leveldb_spec.rb +1 -1
- data/spec/moneta/simple_leveldb_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_localmemcache_spec.rb +1 -1
- data/spec/moneta/simple_localmemcache_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_lruhash_spec.rb +1 -1
- data/spec/moneta/simple_lruhash_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_memcached_dalli_spec.rb +1 -1
- data/spec/moneta/simple_memcached_native_spec.rb +1 -1
- data/spec/moneta/simple_memcached_spec.rb +1 -1
- data/spec/moneta/simple_memory_spec.rb +1 -1
- data/spec/moneta/simple_memory_with_compress_spec.rb +1 -1
- data/spec/moneta/simple_memory_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_memory_with_json_key_serializer_spec.rb +1 -1
- data/spec/moneta/simple_memory_with_json_serializer_spec.rb +1 -1
- data/spec/moneta/simple_memory_with_json_value_serializer_spec.rb +1 -1
- data/spec/moneta/simple_memory_with_prefix_spec.rb +1 -1
- data/spec/moneta/simple_memory_with_snappy_compress_spec.rb +1 -1
- data/spec/moneta/simple_mongo_spec.rb +3 -2
- data/spec/moneta/simple_null_spec.rb +1 -1
- data/spec/moneta/simple_pstore_spec.rb +1 -1
- data/spec/moneta/simple_pstore_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_redis_spec.rb +1 -1
- data/spec/moneta/simple_restclient_spec.rb +1 -1
- data/spec/moneta/simple_riak_spec.rb +1 -1
- data/spec/moneta/simple_riak_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_sdbm_spec.rb +1 -1
- data/spec/moneta/simple_sdbm_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_sequel_spec.rb +1 -1
- data/spec/moneta/simple_sequel_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_sqlite_spec.rb +1 -1
- data/spec/moneta/simple_sqlite_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_tdb_spec.rb +144 -0
- data/spec/moneta/{simple_mongo_with_expires_spec.rb → simple_tdb_with_expires_spec.rb} +4 -4
- data/spec/moneta/simple_tokyocabinet_spec.rb +1 -1
- data/spec/moneta/simple_tokyocabinet_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_yaml_spec.rb +1 -1
- data/spec/moneta/simple_yaml_with_expires_spec.rb +1 -1
- data/spec/moneta/stack_file_memory_spec.rb +1 -1
- data/spec/moneta/stack_memory_file_spec.rb +1 -1
- data/spec/moneta/transformer_bencode_spec.rb +1 -1
- data/spec/moneta/transformer_bert_spec.rb +1 -1
- data/spec/moneta/transformer_bson_spec.rb +1 -1
- data/spec/moneta/transformer_bzip2_spec.rb +1 -1
- data/spec/moneta/transformer_json_spec.rb +1 -1
- data/spec/moneta/transformer_key_marshal_spec.rb +1 -1
- data/spec/moneta/transformer_key_yaml_spec.rb +1 -1
- data/spec/moneta/transformer_lzma_spec.rb +1 -1
- data/spec/moneta/transformer_lzo_spec.rb +1 -1
- data/spec/moneta/transformer_marshal_base64_spec.rb +1 -1
- data/spec/moneta/transformer_marshal_escape_spec.rb +1 -1
- data/spec/moneta/transformer_marshal_hmac_spec.rb +1 -1
- data/spec/moneta/transformer_marshal_md5_spec.rb +1 -1
- data/spec/moneta/transformer_marshal_md5_spread_spec.rb +1 -1
- data/spec/moneta/transformer_marshal_prefix_spec.rb +1 -1
- data/spec/moneta/transformer_marshal_rmd160_spec.rb +1 -1
- data/spec/moneta/transformer_marshal_sha1_spec.rb +1 -1
- data/spec/moneta/transformer_marshal_sha256_spec.rb +1 -1
- data/spec/moneta/transformer_marshal_sha384_spec.rb +1 -1
- data/spec/moneta/transformer_marshal_sha512_spec.rb +1 -1
- data/spec/moneta/transformer_marshal_spec.rb +1 -1
- data/spec/moneta/transformer_marshal_truncate_spec.rb +1 -1
- data/spec/moneta/transformer_marshal_uuencode_spec.rb +1 -1
- data/spec/moneta/transformer_msgpack_spec.rb +1 -1
- data/spec/moneta/transformer_ox_spec.rb +1 -1
- data/spec/moneta/transformer_quicklz_spec.rb +1 -1
- data/spec/moneta/transformer_snappy_spec.rb +1 -1
- data/spec/moneta/transformer_tnet_spec.rb +1 -1
- data/spec/moneta/transformer_value_marshal_spec.rb +1 -1
- data/spec/moneta/transformer_value_yaml_spec.rb +1 -1
- data/spec/moneta/transformer_yaml_spec.rb +1 -1
- data/spec/moneta/transformer_zlib_spec.rb +1 -1
- data/spec/monetaspecs.rb +105 -3
- metadata +35 -6
data/.travis.yml
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
rvm:
|
|
2
2
|
- 1.8.7
|
|
3
3
|
- 1.9.3
|
|
4
|
-
# - ruby-head
|
|
5
4
|
- jruby
|
|
6
5
|
- rbx-18mode
|
|
7
6
|
- rbx-19mode
|
|
@@ -13,60 +12,27 @@ services:
|
|
|
13
12
|
- memcached
|
|
14
13
|
- mongodb
|
|
15
14
|
before_install:
|
|
16
|
-
- sudo apt-get install -qq libtokyocabinet8 libtokyocabinet-dev liblzo2-dev
|
|
15
|
+
- sudo apt-get install -qq libtokyocabinet8 libtokyocabinet-dev liblzo2-dev libtdb-dev
|
|
16
|
+
- script/install-bundle.rb
|
|
17
17
|
env:
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
18
|
+
global:
|
|
19
|
+
- secure: "bNtinRuxS/FLP1fKj7KtHweIP/fG94CusdYKH/sBL6P0aqL3mr/dkbC34pSk\nNGkLKs/FAzvLkOo7aIOcCLx1WnL9yaZ12tmHgH8Ztf8ci2S52HSfqYwQw/dE\nq7euNMZVjvWfVu+15+Xpn6+t2XSubSO/TELfymDFGbhivmKAo5M="
|
|
20
|
+
- secure: "Pv/MUnoaZMbPNB3vx4Hw2ASQBsUO7HIjJsfGHAQa5VbWlX3qEfMdezlYzNbf\nDPdpeabQwEwCUcINT7x10XKH5M4nZn6bBGfpvmNMxvZ8De1Et7mrwvb5/o73\n5EkyvYuUu8FB/LQmjB/4zZcjLQWNCtcfPlYPs7YcADBt0gIwn8M="
|
|
21
|
+
matrix:
|
|
22
|
+
- "TASK=test"
|
|
23
|
+
- "TASK=benchmarks CONFIG=uniform_small"
|
|
24
|
+
- "TASK=benchmarks CONFIG=uniform_medium"
|
|
25
|
+
- "TASK=benchmarks CONFIG=uniform_large"
|
|
26
|
+
- "TASK=benchmarks CONFIG=normal_small"
|
|
27
|
+
- "TASK=benchmarks CONFIG=normal_medium"
|
|
28
|
+
- "TASK=benchmarks CONFIG=normal_large"
|
|
26
29
|
matrix:
|
|
27
30
|
allow_failures:
|
|
28
|
-
# - rvm: ruby-head
|
|
29
31
|
- rvm: jruby
|
|
30
32
|
- rvm: rbx-18mode
|
|
31
33
|
- rvm: rbx-19mode
|
|
32
|
-
# Parallel tests do not work on jruby
|
|
33
|
-
exclude:
|
|
34
|
-
- rvm: jruby
|
|
35
|
-
env: "TASK=test:parallel"
|
|
36
|
-
- rvm: jruby
|
|
37
|
-
env: "TASK=benchmarks CONFIG=uniform_small"
|
|
38
|
-
- rvm: jruby
|
|
39
|
-
env: "TASK=benchmarks CONFIG=uniform_medium"
|
|
40
|
-
- rvm: jruby
|
|
41
|
-
env: "TASK=benchmarks CONFIG=uniform_large"
|
|
42
|
-
- rvm: jruby
|
|
43
|
-
env: "TASK=benchmarks CONFIG=normal_small"
|
|
44
|
-
- rvm: jruby
|
|
45
|
-
env: "TASK=benchmarks CONFIG=normal_medium"
|
|
46
|
-
- rvm: jruby
|
|
47
|
-
env: "TASK=benchmarks CONFIG=normal_large"
|
|
48
|
-
- rvm: rbx-18mode
|
|
49
|
-
env: "TASK=benchmarks CONFIG=uniform_small"
|
|
50
|
-
- rvm: rbx-18mode
|
|
51
|
-
env: "TASK=benchmarks CONFIG=uniform_medium"
|
|
52
|
-
- rvm: rbx-18mode
|
|
53
|
-
env: "TASK=benchmarks CONFIG=uniform_large"
|
|
54
|
-
- rvm: rbx-18mode
|
|
55
|
-
env: "TASK=benchmarks CONFIG=normal_small"
|
|
56
|
-
- rvm: rbx-18mode
|
|
57
|
-
env: "TASK=benchmarks CONFIG=normal_medium"
|
|
58
|
-
- rvm: rbx-18mode
|
|
59
|
-
env: "TASK=benchmarks CONFIG=normal_large"
|
|
60
|
-
- rvm: rbx-19mode
|
|
61
|
-
env: "TASK=benchmarks CONFIG=uniform_small"
|
|
62
|
-
- rvm: rbx-19mode
|
|
63
|
-
env: "TASK=benchmarks CONFIG=uniform_medium"
|
|
64
|
-
- rvm: rbx-19mode
|
|
65
|
-
env: "TASK=benchmarks CONFIG=uniform_large"
|
|
66
|
-
- rvm: rbx-19mode
|
|
67
|
-
env: "TASK=benchmarks CONFIG=normal_small"
|
|
68
|
-
- rvm: rbx-19mode
|
|
69
|
-
env: "TASK=benchmarks CONFIG=normal_medium"
|
|
70
|
-
- rvm: rbx-19mode
|
|
71
|
-
env: "TASK=benchmarks CONFIG=normal_large"
|
|
72
34
|
script: "bundle exec rake $TASK"
|
|
35
|
+
branches:
|
|
36
|
+
only:
|
|
37
|
+
- master
|
|
38
|
+
- travis
|
data/CHANGES
CHANGED
|
@@ -1,3 +1,16 @@
|
|
|
1
|
+
0.7.4
|
|
2
|
+
|
|
3
|
+
* Transformer: fix truncate
|
|
4
|
+
* Adapters::RestClient: raise error if store fails
|
|
5
|
+
* Adapters::TDB added
|
|
6
|
+
* Adapters::Daybreak added
|
|
7
|
+
* Adapters::Mongo - Expiration and increment support added
|
|
8
|
+
* Pool proxy added
|
|
9
|
+
* Mixin ExpiresSupport added
|
|
10
|
+
* Expiration value handling unified
|
|
11
|
+
* 0 and false are interpreted as persist value
|
|
12
|
+
* Adapters::RestClient uses net/http now
|
|
13
|
+
|
|
1
14
|
0.7.3
|
|
2
15
|
|
|
3
16
|
* Added Adapters::RestClient
|
data/Gemfile
CHANGED
|
@@ -12,7 +12,6 @@ end
|
|
|
12
12
|
# Testing
|
|
13
13
|
gem 'rake'
|
|
14
14
|
gem 'rspec'
|
|
15
|
-
gem 'parallel_tests'
|
|
16
15
|
|
|
17
16
|
# Serializer used by Transformer
|
|
18
17
|
gem 'tnetstring'
|
|
@@ -28,10 +27,11 @@ alternatives :mri => 'bzip2-ruby'
|
|
|
28
27
|
alternatives :mri => 'ruby-lzma'
|
|
29
28
|
alternatives :mri => 'lzoruby'
|
|
30
29
|
alternatives :mri => 'snappy'
|
|
31
|
-
# QuickLZ segfaults because of an assertion
|
|
32
|
-
|
|
30
|
+
# WARNING: QuickLZ segfaults because of an assertion
|
|
31
|
+
alternatives :mri => 'qlzruby'
|
|
33
32
|
|
|
34
33
|
# Backends
|
|
34
|
+
gem 'daybreak', :github => 'propublica/daybreak'
|
|
35
35
|
gem 'dm-core'
|
|
36
36
|
gem 'dm-migrations'
|
|
37
37
|
gem 'dm-sqlite-adapter'
|
|
@@ -44,9 +44,9 @@ gem 'sequel'
|
|
|
44
44
|
gem 'dalli'
|
|
45
45
|
gem 'riak-client'
|
|
46
46
|
gem 'cassandra'
|
|
47
|
-
gem 'httpi'
|
|
48
47
|
#gem 'hbaserb'
|
|
49
48
|
#gem 'localmemcache'
|
|
49
|
+
alternatives :mri => 'tdb'
|
|
50
50
|
alternatives :mri => 'leveldb-ruby'
|
|
51
51
|
alternatives :mri => 'tokyocabinet'
|
|
52
52
|
alternatives :mri => 'memcached', :jruby => 'jruby-memcached'
|
data/README.md
CHANGED
|
@@ -14,6 +14,16 @@ Moneta provides a standard interface for interacting with various kinds of key/v
|
|
|
14
14
|
* Includes a very simple key/value server (`Moneta::Server`) and client (`Moneta::Adapters::Client`)
|
|
15
15
|
* Integration with [Rails](http://rubyonrails.org/), [Rack](http://rack.github.com/), [Sinatra](http://sinatrarb.com/) and [Rack-Cache](https://github.com/rtomayko/rack-cache)
|
|
16
16
|
|
|
17
|
+
If you are not yet convinced, you might ask why? What are the goals of the project?
|
|
18
|
+
|
|
19
|
+
* Get people started quickly with key/value stores! Therefore all the adapters are included in the gem and you are ready to go. [Tilt](https://github.com/rtomayko/tilt) does the
|
|
20
|
+
same for template languages.
|
|
21
|
+
* Make it easy to compare different key/value stores and benchmark them
|
|
22
|
+
* To hide a lot of different and maybe complex APIs behind one well-designed and simple Moneta API
|
|
23
|
+
* Give people a starting point or example code to start working with their favourite key/value store. Feel free to copy code, please mention Moneta then :)
|
|
24
|
+
* Create a reusable piece of code, since similar things are solved over and over again ([Rails](http://rubyonrails.org/ brings its own cache stores, and many frameworks do the same...)
|
|
25
|
+
* See also http://yehudakatz.com/2009/02/12/whats-the-point/
|
|
26
|
+
|
|
17
27
|
Moneta is tested thoroughly using [Travis-CI](http://travis-ci.org/minad/moneta).
|
|
18
28
|
|
|
19
29
|
## Links
|
|
@@ -33,6 +43,7 @@ Out of the box, it supports the following backends:
|
|
|
33
43
|
* LRU hash - prefer this over :Memory! (`:LRUHash`)
|
|
34
44
|
* LocalMemCache (`:LocalMemCache`)
|
|
35
45
|
* Memcached store (`:Memcached`, `:MemcachedNative` and `:MemcachedDalli`)
|
|
46
|
+
* Daybreak database (`:Daybreak`)
|
|
36
47
|
* Relational Databases:
|
|
37
48
|
* DataMapper (`:DataMapper`)
|
|
38
49
|
* ActiveRecord (`:ActiveRecord`)
|
|
@@ -46,6 +57,7 @@ Out of the box, it supports the following backends:
|
|
|
46
57
|
* Key/value databases:
|
|
47
58
|
* Berkeley DB (`:DBM`)
|
|
48
59
|
* Cassandra (`:Cassandra`)
|
|
60
|
+
* Daybreak (`:Daybreak`)
|
|
49
61
|
* GDBM (`:GDBM`)
|
|
50
62
|
* HBase (`:HBase`)
|
|
51
63
|
* LevelDB (`:LevelDB`)
|
|
@@ -53,6 +65,7 @@ Out of the box, it supports the following backends:
|
|
|
53
65
|
* Riak (`:Riak`)
|
|
54
66
|
* SDBM (`:SDBM`)
|
|
55
67
|
* TokyoCabinet (`:TokyoCabinet`)
|
|
68
|
+
* Simple Samba database TDB (`:TDB`)
|
|
56
69
|
* Document databases:
|
|
57
70
|
* CouchDB (`:Couch`)
|
|
58
71
|
* MongoDB (`:Mongo`)
|
|
@@ -68,6 +81,52 @@ are useful if you already use the corresponding backend in your application. You
|
|
|
68
81
|
store for free then without installing any additional services and you still have the possibility
|
|
69
82
|
to upgrade to a real key/value store.
|
|
70
83
|
|
|
84
|
+
### Backend feature matrix
|
|
85
|
+
|
|
86
|
+
<table>
|
|
87
|
+
<thead style="font-weight:bold"><tr><th>Adapter</th><th>Required gems</th><th>Multi-thread safe<sup>[1]</sup></th><th>Multi-process safe<sup>[2]</sup></th><th>Atomic increment</th><th>Native expires<sup>[3]</sup></th><th>Persistent</th><th>Description</th></tr></thead>
|
|
88
|
+
<tbody>
|
|
89
|
+
<tr><td>ActiveRecord</td><td>activerecord</td><td style="color:blue">?</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:green">✓</td><td>ActiveRecord ORM</td></tr>
|
|
90
|
+
<tr><td>Cassandra</td><td>cassandra</td><td style="color:blue">?</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:green">✓</td><td style="color:green">✓</td><td>Cassandra distributed database</td></tr>
|
|
91
|
+
<tr><td>Client</td><td>-</td><td style="color:red">✗</td><td style="color:green">✓</td><td style="color:blue">?<sup>[5]</sup></td><td style="color:blue">?<sup>[5]</sup></td><td style="color:blue">?<sup>[5]</sup></td><td>Moneta client adapter</td></tr>
|
|
92
|
+
<tr><td>Cookie</td><td>-</td><td style="color:red">✗</td><td style="color:blue">(✓)<sup>[6]</sup></td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:red">✗</td><td>Cookie in memory store</td></tr>
|
|
93
|
+
<tr><td>Couch</td><td>couchrest</td><td style="color:blue">?</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:red">✗</td><td style="color:green">✓</td><td>CouchDB database</td></tr>
|
|
94
|
+
<tr><td>DataMapper</td><td>dm-core, dm-migrations</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:red">✗</td><td style="color:green">✓</td><td>DataMapper ORM</td></tr>
|
|
95
|
+
<tr><td>Daybreak</td><td>daybreak</td><td style="color:blue">?</td><td style="color:red">✗</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:green">✓</td><td>Daybreak ruby key/value store</td></tr>
|
|
96
|
+
<tr><td>DBM</td><td>-</td><td style="color:red">✗</td><td style="color:red">✗</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:green">✓</td><td>Berkeley DB</td></tr>
|
|
97
|
+
<tr><td>File</td><td>-</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:green">✓</td><td>File store</td></tr>
|
|
98
|
+
<tr><td>Fog</td><td>fog</td><td style="color:blue">?</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:red">✗</td><td style="color:green">✓</td><td>Fog cloud store</td></tr>
|
|
99
|
+
<tr><td>GDBM</td><td>-</td><td style="color:red">✗</td><td style="color:red">✗</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:green">✓</td><td>GDBM database</td></tr>
|
|
100
|
+
<tr><td>HBase</td><td>hbase</td><td style="color:blue">?</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:red">✗</td><td style="color:green">✓</td><td>HBase database</td></tr>
|
|
101
|
+
<tr><td>LevelDB</td><td>leveldb</td><td style="color:red">✗</td><td style="color:red">✗</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:green">✓</td><td>LevelDB database</td></tr>
|
|
102
|
+
<tr><td>LocalMemCache</td><td>localmemcache</td><td style="color:blue">?</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:red">✗</td><td style="color:green">✓</td><td>LocalMemCache database</td></tr>
|
|
103
|
+
<tr><td>LRUHash</td><td>-</td><td style="color:red">✗</td><td style="color:blue">(✓)<sup>[6]</sup></td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:red">✗</td><td>LRU memory store</td></tr>
|
|
104
|
+
<tr><td>Memcached</td><td>dalli or memcached</td><td style="color:blue">?</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:red">✗<sup>[4]</sup></td><td>Memcached database</td></tr>
|
|
105
|
+
<tr><td>MemcachedDalli</td><td>dalli</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:red">✗<sup>[4]</sup></td><td>Memcached database</td></tr>
|
|
106
|
+
<tr><td>MemcachedNative</td><td>memcached</td><td style="color:red">✗</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:red">✗<sup>[4]</sup></td><td>Memcached database</td></tr>
|
|
107
|
+
<tr><td>Memory</td><td>-</td><td style="color:red">✗</td><td style="color:blue">(✓)<sup>[6]</sup></td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:red">✗</td><td>Memory store</td></tr>
|
|
108
|
+
<tr><td>Mongo</td><td>mongo</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:green">✓</td><td>MongoDB database</td></tr>
|
|
109
|
+
<tr><td>Null</td><td>-</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:red">✗</td><td style="color:red">✗</td><td>No database</td></tr>
|
|
110
|
+
<tr><td>PStore</td><td>-</td><td style="color:red">✗</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:green">✓</td><td>PStore store</td></tr>
|
|
111
|
+
<tr><td>Redis</td><td>redis</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:green">✓</td><td>Redis database</td></tr>
|
|
112
|
+
<tr><td>RestClient</td><td>-</td><td style="color:red">✗</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:red">✗</td><td style="color:blue">?<sup>[5]</sup></td><td>Moneta REST client adapter</td></tr>
|
|
113
|
+
<tr><td>Riak</td><td>riak-client</td><td style="color:blue">?</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:red">✗</td><td style="color:green">✓</td><td>Riak database</td></tr>
|
|
114
|
+
<tr><td>SDBM</td><td>-</td><td style="color:red">✗</td><td style="color:red">✗</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:green">✓</td><td>SDBM database</td></tr>
|
|
115
|
+
<tr><td>Sequel</td><td>sequel</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:green">✓</td><td>Sequel ORM</td></tr>
|
|
116
|
+
<tr><td>Sqlite</td><td>sqlite3</td><td style="color:blue">?</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:green">✓</td><td>Sqlite3 database</td></tr>
|
|
117
|
+
<tr><td>TDB</td><td>tdb</td><td style="color:red">✗</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:green">✓</td><td>TDB database</td></tr>
|
|
118
|
+
<tr><td>TokyoCabinet</td><td>tokoycabinet</td><td style="color:red">✗</td><td style="color:red">✗</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:green">✓</td><td>TokyoCabinet database</td></tr>
|
|
119
|
+
<tr><td>YAML</td><td>-</td><td style="color:red">✗</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:green">✓</td><td>YAML store</td></tr>
|
|
120
|
+
</tbody>
|
|
121
|
+
</table>
|
|
122
|
+
|
|
123
|
+
* [1]: Make adapters thread-safe by using `Moneta::Lock`, `Moneta::Pool` or by passing the option `:threadsafe => true` to `Moneta#new`.
|
|
124
|
+
* [2]: Share a Moneta store between multiple processes using `Moneta::Shared` (See below).
|
|
125
|
+
* [3]: Add expiration support by using `Moneta::Expires` or by passing the option `:expires => true` to `Moneta#new`.
|
|
126
|
+
* [4]: There are some servers which use the memcached protocol but which are persistent (e.g. MemcacheDB, Kai, IronCache, ...)
|
|
127
|
+
* [5]: Depends on server
|
|
128
|
+
* [6]: Store is multi-process safe because it is an in-memory store, values are not shared between multiple processes
|
|
129
|
+
|
|
71
130
|
## Proxies
|
|
72
131
|
|
|
73
132
|
In addition it supports proxies (Similar to [Rack middlewares](http://rack.github.com/)) which
|
|
@@ -75,14 +134,15 @@ add additional features to storage backends:
|
|
|
75
134
|
|
|
76
135
|
* `Moneta::Proxy` and `Moneta::Wrapper` proxy base classes
|
|
77
136
|
* `Moneta::Expires` to add expiration support to stores which don't support it natively. Add it in the builder using `use :Expires`.
|
|
78
|
-
* `Moneta::Stack` to stack multiple stores (Read returns result from first where the key is found, writes go to all stores). Add it in the builder using `use
|
|
137
|
+
* `Moneta::Stack` to stack multiple stores (Read returns result from first where the key is found, writes go to all stores). Add it in the builder using `use(:Stack) {}`.
|
|
79
138
|
* `Moneta::Transformer` transforms keys and values (Marshal, YAML, JSON, Base64, MD5, ...). Add it in the builder using `use :Transformer`.
|
|
80
|
-
* `Moneta::Cache` combine two stores, one as backend and one as cache (e.g. `Moneta::Adapters::File` + `Moneta::Adapters::Memory`). Add it in the builder using `use
|
|
139
|
+
* `Moneta::Cache` combine two stores, one as backend and one as cache (e.g. `Moneta::Adapters::File` + `Moneta::Adapters::Memory`). Add it in the builder using `use(:Cache) {}`.
|
|
81
140
|
* `Moneta::Lock` to make store thread safe. Add it in the builder using `use :Lock`.
|
|
141
|
+
* `Moneta::Pool` to create a pool of stores as a means of making the store thread safe. Add it in the builder using `use(:Pool) {}`.
|
|
82
142
|
* `Moneta::Logger` to log database accesses. Add it in the builder using `use :Logger`.
|
|
83
|
-
* `Moneta::Shared` to share a store between multiple processes. Add it in the builder using `use
|
|
143
|
+
* `Moneta::Shared` to share a store between multiple processes. Add it in the builder using `use(:Shared) {}`.
|
|
84
144
|
|
|
85
|
-
|
|
145
|
+
### Serializers and compressors (`Moneta::Transformer`)
|
|
86
146
|
|
|
87
147
|
Supported serializers:
|
|
88
148
|
|
|
@@ -172,7 +232,7 @@ end
|
|
|
172
232
|
|
|
173
233
|
### Expiration
|
|
174
234
|
|
|
175
|
-
The Cassandra, Memcached and
|
|
235
|
+
The Cassandra, Memcached, Redis and Mongo backends supports expires values natively.
|
|
176
236
|
|
|
177
237
|
~~~ ruby
|
|
178
238
|
cache = Moneta::Adapters::Memcached.new
|
|
@@ -185,12 +245,21 @@ end
|
|
|
185
245
|
# Expires in 60 seconds
|
|
186
246
|
cache.store(key, value, :expires => 60)
|
|
187
247
|
|
|
248
|
+
# Never expire
|
|
249
|
+
cache.store(key, value, :expires => 0)
|
|
250
|
+
cache.store(key, value, :expires => false)
|
|
251
|
+
|
|
188
252
|
# Update expires time if value is found
|
|
189
253
|
cache.load(key, :expires => 30)
|
|
190
254
|
cache.key?(key, :expires => 30)
|
|
255
|
+
|
|
256
|
+
# Or remove the expiration if found
|
|
257
|
+
cache.load(key, :expires => false)
|
|
258
|
+
cache.key?(key, :expires => 0)
|
|
191
259
|
~~~
|
|
192
260
|
|
|
193
|
-
You can add the expires feature to other backends using the Expires proxy
|
|
261
|
+
You can add the expires feature to other backends using the `Moneta::Expires` proxy. But be aware
|
|
262
|
+
that expired values are not deleted automatically if they are not looked up.
|
|
194
263
|
|
|
195
264
|
~~~ ruby
|
|
196
265
|
# Using the :expires option
|
|
@@ -257,32 +326,6 @@ counters['counter'] = '10'
|
|
|
257
326
|
counters.increment('counter') # returns 11
|
|
258
327
|
~~~
|
|
259
328
|
|
|
260
|
-
Stores which support incrementation (you have to use `Moneta::Lock` if you want to use the store in a multithreading environment.)
|
|
261
|
-
|
|
262
|
-
* ActiveRecord
|
|
263
|
-
* File
|
|
264
|
-
* HBase
|
|
265
|
-
* LRUHash
|
|
266
|
-
* LevelDB
|
|
267
|
-
* Memcached
|
|
268
|
-
* Memory
|
|
269
|
-
* Redis
|
|
270
|
-
* SDBM/DBM/GDBM
|
|
271
|
-
* Sequel
|
|
272
|
-
* Sqlite
|
|
273
|
-
* TokyoCabinet
|
|
274
|
-
* YAML/PStore
|
|
275
|
-
|
|
276
|
-
Stores which don't support incrementation:
|
|
277
|
-
|
|
278
|
-
* Cassandra
|
|
279
|
-
* Couch
|
|
280
|
-
* DataMapper
|
|
281
|
-
* Fog
|
|
282
|
-
* LocalMemCache
|
|
283
|
-
* Mongo
|
|
284
|
-
* Riak
|
|
285
|
-
|
|
286
329
|
### Syntactic sugar and option merger
|
|
287
330
|
|
|
288
331
|
For raw data access as described before the class `Moneta::OptionMerger` is used. It works like this:
|
|
@@ -524,19 +567,15 @@ to compare the speed of the different key value stores for different key/value s
|
|
|
524
567
|
Feel free to add your own configurations! The impact of Moneta should be minimal since it is only a thin layer
|
|
525
568
|
on top of the different stores.
|
|
526
569
|
|
|
527
|
-
## More information
|
|
528
|
-
|
|
529
|
-
* http://yehudakatz.com/2009/02/12/whats-the-point/
|
|
530
|
-
* http://yehudakatz.com/2009/02/12/initial-release-of-moneta-unified-keyvalue-store-api/
|
|
531
|
-
|
|
532
570
|
## Alternatives
|
|
533
571
|
|
|
534
572
|
* [Horcrux](https://github.com/technoweenie/horcrux): Used at github, supports batch operations but only Memcached backend
|
|
573
|
+
* [ActiveSupport::Cache::Store](http://api.rubyonrails.org/classes/ActiveSupport/Cache/Store.html): The Rails cache store abstraction
|
|
535
574
|
* [ToyStore](https://github.com/jnunemaker/toystore): ORM mapper for key/value stores
|
|
536
575
|
* [ToyStore Adapter](https://github.com/jnunemaker/adapter): Adapter to key/value stores used by ToyStore, Moneta can be used directly with the ToyStore Memory adapter
|
|
537
576
|
|
|
538
577
|
## Authors
|
|
539
578
|
|
|
540
|
-
* Daniel Mendler
|
|
541
|
-
* Hannes Georg
|
|
542
|
-
* Originally by Yehuda Katz and contributors
|
|
579
|
+
* Daniel Mendler (@minad)
|
|
580
|
+
* Hannes Georg (@hannesg)
|
|
581
|
+
* Originally by Yehuda Katz (@wycats) and contributors
|
data/Rakefile
CHANGED
|
@@ -1,32 +1,47 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
rescue Exception
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
namespace :test do
|
|
13
|
-
task :parallel do
|
|
14
|
-
if defined?(JRUBY_VERSION)
|
|
15
|
-
puts 'No tests executed in parallel in JRuby'
|
|
16
|
-
else
|
|
17
|
-
specs = Dir['spec/*/*_spec.rb'].reject {|s| s =~ /memcached|redis|client|shared|riak/ }
|
|
18
|
-
sh("parallel_rspec -m 5 #{specs.join(' ')}")
|
|
1
|
+
def rspec(spec)
|
|
2
|
+
sh("rspec #{spec}")
|
|
3
|
+
true
|
|
4
|
+
rescue Exception => ex
|
|
5
|
+
if $?.termsig
|
|
6
|
+
sig = nil
|
|
7
|
+
Signal.list.each do |name, id|
|
|
8
|
+
if id == $?.termsig
|
|
9
|
+
sig = name
|
|
10
|
+
break
|
|
11
|
+
end
|
|
19
12
|
end
|
|
13
|
+
puts "\e[31m########## SIG#{sig} rspec #{spec} ##########\e[0m"
|
|
20
14
|
end
|
|
15
|
+
false
|
|
16
|
+
end
|
|
21
17
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
18
|
+
task :test do
|
|
19
|
+
# memcached and redis specs cannot be used in parallel
|
|
20
|
+
# because of flushing and namespace lacking in redis
|
|
21
|
+
specs = Dir['spec/*/*_spec.rb']
|
|
22
|
+
parallel = specs.reject {|s| s =~ /memcached|redis|client|shared|riak/ }
|
|
23
|
+
serial = specs - parallel
|
|
24
|
+
threads = []
|
|
25
|
+
failed = false
|
|
26
|
+
parallel.each do |spec|
|
|
27
|
+
threads << Thread.new do
|
|
28
|
+
begin
|
|
29
|
+
failed = true unless rspec(spec)
|
|
30
|
+
ensure
|
|
31
|
+
threads.delete Thread.current
|
|
32
|
+
end
|
|
29
33
|
end
|
|
34
|
+
sleep 0.1
|
|
35
|
+
sleep 0.1 while threads.size >= 20
|
|
36
|
+
end
|
|
37
|
+
sleep 0.1 until threads.empty?
|
|
38
|
+
serial.each do |spec|
|
|
39
|
+
failed = true unless rspec(spec)
|
|
40
|
+
end
|
|
41
|
+
if failed
|
|
42
|
+
fail "\e[31m########## MONETA TESTSUITE FAILED ##########\e[0m"
|
|
43
|
+
else
|
|
44
|
+
puts "\e[32m########## MONETA TESTSUITE SUCCEDED ##########\e[0m"
|
|
30
45
|
end
|
|
31
46
|
end
|
|
32
47
|
|
data/benchmarks/run.rb
CHANGED
|
@@ -5,12 +5,17 @@ require 'benchmark'
|
|
|
5
5
|
require 'moneta'
|
|
6
6
|
|
|
7
7
|
STORES = {
|
|
8
|
+
# SDBM is unstable
|
|
9
|
+
# :SDBM => { :file => 'bench.sdbm' },
|
|
10
|
+
# YAML is so fucking slow
|
|
11
|
+
# :YAML => { :file => 'bench.yaml' },
|
|
8
12
|
:ActiveRecord => { :connection => { :adapter => 'sqlite3', :database => ':memory:' } },
|
|
9
13
|
:Cassandra => {},
|
|
10
14
|
:Client => {},
|
|
11
15
|
:Couch => {},
|
|
12
16
|
:DBM => { :file => 'bench.dbm' },
|
|
13
17
|
:DataMapper => { :setup => 'sqlite3:bench.datamapper' },
|
|
18
|
+
:Daybreak => { :file => 'bench.daybreak' },
|
|
14
19
|
:File => { :dir => 'bench.file' },
|
|
15
20
|
:GDBM => { :file => 'bench.gdbm' },
|
|
16
21
|
:HBase => {},
|
|
@@ -24,13 +29,11 @@ STORES = {
|
|
|
24
29
|
:Mongo => {},
|
|
25
30
|
:PStore => { :file => 'bench.pstore' },
|
|
26
31
|
:Redis => {},
|
|
32
|
+
:RestClient => { :url => 'http://localhost:8808/' },
|
|
27
33
|
:Riak => {},
|
|
28
|
-
# SDBM is unstable
|
|
29
|
-
# :SDBM => { :file => 'bench.sdbm' },
|
|
30
34
|
:Sequel => { :db => 'sqlite:/' },
|
|
31
35
|
:Sqlite => { :file => ':memory:' },
|
|
32
|
-
|
|
33
|
-
# :YAML => { :file => 'bench.yaml' },
|
|
36
|
+
:TDB => { :file => 'bench.tdb' },
|
|
34
37
|
}
|
|
35
38
|
|
|
36
39
|
CONFIGS = {
|
|
@@ -129,7 +132,31 @@ Process.fork do
|
|
|
129
132
|
puts "\e[31mFailed to start Moneta server - #{ex.message}\e[0m"
|
|
130
133
|
end
|
|
131
134
|
end
|
|
132
|
-
|
|
135
|
+
|
|
136
|
+
Process.fork do
|
|
137
|
+
require 'rack'
|
|
138
|
+
require 'webrick'
|
|
139
|
+
require 'httpi'
|
|
140
|
+
require 'rack/moneta_rest'
|
|
141
|
+
|
|
142
|
+
# Keep webrick quiet
|
|
143
|
+
::WEBrick::HTTPServer.class_eval do
|
|
144
|
+
def access_log(config, req, res); end
|
|
145
|
+
end
|
|
146
|
+
::WEBrick::BasicLog.class_eval do
|
|
147
|
+
def log(level, data); end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
Rack::Server.start(:app => Rack::Builder.app do
|
|
151
|
+
use Rack::Lint
|
|
152
|
+
run Rack::MonetaRest.new(:store => :Memory)
|
|
153
|
+
end,
|
|
154
|
+
:environment => :none,
|
|
155
|
+
:server => :webrick,
|
|
156
|
+
:Port => 8808)
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
sleep 1 # Wait for servers
|
|
133
160
|
|
|
134
161
|
STORES.each do |name, options|
|
|
135
162
|
begin
|
|
@@ -143,6 +170,9 @@ STORES.each do |name, options|
|
|
|
143
170
|
elsif name == :Riak
|
|
144
171
|
require 'riak'
|
|
145
172
|
Riak.disable_list_keys_warnings = true
|
|
173
|
+
elsif name == :RestClient
|
|
174
|
+
require 'httpi'
|
|
175
|
+
HTTPI.log = false
|
|
146
176
|
end
|
|
147
177
|
|
|
148
178
|
cache = Moneta.new(name, options.dup)
|