moneta 0.7.8 → 0.7.9
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +1 -0
- data/CHANGES +6 -0
- data/Gemfile +1 -0
- data/README.md +107 -40
- data/SPEC.md +8 -0
- data/lib/moneta.rb +6 -7
- data/lib/moneta/adapters/activerecord.rb +2 -0
- data/lib/moneta/adapters/client.rb +9 -0
- data/lib/moneta/adapters/datamapper.rb +2 -0
- data/lib/moneta/adapters/file.rb +2 -0
- data/lib/moneta/adapters/kyotocabinet.rb +39 -0
- data/lib/moneta/adapters/lruhash.rb +1 -1
- data/lib/moneta/adapters/memcached/dalli.rb +3 -5
- data/lib/moneta/adapters/memcached/native.rb +2 -0
- data/lib/moneta/adapters/mongo.rb +2 -0
- data/lib/moneta/adapters/pstore.rb +2 -0
- data/lib/moneta/adapters/redis.rb +3 -3
- data/lib/moneta/adapters/sequel.rb +2 -0
- data/lib/moneta/adapters/sqlite.rb +2 -0
- data/lib/moneta/adapters/tokyocabinet.rb +2 -3
- data/lib/moneta/adapters/yaml.rb +1 -1
- data/lib/moneta/cache.rb +5 -0
- data/lib/moneta/expires.rb +1 -0
- data/lib/moneta/mixins.rb +68 -1
- data/lib/moneta/proxy.rb +5 -0
- data/lib/moneta/server.rb +1 -1
- data/lib/moneta/stack.rb +16 -0
- data/lib/moneta/synchronize.rb +3 -1
- data/lib/moneta/version.rb +1 -1
- data/lib/moneta/weak.rb +15 -1
- data/lib/moneta/wrapper.rb +5 -0
- data/script/benchmarks +2 -0
- data/script/generate-specs +64 -37
- data/script/install-bundle +2 -1
- data/script/install-kyotocabinet +17 -0
- data/spec/moneta/adapter_activerecord_spec.rb +5 -0
- data/spec/moneta/adapter_cassandra_spec.rb +5 -0
- data/spec/moneta/adapter_cassandra_with_default_expires_spec.rb +5 -0
- data/spec/moneta/adapter_client_spec.rb +5 -0
- data/spec/moneta/adapter_cookie_spec.rb +5 -0
- data/spec/moneta/adapter_couch_spec.rb +5 -0
- data/spec/moneta/adapter_datamapper_spec.rb +5 -0
- data/spec/moneta/adapter_daybreak_spec.rb +5 -0
- data/spec/moneta/adapter_dbm_spec.rb +5 -0
- data/spec/moneta/adapter_file_spec.rb +5 -0
- data/spec/moneta/adapter_fog_spec.rb +5 -0
- data/spec/moneta/adapter_gdbm_spec.rb +5 -0
- data/spec/moneta/adapter_hbase_spec.rb +5 -0
- data/spec/moneta/adapter_kyotocabinet_spec.rb +29 -0
- data/spec/moneta/adapter_leveldb_spec.rb +5 -0
- data/spec/moneta/adapter_localmemcache_spec.rb +5 -0
- data/spec/moneta/adapter_lruhash_spec.rb +5 -0
- data/spec/moneta/adapter_memcached_dalli_spec.rb +5 -0
- data/spec/moneta/adapter_memcached_dalli_with_default_expires_spec.rb +5 -0
- data/spec/moneta/adapter_memcached_native_spec.rb +5 -0
- data/spec/moneta/adapter_memcached_native_with_default_expires_spec.rb +5 -0
- data/spec/moneta/adapter_memcached_spec.rb +5 -0
- data/spec/moneta/adapter_memcached_with_default_expires_spec.rb +5 -0
- data/spec/moneta/adapter_memory_spec.rb +5 -0
- data/spec/moneta/adapter_mongo_spec.rb +5 -0
- data/spec/moneta/adapter_mongo_with_default_expires_spec.rb +5 -0
- data/spec/moneta/adapter_pstore_spec.rb +5 -0
- data/spec/moneta/adapter_redis_spec.rb +5 -0
- data/spec/moneta/adapter_redis_with_default_expires_spec.rb +5 -0
- data/spec/moneta/adapter_restclient_spec.rb +5 -0
- data/spec/moneta/adapter_riak_spec.rb +5 -0
- data/spec/moneta/adapter_sdbm_spec.rb +5 -0
- data/spec/moneta/adapter_sequel_spec.rb +5 -0
- data/spec/moneta/adapter_sqlite_spec.rb +5 -0
- data/spec/moneta/adapter_tdb_spec.rb +5 -0
- data/spec/moneta/adapter_tokyocabinet_bdb_spec.rb +5 -0
- data/spec/moneta/adapter_tokyocabinet_hdb_spec.rb +5 -0
- data/spec/moneta/adapter_yaml_spec.rb +5 -0
- data/spec/moneta/cache_file_memory_spec.rb +5 -0
- data/spec/moneta/cache_memory_null_spec.rb +5 -0
- data/spec/moneta/expires_file_spec.rb +5 -0
- data/spec/moneta/expires_memory_spec.rb +5 -0
- data/spec/moneta/expires_memory_with_default_expires_spec.rb +5 -0
- data/spec/moneta/lock_spec.rb +5 -0
- data/spec/moneta/mutex_spec.rb +4 -0
- data/spec/moneta/null_adapter_spec.rb +4 -0
- data/spec/moneta/optionmerger_spec.rb +8 -0
- data/spec/moneta/pool_spec.rb +5 -0
- data/spec/moneta/proxy_expires_memory_spec.rb +5 -0
- data/spec/moneta/proxy_redis_spec.rb +5 -0
- data/spec/moneta/semaphore_spec.rb +4 -0
- data/spec/moneta/shared_tcp_spec.rb +5 -0
- data/spec/moneta/shared_unix_spec.rb +5 -0
- data/spec/moneta/simple_activerecord_spec.rb +5 -0
- data/spec/moneta/simple_activerecord_with_expires_spec.rb +5 -0
- data/spec/moneta/simple_cassandra_spec.rb +5 -0
- data/spec/moneta/simple_client_tcp_spec.rb +5 -0
- data/spec/moneta/simple_client_unix_spec.rb +5 -0
- data/spec/moneta/simple_couch_spec.rb +5 -0
- data/spec/moneta/simple_couch_with_expires_spec.rb +5 -0
- data/spec/moneta/simple_datamapper_spec.rb +5 -0
- data/spec/moneta/simple_datamapper_with_expires_spec.rb +5 -0
- data/spec/moneta/simple_datamapper_with_repository_spec.rb +5 -0
- data/spec/moneta/simple_daybreak_spec.rb +5 -0
- data/spec/moneta/simple_daybreak_with_expires_spec.rb +5 -0
- data/spec/moneta/simple_dbm_spec.rb +5 -0
- data/spec/moneta/simple_dbm_with_expires_spec.rb +5 -0
- data/spec/moneta/simple_file_spec.rb +5 -0
- data/spec/moneta/simple_file_with_expires_spec.rb +5 -0
- data/spec/moneta/simple_fog_spec.rb +5 -0
- data/spec/moneta/simple_fog_with_expires_spec.rb +5 -0
- data/spec/moneta/simple_gdbm_spec.rb +5 -0
- data/spec/moneta/simple_gdbm_with_expires_spec.rb +5 -0
- data/spec/moneta/simple_hashfile_spec.rb +5 -0
- data/spec/moneta/simple_hashfile_with_expires_spec.rb +5 -0
- data/spec/moneta/simple_hbase_spec.rb +5 -0
- data/spec/moneta/simple_hbase_with_expires_spec.rb +5 -0
- data/spec/moneta/simple_kyotocabinet_spec.rb +154 -0
- data/spec/moneta/simple_kyotocabinet_with_expires_spec.rb +156 -0
- data/spec/moneta/simple_leveldb_spec.rb +5 -0
- data/spec/moneta/simple_leveldb_with_expires_spec.rb +5 -0
- data/spec/moneta/simple_localmemcache_spec.rb +5 -0
- data/spec/moneta/simple_localmemcache_with_expires_spec.rb +5 -0
- data/spec/moneta/simple_lruhash_spec.rb +5 -0
- data/spec/moneta/simple_lruhash_with_expires_spec.rb +5 -0
- data/spec/moneta/simple_memcached_dalli_spec.rb +5 -0
- data/spec/moneta/simple_memcached_native_spec.rb +5 -0
- data/spec/moneta/simple_memcached_spec.rb +5 -0
- data/spec/moneta/simple_memory_spec.rb +5 -0
- data/spec/moneta/simple_memory_with_compress_spec.rb +5 -0
- data/spec/moneta/simple_memory_with_expires_spec.rb +5 -0
- data/spec/moneta/simple_memory_with_json_key_serializer_spec.rb +5 -0
- data/spec/moneta/simple_memory_with_json_serializer_spec.rb +5 -0
- data/spec/moneta/simple_memory_with_json_value_serializer_spec.rb +5 -0
- data/spec/moneta/simple_memory_with_prefix_spec.rb +5 -0
- data/spec/moneta/simple_memory_with_snappy_compress_spec.rb +5 -0
- data/spec/moneta/simple_mongo_spec.rb +5 -0
- data/spec/moneta/simple_null_spec.rb +5 -0
- data/spec/moneta/simple_pstore_spec.rb +5 -0
- data/spec/moneta/simple_pstore_with_expires_spec.rb +5 -0
- data/spec/moneta/simple_redis_spec.rb +5 -0
- data/spec/moneta/simple_restclient_spec.rb +5 -0
- data/spec/moneta/simple_riak_spec.rb +5 -0
- data/spec/moneta/simple_riak_with_expires_spec.rb +5 -0
- data/spec/moneta/simple_sdbm_spec.rb +5 -0
- data/spec/moneta/simple_sdbm_with_expires_spec.rb +5 -0
- data/spec/moneta/simple_sequel_spec.rb +5 -0
- data/spec/moneta/simple_sequel_with_expires_spec.rb +5 -0
- data/spec/moneta/simple_sqlite_spec.rb +5 -0
- data/spec/moneta/simple_sqlite_with_expires_spec.rb +5 -0
- data/spec/moneta/simple_tdb_spec.rb +5 -0
- data/spec/moneta/simple_tdb_with_expires_spec.rb +5 -0
- data/spec/moneta/simple_tokyocabinet_spec.rb +5 -0
- data/spec/moneta/simple_tokyocabinet_with_expires_spec.rb +5 -0
- data/spec/moneta/simple_yaml_spec.rb +5 -0
- data/spec/moneta/simple_yaml_with_expires_spec.rb +5 -0
- data/spec/moneta/stack_file_memory_spec.rb +5 -0
- data/spec/moneta/stack_memory_file_spec.rb +7 -4
- data/spec/moneta/transformer_bencode_spec.rb +5 -0
- data/spec/moneta/transformer_bert_spec.rb +5 -0
- data/spec/moneta/transformer_bson_spec.rb +5 -0
- data/spec/moneta/transformer_bzip2_spec.rb +5 -0
- data/spec/moneta/transformer_json_spec.rb +5 -0
- data/spec/moneta/transformer_key_inspect_spec.rb +5 -0
- data/spec/moneta/transformer_key_marshal_spec.rb +5 -0
- data/spec/moneta/transformer_key_to_s_spec.rb +5 -0
- data/spec/moneta/transformer_key_yaml_spec.rb +5 -0
- data/spec/moneta/transformer_lzma_spec.rb +5 -0
- data/spec/moneta/transformer_lzo_spec.rb +5 -0
- data/spec/moneta/transformer_marshal_base64_spec.rb +5 -0
- data/spec/moneta/transformer_marshal_escape_spec.rb +5 -0
- data/spec/moneta/transformer_marshal_hmac_spec.rb +5 -0
- data/spec/moneta/transformer_marshal_md5_spec.rb +5 -0
- data/spec/moneta/transformer_marshal_md5_spread_spec.rb +5 -0
- data/spec/moneta/transformer_marshal_prefix_spec.rb +5 -0
- data/spec/moneta/transformer_marshal_rmd160_spec.rb +5 -0
- data/spec/moneta/transformer_marshal_sha1_spec.rb +5 -0
- data/spec/moneta/transformer_marshal_sha256_spec.rb +5 -0
- data/spec/moneta/transformer_marshal_sha384_spec.rb +5 -0
- data/spec/moneta/transformer_marshal_sha512_spec.rb +5 -0
- data/spec/moneta/transformer_marshal_spec.rb +5 -0
- data/spec/moneta/transformer_marshal_truncate_spec.rb +5 -0
- data/spec/moneta/transformer_marshal_uuencode_spec.rb +5 -0
- data/spec/moneta/transformer_msgpack_spec.rb +5 -0
- data/spec/moneta/transformer_ox_spec.rb +5 -0
- data/spec/moneta/transformer_quicklz_spec.rb +5 -0
- data/spec/moneta/transformer_snappy_spec.rb +5 -0
- data/spec/moneta/transformer_tnet_spec.rb +5 -0
- data/spec/moneta/transformer_value_marshal_spec.rb +5 -0
- data/spec/moneta/transformer_value_yaml_spec.rb +5 -0
- data/spec/moneta/transformer_yaml_spec.rb +5 -0
- data/spec/moneta/transformer_zlib_spec.rb +5 -0
- data/spec/moneta/weak_create_spec.rb +10 -91
- data/spec/moneta/weak_increment_spec.rb +10 -91
- data/spec/monetaspecs.rb +19 -0
- metadata +10 -2
data/.travis.yml
CHANGED
data/CHANGES
CHANGED
data/Gemfile
CHANGED
@@ -42,6 +42,7 @@ gem 'cassandra'
|
|
42
42
|
gem 'tdb', :platforms => :ruby
|
43
43
|
gem 'leveldb-ruby', :platforms => :ruby
|
44
44
|
gem 'tokyocabinet', :platforms => :ruby
|
45
|
+
gem 'kyotocabinet-ruby', :platforms => :ruby, :github => 'minad/kyotocabinet-ruby'
|
45
46
|
gem 'memcached', :platforms => :ruby
|
46
47
|
gem 'jruby-memcached', :platforms => :jruby
|
47
48
|
gem 'sqlite3', :platforms => :ruby
|
data/README.md
CHANGED
@@ -29,6 +29,8 @@ same for template languages.
|
|
29
29
|
|
30
30
|
Moneta is tested thoroughly using [Travis-CI](http://travis-ci.org/minad/moneta).
|
31
31
|
|
32
|
+
------
|
33
|
+
|
32
34
|
## Getting started
|
33
35
|
|
34
36
|
Install Moneta via Rubygems
|
@@ -61,14 +63,19 @@ store['key'] # returns 'value'
|
|
61
63
|
store.close
|
62
64
|
~~~
|
63
65
|
|
66
|
+
------
|
67
|
+
|
64
68
|
## Links
|
65
69
|
|
66
70
|
* Source: <http://github.com/minad/moneta>
|
67
71
|
* Bugs: <http://github.com/minad/moneta/issues>
|
72
|
+
* Tests and benchmarks: <http://travis-ci.org/minad/moneta>
|
68
73
|
* API documentation:
|
69
74
|
* Latest Gem: <http://rubydoc.info/gems/moneta/frames>
|
70
75
|
* GitHub master: <http://rubydoc.info/github/minad/moneta/master/frames>
|
71
76
|
|
77
|
+
------
|
78
|
+
|
72
79
|
## Supported backends
|
73
80
|
|
74
81
|
Out of the box, it supports the following backends. Use the backend name symbol in the Moneta constructor (e.g. `Moneta.new(:Memory)`).
|
@@ -98,6 +105,7 @@ Out of the box, it supports the following backends. Use the backend name symbol
|
|
98
105
|
* [Redis](http://redis.io/) (`:Redis`)
|
99
106
|
* [Riak](http://docs.basho.com/) (`:Riak`)
|
100
107
|
* [SDBM](http://www.ruby-doc.org/stdlib/libdoc/sdbm/rdoc/SDBM.html) (`:SDBM`)
|
108
|
+
* [KyotoCabinet](http://fallabs.com/kyotocabinet/) (`:KyotoCabinet`)
|
101
109
|
* [TokyoCabinet](http://fallabs.com/tokyocabinet/) (`:TokyoCabinet`)
|
102
110
|
* [Simple Samba database TDB](http://tdb.samba.org/) (`:TDB`)
|
103
111
|
* Document databases:
|
@@ -117,53 +125,94 @@ to upgrade to a real key/value store.
|
|
117
125
|
|
118
126
|
### Backend feature matrix
|
119
127
|
|
128
|
+
__NOTE:__ <a name="backend-matrix">The backend matrix</a> is much more readable on rubydoc.info than on github. [Go there!](http://rubydoc.info/github/minad/moneta/master/file/README.md#backend-matrix)
|
129
|
+
|
120
130
|
<table>
|
121
|
-
|
122
|
-
<
|
123
|
-
|
124
|
-
<tr><
|
125
|
-
|
126
|
-
<tr><td>
|
127
|
-
|
128
|
-
<tr><td>
|
129
|
-
|
130
|
-
<tr><td>
|
131
|
-
|
132
|
-
<tr><td>
|
133
|
-
|
134
|
-
<tr><td>
|
135
|
-
|
136
|
-
<tr><td>
|
137
|
-
|
138
|
-
<tr><td>
|
139
|
-
|
140
|
-
<tr><td>
|
141
|
-
|
142
|
-
<tr><td>
|
143
|
-
|
144
|
-
<tr><td>
|
145
|
-
|
146
|
-
<tr><td>
|
147
|
-
|
148
|
-
<tr><td>
|
149
|
-
|
150
|
-
<tr><td>
|
151
|
-
|
152
|
-
<tr><td>
|
153
|
-
|
154
|
-
</
|
131
|
+
|
132
|
+
<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<sup>[8]</sup></th><th>Atomic create<sup>[9]</sup></th><th>Native expires<sup>[3]</sup></th><th>Persistent</th><th>Description</th></tr>
|
133
|
+
|
134
|
+
<tr><th colspan="2">Persistent stores</th><th colspan="7"></th></tr>
|
135
|
+
|
136
|
+
<tr><td>Mongo</td><td>mongo</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td><a href="http://www.mongodb.org/">MongoDB</a> database</td></tr>
|
137
|
+
|
138
|
+
<tr><td>Redis</td><td>redis</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td><a href="http://redis.io/">Redis</a> database</td></tr>
|
139
|
+
|
140
|
+
<tr><td>ActiveRecord</td><td>activerecord</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</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><a href="https://rubygems.org/gems/activerecord">ActiveRecord</a> ORM</td></tr>
|
141
|
+
|
142
|
+
<tr><td>File</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:#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>File store</td></tr>
|
143
|
+
|
144
|
+
<tr><td>Sequel</td><td>sequel</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</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><a href="http://sequel.rubyforge.org/">Sequel</a> ORM</td></tr>
|
145
|
+
|
146
|
+
<tr><td>Sqlite</td><td>sqlite3</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:#5F5">✓</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td><a href="http://sqlite.org/">Sqlite3</a> database</td></tr>
|
147
|
+
|
148
|
+
<tr><td>PStore</td><td>-</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 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://ruby-doc.org/stdlib/libdoc/pstore/rdoc/PStore.html">PStore</a> store</td></tr>
|
149
|
+
|
150
|
+
<tr><td>YAML</td><td>-</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 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://www.ruby-doc.org/stdlib/libdoc/yaml/rdoc/YAML/Store.html">YAML</a> store</td></tr>
|
151
|
+
|
152
|
+
<tr><td>Daybreak</td><td>daybreak</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#55F">(✓)<sup>[7]</sup></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>Incredibly fast pure-ruby key/value store <a href="http://propublica.github.com/daybreak/">Daybreak</a></td></tr>
|
153
|
+
|
154
|
+
<tr><td>DBM</td><td>-</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 style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td><a href="http://www.ruby-doc.org/stdlib/libdoc/dbm/rdoc/DBM.html">Berkeley DB</a></td></tr>
|
155
|
+
|
156
|
+
<tr><td>GDBM</td><td>-</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 style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td><a href="http://www.ruby-doc.org/stdlib/libdoc/gdbm/rdoc/GDBM.html">GDBM</a> database</td></tr>
|
157
|
+
|
158
|
+
<tr><td>LevelDB</td><td>leveldb</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 style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td><a href="http://code.google.com/p/leveldb/">LevelDB</a> database</td></tr>
|
159
|
+
|
160
|
+
<tr><td>SDBM</td><td>-</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 style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td><a href="http://www.ruby-doc.org/stdlib/libdoc/sdbm/rdoc/SDBM.html">SDBM</a> database</td></tr>
|
161
|
+
|
162
|
+
<tr><td>TDB</td><td>tdb</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 style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td><a href="http://tdb.samba.org/">TDB</a> database</td></tr>
|
163
|
+
|
164
|
+
<tr><td>KyotoCabinet</td><td>tokoycabinet</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 style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td><a href="http://fallabs.com/kyotocabinet/">KyotoCabinet</a> database</td></tr>
|
165
|
+
|
166
|
+
<tr><td>TokyoCabinet</td><td>tokoycabinet</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 style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td><a href="http://fallabs.com/tokyocabinet/">TokyoCabinet</a> database</td></tr>
|
167
|
+
|
168
|
+
<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>
|
169
|
+
|
170
|
+
<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>
|
171
|
+
|
172
|
+
<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>
|
173
|
+
|
174
|
+
<tr><td>Couch</td><td>couchrest</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://couchdb.apache.org/">CouchDB</a> database</td></tr>
|
175
|
+
|
176
|
+
<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>
|
177
|
+
|
178
|
+
<tr><td>HBase</td><td>hbase</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://hbase.apache.org/">HBase</a> database</td></tr>
|
179
|
+
|
180
|
+
<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>
|
181
|
+
|
182
|
+
<tr><th colspan="2">Non persistent stores</th><th colspan="7"></th></tr>
|
183
|
+
|
184
|
+
<tr><td>MemcachedDalli</td><td>dalli</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#F44">✗<sup>[4]</sup></td><td><a href="http://memcached.org/">Memcached</a> database with Dalli library</td></tr>
|
185
|
+
|
186
|
+
<tr><td>Memcached</td><td>dalli or memcached</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:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#F44">✗<sup>[4]</sup></td><td><a href="http://memcached.org/">Memcached</a> database</td></tr>
|
187
|
+
|
188
|
+
<tr><td>MemcachedNative</td><td>memcached</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 style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#F44">✗<sup>[4]</sup></td><td>Memcached database with native library</td></tr>
|
189
|
+
|
190
|
+
<tr><td>Cookie</td><td>-</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#55F">(✓)<sup>[6]</sup></td><td style="text-align:center;background:#5F5">✓</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>Cookie in memory store</td></tr>
|
191
|
+
|
192
|
+
<tr><td>LRUHash</td><td>-</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#55F">(✓)<sup>[6]</sup></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>LRU memory store</td></tr>
|
193
|
+
|
194
|
+
<tr><td>Memory</td><td>-</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#55F">(✓)<sup>[6]</sup></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>Memory store</td></tr>
|
195
|
+
|
196
|
+
<tr><td>Null</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:#F44">✗</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#F44">✗</td><td>No database</td></tr>
|
197
|
+
|
198
|
+
<tr><td>Client</td><td>-</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>[5]</sup></td><td style="text-align:center;background:#55F">?<sup>[5]</sup></td><td style="text-align:center;background:#55F">?<sup>[5]</sup></td><td style="text-align:center;background:#55F">?<sup>[5]</sup></td><td>Moneta client adapter</td></tr>
|
199
|
+
|
200
|
+
<tr><td>RestClient</td><td>-</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>[5]</sup></td><td>Moneta REST client adapter</td></tr>
|
201
|
+
|
155
202
|
</table>
|
156
203
|
|
157
204
|
* [1]: Make adapters thread-safe by using `Moneta::Lock` or by passing the option `:threadsafe => true` to `Moneta#new`. There is also `Moneta::Pool` which can be used to share a store between multiple threads if the store is multi-process safe. I recommend to add the option `:threadsafe` to ensure thread-safety since for example under JRuby and Rubinius even the basic datastructures are not thread safe due to the lack of a global interpreter lock (GIL). This differs from MRI where some adapters might appear thread safe already but only due to the GIL.
|
158
205
|
* [2]: Share a Moneta store between multiple processes using `Moneta::Shared` (See below).
|
159
206
|
* [3]: Add expiration support by using `Moneta::Expires` or by passing the option `:expires => true` to `Moneta#new`.
|
160
|
-
* [4]: There are some servers which use the memcached protocol but which are persistent (e.g. [MemcacheDB](http://memcachedb.org/), [Kai](http://sourceforge.net/apps/mediawiki/kai), [IronCache](http://dev.iron.io/cache/reference/memcache/))
|
207
|
+
* [4]: There are some servers which use the memcached protocol but which are persistent (e.g. [MemcacheDB](http://memcachedb.org/), [Kai](http://sourceforge.net/apps/mediawiki/kai), [IronCache](http://dev.iron.io/cache/reference/memcache/), [Roma](https://github.com/roma/roma/tree))
|
161
208
|
* [5]: Depends on server
|
162
209
|
* [6]: Store is multi-process safe because it is an in-memory store, values are not shared between multiple processes
|
163
210
|
* [7]: Store is multi-process safe, but not synchronized automatically between multiple processes
|
164
211
|
* [8]: If a store provides atomic increment it can be used with `Moneta::Semaphore`. You can add weak `#increment` using the `Moneta::WeakIncrement` proxy.
|
165
212
|
* [8]: If a store provides atomic creation it can be used with `Moneta::Mutex`. You can add weak `#create` using the `Moneta::WeakCreate` proxy.
|
166
213
|
|
214
|
+
------
|
215
|
+
|
167
216
|
## Proxies
|
168
217
|
|
169
218
|
In addition it supports proxies (Similar to [Rack middlewares](http://rack.github.com/)) which
|
@@ -208,11 +257,13 @@ Special transformers:
|
|
208
257
|
* Add prefix to keys (`:prefix`)
|
209
258
|
* HMAC to verify values (`:hmac`, useful for `Rack::MonetaCookies`)
|
210
259
|
|
260
|
+
------
|
261
|
+
|
211
262
|
## Moneta API
|
212
263
|
|
213
264
|
The Moneta API is purposely extremely similar to the Hash API with a few minor additions.
|
214
|
-
|
215
|
-
|
265
|
+
Every method takes also a optional option hash. In order so support an identical API across stores,
|
266
|
+
Moneta does not support iteration or partial matches.
|
216
267
|
|
217
268
|
~~~
|
218
269
|
#initialize(options) options differs per-store, and is used to set up the store.
|
@@ -248,6 +299,10 @@ option hash. In order so support an identical API across stores, Moneta does not
|
|
248
299
|
#clear(options = {}) clear all keys in this store.
|
249
300
|
|
250
301
|
#close close database connection.
|
302
|
+
|
303
|
+
#features return array of features, e.g. [:create, :expires, :increment]
|
304
|
+
|
305
|
+
#supports?(feature) returns true if store supports a given feature
|
251
306
|
~~~
|
252
307
|
|
253
308
|
### Creating a Store
|
@@ -384,7 +439,7 @@ store.create('key', 'other value') # returns false
|
|
384
439
|
Moneta provides shared/distributed synchronization primitives which are shared database-wide between
|
385
440
|
all clients.
|
386
441
|
|
387
|
-
|
442
|
+
`Moneta::Mutex` allows a single thread to enter a critical section.
|
388
443
|
|
389
444
|
~~~ ruby
|
390
445
|
mutex = Moneta::Mutex.new(store, 'mutex_key')
|
@@ -405,7 +460,7 @@ ensure
|
|
405
460
|
end
|
406
461
|
~~~
|
407
462
|
|
408
|
-
|
463
|
+
`Moneta::Semaphore` allows `max_concurrent` threads to enter a critical section.
|
409
464
|
|
410
465
|
~~~ ruby
|
411
466
|
semaphore = Moneta::Semaphore.new(store, 'semaphore_counter', max_concurrent)
|
@@ -471,6 +526,8 @@ store['key'] = 'this value will not be compressed'
|
|
471
526
|
compressed_store['key'] = 'value will be compressed'
|
472
527
|
~~~
|
473
528
|
|
529
|
+
------
|
530
|
+
|
474
531
|
## Framework Integration
|
475
532
|
|
476
533
|
Inspired by [redis-store](https://github.com/jodosha/redis-store) there exist integration classes for [Rails](http://rubyonrails.org/) and [Rack](http://rack.github.com/)/[Rack-Cache](https://github.com/rtomayko/rack-cache). You can also use all the Rack middlewares together with Rails and the [Sinatra](http://sinatrarb.com/) framework. There exist the following integration classes:
|
@@ -637,6 +694,8 @@ config.cache_store :moneta_store, :store => Moneta.build do
|
|
637
694
|
end
|
638
695
|
~~~
|
639
696
|
|
697
|
+
------
|
698
|
+
|
640
699
|
## Advanced
|
641
700
|
|
642
701
|
### Build your own key value server
|
@@ -684,6 +743,8 @@ add persistence using Moneta as follows:
|
|
684
743
|
Person.adapter :memory, Moneta.new(:Redis)
|
685
744
|
~~~
|
686
745
|
|
746
|
+
------
|
747
|
+
|
687
748
|
## Testing and Benchmarks
|
688
749
|
|
689
750
|
Testing is done using [Travis-CI](http://travis-ci.org/minad/moneta). Currently we support Ruby 1.8.7 and 1.9.3.
|
@@ -693,13 +754,19 @@ to compare the speed of the different key value stores for different key/value s
|
|
693
754
|
Feel free to add your own configurations! The impact of Moneta should be minimal since it is only a thin layer
|
694
755
|
on top of the different stores.
|
695
756
|
|
757
|
+
------
|
758
|
+
|
696
759
|
## Alternatives
|
697
760
|
|
698
761
|
* [Horcrux](https://github.com/technoweenie/horcrux): Used at github, supports batch operations but only Memcached backend
|
699
762
|
* [ActiveSupport::Cache::Store](http://api.rubyonrails.org/classes/ActiveSupport/Cache/Store.html): The Rails cache store abstraction
|
700
|
-
* [Padrino::Cache::Store](http://www.padrinorb.com/api/Padrino/Cache/Store.html): The Padrino cache store abstraction
|
763
|
+
* [Padrino::Cache::Store](http://www.padrinorb.com/api/Padrino/Cache/Store.html): The Padrino cache store abstraction. Padrino is currently considering switching to Moneta, see https://github.com/padrino/padrino-framework/pull/1018
|
701
764
|
* [ToyStore](https://github.com/jnunemaker/toystore): ORM mapper for key/value stores
|
702
765
|
* [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
|
766
|
+
* [Cache](https://github.com/seamusabshere/cache): Rubygem cache wraps Memcached and Redis
|
767
|
+
* [Ramaze::Cache](http://ramaze.net/documentation/Innate/Cache.html): Cache stores of the Ramaze framework with support for LocalMemCache, Memcached, Sequel, Redis, ...
|
768
|
+
|
769
|
+
------
|
703
770
|
|
704
771
|
## Authors
|
705
772
|
|
data/SPEC.md
CHANGED
@@ -59,6 +59,14 @@ It MUST return true if the value was created.
|
|
59
59
|
|
60
60
|
Completely empty all keys and values from the key-value-store. Adapters MAY allow a namespace during initialization, which can scope this operation to a particular subset of keys. After calling <code>clear</code>, a <code>[]</code> operation MUST return nil for every possible key, and a <code>key?</code> query MUST return false for every possible key.
|
61
61
|
|
62
|
+
### <code>close</code>
|
63
|
+
|
64
|
+
Closes the store
|
65
|
+
|
66
|
+
### <code>features => Array<Symbol></code> and <code>supports?(Symbol) => [TrueClass, FalseClass]</code>
|
67
|
+
|
68
|
+
Feature detection. Adapters MUST return <code>:create</code> and <code>:increment</code> if these methods are supported.
|
69
|
+
|
62
70
|
## Additional Options Hashes
|
63
71
|
|
64
72
|
The following methods may all take an additional Hash as a final argument. This allows the client to send additional options which can be specified by the adapter (and which may be specified by extensions to this specification). The methods MUST NOT modify the supplied option hash.
|
data/lib/moneta.rb
CHANGED
@@ -39,6 +39,7 @@ module Moneta
|
|
39
39
|
autoload :GDBM, 'moneta/adapters/gdbm'
|
40
40
|
autoload :HBase, 'moneta/adapters/hbase'
|
41
41
|
autoload :LRUHash, 'moneta/adapters/lruhash'
|
42
|
+
autoload :KyotoCabinet, 'moneta/adapters/kyotocabinet'
|
42
43
|
autoload :LevelDB, 'moneta/adapters/leveldb'
|
43
44
|
autoload :LocalMemCache, 'moneta/adapters/localmemcache'
|
44
45
|
autoload :Memcached, 'moneta/adapters/memcached'
|
@@ -88,7 +89,8 @@ module Moneta
|
|
88
89
|
#
|
89
90
|
# @api public
|
90
91
|
def self.new(name, options = {})
|
91
|
-
expires = options
|
92
|
+
expires = options[:expires]
|
93
|
+
options.delete(:expires) unless Integer === expires
|
92
94
|
logger = options.delete(:logger)
|
93
95
|
threadsafe = options.delete(:threadsafe)
|
94
96
|
compress = options.delete(:compress)
|
@@ -118,17 +120,14 @@ module Moneta
|
|
118
120
|
when :File
|
119
121
|
# Use escaping
|
120
122
|
transformer[:key] << :escape
|
121
|
-
when :Cassandra, :Redis, :Mongo, :Memcached, :MemcachedDalli, :MemcachedNative
|
122
|
-
# Expires already supported
|
123
|
-
options[:expires] = expires if Integer === expires
|
124
|
-
expires = false
|
125
123
|
end
|
124
|
+
a = Adapters.const_get(name).new(options)
|
126
125
|
build do
|
127
126
|
use :Logger, Hash === logger ? logger : {} if logger
|
128
|
-
use :Expires, :expires =>
|
127
|
+
use :Expires, :expires => options[:expires] if !a.supports?(:expires) && expires
|
129
128
|
use :Transformer, transformer
|
130
129
|
use :Lock if threadsafe
|
131
|
-
adapter
|
130
|
+
adapter a
|
132
131
|
end
|
133
132
|
end
|
134
133
|
|
data/lib/moneta/adapters/file.rb
CHANGED
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'kyotocabinet'
|
2
|
+
|
3
|
+
module Moneta
|
4
|
+
module Adapters
|
5
|
+
# KyotoCabinet backend
|
6
|
+
# @api public
|
7
|
+
class KyotoCabinet < Memory
|
8
|
+
# @param [Hash] options
|
9
|
+
# @option options [String] :file Database file
|
10
|
+
def initialize(options = {})
|
11
|
+
raise ArgumentError, 'Option :file is required' unless options[:file]
|
12
|
+
@hash = ::KyotoCabinet::DB.new
|
13
|
+
raise @hash.error.to_s unless @hash.open(options[:file],
|
14
|
+
::KyotoCabinet::DB::OWRITER | ::KyotoCabinet::DB::OCREATE)
|
15
|
+
end
|
16
|
+
|
17
|
+
# (see Proxy#key?)
|
18
|
+
def key?(key, options = {})
|
19
|
+
@hash.check(key) >= 0
|
20
|
+
end
|
21
|
+
|
22
|
+
# (see Proxy#delete)
|
23
|
+
def delete(key, options = {})
|
24
|
+
@hash.seize(key)
|
25
|
+
end
|
26
|
+
|
27
|
+
# (see Proxy#create)
|
28
|
+
def create(key, value, options = {})
|
29
|
+
@hash.add(key, value)
|
30
|
+
end
|
31
|
+
|
32
|
+
# (see Proxy#close)
|
33
|
+
def close
|
34
|
+
@hash.close
|
35
|
+
nil
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -2,7 +2,7 @@ module Moneta
|
|
2
2
|
module Adapters
|
3
3
|
# LRUHash backend
|
4
4
|
#
|
5
|
-
# Based on Hashery::LRUHash but simpler and measures memory usage
|
5
|
+
# Based on Hashery::LRUHash but simpler and measures both memory usage and hash size.
|
6
6
|
#
|
7
7
|
# @api public
|
8
8
|
class LRUHash
|
@@ -8,6 +8,8 @@ module Moneta
|
|
8
8
|
include Defaults
|
9
9
|
include ExpiresSupport
|
10
10
|
|
11
|
+
supports :create, :increment
|
12
|
+
|
11
13
|
# @param [Hash] options
|
12
14
|
# @option options [String] :server ('127.0.0.1:11211') Memcached server
|
13
15
|
# @option options [Integer] :expires Default expiration time
|
@@ -46,11 +48,7 @@ module Moneta
|
|
46
48
|
# FIXME: There is a Dalli bug, load(key) returns a wrong value after increment
|
47
49
|
# therefore we set default = nil and create the counter manually
|
48
50
|
# See https://github.com/mperham/dalli/issues/309
|
49
|
-
result =
|
50
|
-
@cache.incr(key, amount, expires_value(options) || nil, nil)
|
51
|
-
else
|
52
|
-
@cache.decr(key, -amount, expires_value(options) || nil, nil)
|
53
|
-
end
|
51
|
+
result = amount >= 0 ? @cache.incr(key, amount, nil, nil) : @cache.decr(key, -amount, nil, nil)
|
54
52
|
if result
|
55
53
|
result
|
56
54
|
elsif create(key, amount.to_s, options)
|