moneta 0.6.0 → 0.7.0
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/.gitignore +7 -0
- data/.travis.yml +39 -0
- data/Gemfile +61 -0
- data/LICENSE +2 -2
- data/README.md +450 -0
- data/Rakefile +29 -51
- data/SPEC.md +75 -0
- data/benchmarks/run.rb +195 -0
- data/lib/action_dispatch/middleware/session/moneta_store.rb +11 -0
- data/lib/active_support/cache/moneta_store.rb +55 -0
- data/lib/moneta.rb +121 -67
- data/lib/moneta/adapters/activerecord.rb +87 -0
- data/lib/moneta/adapters/cassandra.rb +91 -0
- data/lib/moneta/adapters/client.rb +69 -0
- data/lib/moneta/adapters/cookie.rb +35 -0
- data/lib/moneta/adapters/couch.rb +57 -0
- data/lib/moneta/adapters/datamapper.rb +75 -0
- data/lib/moneta/adapters/dbm.rb +25 -0
- data/lib/moneta/adapters/file.rb +79 -0
- data/lib/moneta/adapters/fog.rb +51 -0
- data/lib/moneta/adapters/gdbm.rb +25 -0
- data/lib/moneta/adapters/hbase.rb +101 -0
- data/lib/moneta/adapters/leveldb.rb +35 -0
- data/lib/moneta/adapters/localmemcache.rb +28 -0
- data/lib/moneta/adapters/lruhash.rb +85 -0
- data/lib/moneta/adapters/memcached.rb +11 -0
- data/lib/moneta/adapters/memcached_dalli.rb +69 -0
- data/lib/moneta/adapters/memcached_native.rb +70 -0
- data/lib/moneta/adapters/memory.rb +10 -0
- data/lib/moneta/adapters/mongo.rb +50 -0
- data/lib/moneta/adapters/null.rb +30 -0
- data/lib/moneta/adapters/pstore.rb +69 -0
- data/lib/moneta/adapters/redis.rb +68 -0
- data/lib/moneta/adapters/riak.rb +57 -0
- data/lib/moneta/adapters/sdbm.rb +35 -0
- data/lib/moneta/adapters/sequel.rb +79 -0
- data/lib/moneta/adapters/sqlite.rb +65 -0
- data/lib/moneta/adapters/tokyocabinet.rb +41 -0
- data/lib/moneta/adapters/yaml.rb +15 -0
- data/lib/moneta/base.rb +78 -0
- data/lib/moneta/builder.rb +39 -0
- data/lib/moneta/cache.rb +84 -0
- data/lib/moneta/expires.rb +71 -0
- data/lib/moneta/lock.rb +25 -0
- data/lib/moneta/logger.rb +61 -0
- data/lib/moneta/mixins.rb +65 -0
- data/lib/moneta/net.rb +18 -0
- data/lib/moneta/optionmerger.rb +39 -0
- data/lib/moneta/proxy.rb +86 -0
- data/lib/moneta/server.rb +81 -0
- data/lib/moneta/shared.rb +60 -0
- data/lib/moneta/stack.rb +78 -0
- data/lib/moneta/transformer.rb +159 -0
- data/lib/moneta/transformer/config.rb +42 -0
- data/lib/moneta/transformer/helper.rb +37 -0
- data/lib/moneta/version.rb +5 -0
- data/lib/moneta/wrapper.rb +33 -0
- data/lib/rack/cache/moneta.rb +93 -0
- data/lib/rack/moneta_cookies.rb +64 -0
- data/lib/rack/session/moneta.rb +63 -0
- data/moneta.gemspec +19 -0
- data/spec/action_dispatch/fixtures/session_autoload_test/foo.rb +10 -0
- data/spec/action_dispatch/session_moneta_store_spec.rb +196 -0
- data/spec/active_support/cache_moneta_store_spec.rb +197 -0
- data/spec/generate.rb +1489 -0
- data/spec/helper.rb +91 -0
- data/spec/moneta/adapter_activerecord_spec.rb +32 -0
- data/spec/moneta/adapter_cassandra_spec.rb +30 -0
- data/spec/moneta/adapter_client_spec.rb +19 -0
- data/spec/moneta/adapter_cookie_spec.rb +18 -0
- data/spec/moneta/adapter_couch_spec.rb +18 -0
- data/spec/moneta/adapter_datamapper_spec.rb +49 -0
- data/spec/moneta/adapter_dbm_spec.rb +18 -0
- data/spec/moneta/adapter_file_spec.rb +18 -0
- data/spec/moneta/adapter_fog_spec.rb +23 -0
- data/spec/moneta/adapter_gdbm_spec.rb +18 -0
- data/spec/moneta/adapter_hbase_spec.rb +18 -0
- data/spec/moneta/adapter_leveldb_spec.rb +18 -0
- data/spec/moneta/adapter_localmemcache_spec.rb +18 -0
- data/spec/moneta/adapter_lruhash_spec.rb +31 -0
- data/spec/moneta/adapter_memcached_dalli_spec.rb +30 -0
- data/spec/moneta/adapter_memcached_native_spec.rb +31 -0
- data/spec/moneta/adapter_memcached_spec.rb +30 -0
- data/spec/moneta/adapter_memory_spec.rb +39 -0
- data/spec/moneta/adapter_mongo_spec.rb +18 -0
- data/spec/moneta/adapter_pstore_spec.rb +21 -0
- data/spec/moneta/adapter_redis_spec.rb +30 -0
- data/spec/moneta/adapter_riak_spec.rb +22 -0
- data/spec/moneta/adapter_sdbm_spec.rb +18 -0
- data/spec/moneta/adapter_sequel_spec.rb +18 -0
- data/spec/moneta/adapter_sqlite_spec.rb +18 -0
- data/spec/moneta/adapter_tokyocabinet_bdb_spec.rb +18 -0
- data/spec/moneta/adapter_tokyocabinet_hdb_spec.rb +18 -0
- data/spec/moneta/adapter_yaml_spec.rb +21 -0
- data/spec/moneta/cache_file_memory_spec.rb +34 -0
- data/spec/moneta/cache_memory_null_spec.rb +23 -0
- data/spec/moneta/expires_file_spec.rb +76 -0
- data/spec/moneta/expires_memory_spec.rb +65 -0
- data/spec/moneta/lock_spec.rb +42 -0
- data/spec/moneta/null_adapter_spec.rb +26 -0
- data/spec/moneta/optionmerger_spec.rb +92 -0
- data/spec/moneta/proxy_expires_memory_spec.rb +55 -0
- data/spec/moneta/proxy_redis_spec.rb +23 -0
- data/spec/moneta/shared_spec.rb +30 -0
- data/spec/moneta/simple_activerecord_spec.rb +51 -0
- data/spec/moneta/simple_activerecord_with_expires_spec.rb +52 -0
- data/spec/moneta/simple_cassandra_spec.rb +52 -0
- data/spec/moneta/simple_client_tcp_spec.rb +67 -0
- data/spec/moneta/simple_client_unix_spec.rb +53 -0
- data/spec/moneta/simple_couch_spec.rb +51 -0
- data/spec/moneta/simple_couch_with_expires_spec.rb +52 -0
- data/spec/moneta/simple_datamapper_spec.rb +53 -0
- data/spec/moneta/simple_datamapper_with_expires_spec.rb +54 -0
- data/spec/moneta/simple_datamapper_with_repository_spec.rb +53 -0
- data/spec/moneta/simple_dbm_spec.rb +51 -0
- data/spec/moneta/simple_dbm_with_expires_spec.rb +52 -0
- data/spec/moneta/simple_file_spec.rb +51 -0
- data/spec/moneta/simple_file_with_expires_spec.rb +52 -0
- data/spec/moneta/simple_fog_spec.rb +56 -0
- data/spec/moneta/simple_fog_with_expires_spec.rb +58 -0
- data/spec/moneta/simple_gdbm_spec.rb +51 -0
- data/spec/moneta/simple_gdbm_with_expires_spec.rb +52 -0
- data/spec/moneta/simple_hashfile_spec.rb +51 -0
- data/spec/moneta/simple_hashfile_with_expires_spec.rb +52 -0
- data/spec/moneta/simple_hbase_spec.rb +51 -0
- data/spec/moneta/simple_hbase_with_expires_spec.rb +52 -0
- data/spec/moneta/simple_leveldb_spec.rb +51 -0
- data/spec/moneta/simple_leveldb_with_expires_spec.rb +52 -0
- data/spec/moneta/simple_localmemcache_spec.rb +51 -0
- data/spec/moneta/simple_localmemcache_with_expires_spec.rb +52 -0
- data/spec/moneta/simple_lruhash_spec.rb +51 -0
- data/spec/moneta/simple_lruhash_with_expires_spec.rb +52 -0
- data/spec/moneta/simple_memcached_dalli_spec.rb +52 -0
- data/spec/moneta/simple_memcached_native_spec.rb +52 -0
- data/spec/moneta/simple_memcached_spec.rb +52 -0
- data/spec/moneta/simple_memory_spec.rb +51 -0
- data/spec/moneta/simple_memory_with_compress_spec.rb +51 -0
- data/spec/moneta/simple_memory_with_expires_spec.rb +52 -0
- data/spec/moneta/simple_memory_with_json_key_serializer_spec.rb +37 -0
- data/spec/moneta/simple_memory_with_json_serializer_spec.rb +28 -0
- data/spec/moneta/simple_memory_with_json_value_serializer_spec.rb +35 -0
- data/spec/moneta/simple_memory_with_prefix_spec.rb +51 -0
- data/spec/moneta/simple_memory_with_snappy_compress_spec.rb +51 -0
- data/spec/moneta/simple_mongo_spec.rb +51 -0
- data/spec/moneta/simple_mongo_with_expires_spec.rb +52 -0
- data/spec/moneta/simple_null_spec.rb +36 -0
- data/spec/moneta/simple_pstore_spec.rb +51 -0
- data/spec/moneta/simple_pstore_with_expires_spec.rb +52 -0
- data/spec/moneta/simple_redis_spec.rb +52 -0
- data/spec/moneta/simple_riak_spec.rb +55 -0
- data/spec/moneta/simple_riak_with_expires_spec.rb +56 -0
- data/spec/moneta/simple_sdbm_spec.rb +51 -0
- data/spec/moneta/simple_sdbm_with_expires_spec.rb +52 -0
- data/spec/moneta/simple_sequel_spec.rb +51 -0
- data/spec/moneta/simple_sequel_with_expires_spec.rb +52 -0
- data/spec/moneta/simple_sqlite_spec.rb +51 -0
- data/spec/moneta/simple_sqlite_with_expires_spec.rb +52 -0
- data/spec/moneta/simple_tokyocabinet_spec.rb +51 -0
- data/spec/moneta/simple_tokyocabinet_with_expires_spec.rb +52 -0
- data/spec/moneta/simple_yaml_spec.rb +50 -0
- data/spec/moneta/simple_yaml_with_expires_spec.rb +51 -0
- data/spec/moneta/stack_file_memory_spec.rb +25 -0
- data/spec/moneta/stack_memory_file_spec.rb +24 -0
- data/spec/moneta/transformer_bencode_spec.rb +30 -0
- data/spec/moneta/transformer_bert_spec.rb +30 -0
- data/spec/moneta/transformer_bson_spec.rb +30 -0
- data/spec/moneta/transformer_bzip2_spec.rb +27 -0
- data/spec/moneta/transformer_json_spec.rb +30 -0
- data/spec/moneta/transformer_lzma_spec.rb +27 -0
- data/spec/moneta/transformer_lzo_spec.rb +27 -0
- data/spec/moneta/transformer_marshal_base64_spec.rb +54 -0
- data/spec/moneta/transformer_marshal_escape_spec.rb +54 -0
- data/spec/moneta/transformer_marshal_hmac_spec.rb +54 -0
- data/spec/moneta/transformer_marshal_md5_spec.rb +54 -0
- data/spec/moneta/transformer_marshal_md5_spread_spec.rb +54 -0
- data/spec/moneta/transformer_marshal_prefix_spec.rb +54 -0
- data/spec/moneta/transformer_marshal_rmd160_spec.rb +54 -0
- data/spec/moneta/transformer_marshal_sha1_spec.rb +54 -0
- data/spec/moneta/transformer_marshal_sha256_spec.rb +54 -0
- data/spec/moneta/transformer_marshal_sha384_spec.rb +54 -0
- data/spec/moneta/transformer_marshal_sha512_spec.rb +54 -0
- data/spec/moneta/transformer_marshal_truncate_spec.rb +54 -0
- data/spec/moneta/transformer_marshal_uuencode_spec.rb +54 -0
- data/spec/moneta/transformer_msgpack_spec.rb +30 -0
- data/spec/moneta/transformer_ox_spec.rb +51 -0
- data/spec/moneta/transformer_quicklz_spec.rb +27 -0
- data/spec/moneta/transformer_snappy_spec.rb +27 -0
- data/spec/moneta/transformer_tnet_spec.rb +30 -0
- data/spec/moneta/transformer_yaml_spec.rb +51 -0
- data/spec/moneta/transformer_zlib_spec.rb +27 -0
- data/spec/monetaspecs.rb +2663 -0
- data/spec/rack/cache_moneta_spec.rb +355 -0
- data/spec/rack/moneta_cookies_spec.rb +81 -0
- data/spec/rack/session_moneta_spec.rb +305 -0
- metadata +359 -56
- data/README +0 -51
- data/TODO +0 -4
- data/lib/moneta/basic_file.rb +0 -111
- data/lib/moneta/berkeley.rb +0 -53
- data/lib/moneta/couch.rb +0 -63
- data/lib/moneta/datamapper.rb +0 -117
- data/lib/moneta/file.rb +0 -91
- data/lib/moneta/lmc.rb +0 -52
- data/lib/moneta/memcache.rb +0 -52
- data/lib/moneta/memory.rb +0 -11
- data/lib/moneta/mongodb.rb +0 -58
- data/lib/moneta/redis.rb +0 -49
- data/lib/moneta/rufus.rb +0 -41
- data/lib/moneta/s3.rb +0 -162
- data/lib/moneta/sdbm.rb +0 -33
- data/lib/moneta/tyrant.rb +0 -58
- data/lib/moneta/xattr.rb +0 -58
data/.gitignore
ADDED
data/.travis.yml
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
rvm:
|
|
2
|
+
- 1.8.7
|
|
3
|
+
- 1.9.3
|
|
4
|
+
# - ruby-head
|
|
5
|
+
- jruby
|
|
6
|
+
- rbx-18mode
|
|
7
|
+
- rbx-19mode
|
|
8
|
+
services:
|
|
9
|
+
- riak
|
|
10
|
+
- couchdb
|
|
11
|
+
- redis-server
|
|
12
|
+
- cassandra
|
|
13
|
+
- memcached
|
|
14
|
+
- mongodb
|
|
15
|
+
before_install:
|
|
16
|
+
- sudo apt-get install -qq libtokyocabinet8 libtokyocabinet-dev liblzo2-dev
|
|
17
|
+
env:
|
|
18
|
+
- "TASK=test:parallel"
|
|
19
|
+
- "TASK=test:non_parallel"
|
|
20
|
+
- "TASK=benchmarks"
|
|
21
|
+
matrix:
|
|
22
|
+
allow_failures:
|
|
23
|
+
# - rvm: ruby-head
|
|
24
|
+
- rvm: jruby
|
|
25
|
+
- rvm: rbx-18mode
|
|
26
|
+
- rvm: rbx-19mode
|
|
27
|
+
# Parallel tests do not work on jruby
|
|
28
|
+
exclude:
|
|
29
|
+
- rvm: jruby
|
|
30
|
+
env: "TASK=test:parallel"
|
|
31
|
+
- rvm: 1.8.7
|
|
32
|
+
env: "TASK=benchmarks"
|
|
33
|
+
- rvm: jruby
|
|
34
|
+
env: "TASK=benchmarks"
|
|
35
|
+
- rvm: rbx-18mode
|
|
36
|
+
env: "TASK=benchmarks"
|
|
37
|
+
- rvm: rbx-19mode
|
|
38
|
+
env: "TASK=benchmarks"
|
|
39
|
+
script: "bundle exec rake $TASK"
|
data/Gemfile
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
source :rubygems
|
|
2
|
+
gemspec
|
|
3
|
+
|
|
4
|
+
def alternatives(gems)
|
|
5
|
+
if defined?(JRUBY_VERSION)
|
|
6
|
+
[gems[:jruby]].flatten.compact.each {|g| gem g }
|
|
7
|
+
else
|
|
8
|
+
[gems[:mri]].flatten.compact.each {|g| gem g }
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Testing
|
|
13
|
+
gem 'rake'
|
|
14
|
+
gem 'rspec'
|
|
15
|
+
gem 'parallel_tests'
|
|
16
|
+
|
|
17
|
+
# Serializer used by Transformer
|
|
18
|
+
gem 'tnetstring'
|
|
19
|
+
gem 'bencode'
|
|
20
|
+
gem 'multi_json'
|
|
21
|
+
alternatives :mri => 'bson_ext', :jruby => 'bson'
|
|
22
|
+
alternatives :mri => 'ox'
|
|
23
|
+
alternatives :mri => 'msgpack', :jruby => 'msgpack-jruby'
|
|
24
|
+
alternatives :mri => 'bert'
|
|
25
|
+
|
|
26
|
+
# Compressors used by Transformer
|
|
27
|
+
alternatives :mri => 'bzip2-ruby'
|
|
28
|
+
alternatives :mri => 'ruby-lzma'
|
|
29
|
+
alternatives :mri => 'lzoruby'
|
|
30
|
+
alternatives :mri => 'snappy'
|
|
31
|
+
# QuickLZ segfaults because of an assertion, fix this before activating it again
|
|
32
|
+
# alternatives :mri => 'qlzruby'
|
|
33
|
+
|
|
34
|
+
# Backends
|
|
35
|
+
gem 'dm-core'
|
|
36
|
+
gem 'dm-migrations'
|
|
37
|
+
gem 'dm-sqlite-adapter'
|
|
38
|
+
gem 'fog'
|
|
39
|
+
gem 'activerecord', '>= 3.2.9'
|
|
40
|
+
gem 'redis'
|
|
41
|
+
gem 'mongo'
|
|
42
|
+
gem 'couchrest'
|
|
43
|
+
gem 'sequel'
|
|
44
|
+
gem 'dalli'
|
|
45
|
+
gem 'riak-client'
|
|
46
|
+
gem 'cassandra'
|
|
47
|
+
#gem 'hbaserb'
|
|
48
|
+
#gem 'localmemcache'
|
|
49
|
+
alternatives :mri => 'leveldb-ruby'
|
|
50
|
+
alternatives :mri => 'tokyocabinet'
|
|
51
|
+
alternatives :mri => 'memcached', :jruby => 'jruby-memcached'
|
|
52
|
+
alternatives :mri => 'sqlite3', :jruby => %w(jdbc-sqlite3 activerecord-jdbc-adapter activerecord-jdbcsqlite3-adapter)
|
|
53
|
+
alternatives :jruby => %w(ffi gdbm) # gdbm for jruby needs ffi
|
|
54
|
+
|
|
55
|
+
# Rack integration testing
|
|
56
|
+
gem 'rack'
|
|
57
|
+
gem 'rack-cache'
|
|
58
|
+
|
|
59
|
+
# Rails integration testing
|
|
60
|
+
gem 'actionpack'
|
|
61
|
+
gem 'minitest'
|
data/LICENSE
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Copyright (c) 2009 Yehuda Katz
|
|
1
|
+
Copyright (c) 2009 Yehuda Katz, 2012 Daniel Mendler
|
|
2
2
|
|
|
3
3
|
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
4
|
a copy of this software and associated documentation files (the
|
|
@@ -17,4 +17,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
|
17
17
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
18
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
19
19
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
20
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,450 @@
|
|
|
1
|
+
# Moneta: A unified interface for key/value stores
|
|
2
|
+
|
|
3
|
+
[](http://travis-ci.org/minad/moneta) [](https://gemnasium.com/minad/moneta) [](https://codeclimate.com/github/minad/moneta)
|
|
4
|
+
|
|
5
|
+
Moneta provides a standard interface for interacting with various kinds of key/value stores. Moneta is very feature rich:
|
|
6
|
+
|
|
7
|
+
* Supports a lot of backends (See below)
|
|
8
|
+
* Supports proxies (Similar to [Rack middlewares](http://rack.github.com/))
|
|
9
|
+
* Custom serialization via `Moneta::Transformer` proxy (Marshal/JSON/YAML and many more)
|
|
10
|
+
* Custom key transformation via `Moneta::Transformer` proxy
|
|
11
|
+
* Value compression via `Moneta::Transformer` proxy (Zlib, Snappy, LZMA, ...)
|
|
12
|
+
* Expiration for all stores (Added via proxy `Moneta::Expires` if not supported natively)
|
|
13
|
+
* Atomic incrementation and decrementation for most stores (Method `#increment`)
|
|
14
|
+
* Includes a very simple key/value server (`Moneta::Server`) and client (`Moneta::Adapters::Client`)
|
|
15
|
+
* Integration with [Rails](http://rubyonrails.org/), [Rack](http://rack.github.com/) as cookie and session store and [Rack-Cache](https://github.com/rtomayko/rack-cache)
|
|
16
|
+
|
|
17
|
+
Moneta is tested thoroughly using [Travis-CI](http://travis-ci.org/minad/moneta).
|
|
18
|
+
|
|
19
|
+
## Links
|
|
20
|
+
|
|
21
|
+
* Source: <http://github.com/minad/moneta>
|
|
22
|
+
* Bugs: <http://github.com/minad/moneta/issues>
|
|
23
|
+
* API documentation:
|
|
24
|
+
* Latest Gem: <http://rubydoc.info/gems/moneta/frames>
|
|
25
|
+
* GitHub master: <http://rubydoc.info/github/minad/moneta/master/frames>
|
|
26
|
+
|
|
27
|
+
## Supported backends
|
|
28
|
+
|
|
29
|
+
Out of the box, it supports the following backends:
|
|
30
|
+
|
|
31
|
+
* Memory:
|
|
32
|
+
* In-memory store (`:Memory`)
|
|
33
|
+
* LRU hash - prefer this over :Memory! (`:LRUHash`)
|
|
34
|
+
* LocalMemCache (`:LocalMemCache`)
|
|
35
|
+
* Memcached store (`:Memcached`, `:MemcachedNative` and `:MemcachedDalli`)
|
|
36
|
+
* Relational Databases:
|
|
37
|
+
* DataMapper (`:DataMapper`)
|
|
38
|
+
* ActiveRecord (`:ActiveRecord`)
|
|
39
|
+
* Sequel (`:Sequel`)
|
|
40
|
+
* Sqlite3 (`:Sqlite`)
|
|
41
|
+
* Filesystem:
|
|
42
|
+
* PStore (`:PStore`)
|
|
43
|
+
* YAML store (`:YAML`)
|
|
44
|
+
* Filesystem directory store (`:File`)
|
|
45
|
+
* Filesystem directory store which spreads files in subdirectories using md5 hash (`:HashFile`)
|
|
46
|
+
* Key/value databases:
|
|
47
|
+
* Berkeley DB (`:DBM`)
|
|
48
|
+
* Cassandra (`:Cassandra`)
|
|
49
|
+
* GDBM (`:GDBM`)
|
|
50
|
+
* HBase (`:HBase`)
|
|
51
|
+
* LevelDB (`:LevelDB`)
|
|
52
|
+
* Redis (`:Redis`)
|
|
53
|
+
* Riak (`:Riak`)
|
|
54
|
+
* SDBM (`:SDBM`)
|
|
55
|
+
* TokyoCabinet (`:TokyoCabinet`)
|
|
56
|
+
* Document databases:
|
|
57
|
+
* CouchDB (`:Couch`)
|
|
58
|
+
* MongoDB (`:Mongo`)
|
|
59
|
+
* Other
|
|
60
|
+
* Moneta key/value server client (`:Client` works with `Moneta::Server`)
|
|
61
|
+
* Fog cloud storage which supports Amazon S3, Rackspace, etc. (`:Fog`)
|
|
62
|
+
* Storage which doesn't store anything (`:Null`)
|
|
63
|
+
|
|
64
|
+
Some of the backends are not exactly based on key/value stores, e.g. the relational ones. These
|
|
65
|
+
are useful if you already use the corresponding backend in your application. You get a key/value
|
|
66
|
+
store for free then without installing any additional services and you still have the possibility
|
|
67
|
+
to upgrade to a real key/value store.
|
|
68
|
+
|
|
69
|
+
## Proxies
|
|
70
|
+
|
|
71
|
+
In addition it supports proxies (Similar to [Rack middlewares](http://rack.github.com/)) which
|
|
72
|
+
add additional features to storage backends:
|
|
73
|
+
|
|
74
|
+
* `Moneta::Proxy` and `Moneta::Wrapper` proxy base classes
|
|
75
|
+
* `Moneta::Expires` to add expiration support to stores which don't support it natively. Add it in the builder using `use :Expires`.
|
|
76
|
+
* `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`.
|
|
77
|
+
* `Moneta::Transformer` transforms keys and values (Marshal, YAML, JSON, Base64, MD5, ...). Add it in the builder using `use :Transformer`.
|
|
78
|
+
* `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`.
|
|
79
|
+
* `Moneta::Lock` to make store thread safe. Add it in the builder using `use :Lock`.
|
|
80
|
+
* `Moneta::Logger` to log database accesses. Add it in the builder using `use :Logger`.
|
|
81
|
+
* `Moneta::Shared` to share a store between multiple processes. Add it in the builder using `use :Shared`.
|
|
82
|
+
|
|
83
|
+
## Supported serializers and compressors (`Moneta::Transformer`)
|
|
84
|
+
|
|
85
|
+
Supported serializers:
|
|
86
|
+
|
|
87
|
+
* BEncode (`:bencode`)
|
|
88
|
+
* BERT (`:bert`)
|
|
89
|
+
* BSON (`:bson`)
|
|
90
|
+
* JSON (`:json`)
|
|
91
|
+
* Marshal (`:marshal`)
|
|
92
|
+
* MessagePack (`:msgpack`)
|
|
93
|
+
* Ox (`:ox`)
|
|
94
|
+
* TNetStrings (`:tnet`)
|
|
95
|
+
* YAML (`:yaml`)
|
|
96
|
+
|
|
97
|
+
Supported value compressors:
|
|
98
|
+
|
|
99
|
+
* LZMA (`:lzma`)
|
|
100
|
+
* LZO (`:lzo`)
|
|
101
|
+
* Snappy (`:snappy`)
|
|
102
|
+
* QuickLZ (`:quicklz`)
|
|
103
|
+
* Zlib (`:zlib`)
|
|
104
|
+
|
|
105
|
+
Special transformers:
|
|
106
|
+
|
|
107
|
+
* Digests (MD5, Shas, ...)
|
|
108
|
+
* Add prefix to keys (`:prefix`)
|
|
109
|
+
* HMAC to verify values (`:hmac`, useful for `Rack::MonetaCookies`)
|
|
110
|
+
|
|
111
|
+
## Moneta API
|
|
112
|
+
|
|
113
|
+
~~~
|
|
114
|
+
#initialize(options) options differs per-store, and is used to set up the store.
|
|
115
|
+
|
|
116
|
+
#[](key) retrieve a key. If the key is not available, return nil.
|
|
117
|
+
|
|
118
|
+
#load(key, options = {}) retrieve a key. If the key is not available, return nil.
|
|
119
|
+
|
|
120
|
+
#fetch(key, options = {}, &block) retrieve a key. If the key is not available, execute the
|
|
121
|
+
block and return its return value.
|
|
122
|
+
|
|
123
|
+
#fetch(key, value, options = {}) retrieve a key. If the key is not available, return the value,
|
|
124
|
+
|
|
125
|
+
#[]=(key, value) set a value for a key. If the key is already used, clobber it.
|
|
126
|
+
keys set using []= will never expire.
|
|
127
|
+
|
|
128
|
+
#store(key, value, options = {}) same as []=, but you can supply options.
|
|
129
|
+
|
|
130
|
+
#delete(key, options = {}) delete the key from the store and return the current value.
|
|
131
|
+
|
|
132
|
+
#key?(key, options = {}) true if the key exists, false if it does not.
|
|
133
|
+
|
|
134
|
+
#increment(key, amount = 1, options = {}) increment numeric value. This is a atomic operation
|
|
135
|
+
which is not supported by all stores. Returns current value.
|
|
136
|
+
|
|
137
|
+
#clear(options = {}) clear all keys in this store.
|
|
138
|
+
|
|
139
|
+
#close close database connection.
|
|
140
|
+
~~~
|
|
141
|
+
|
|
142
|
+
The Moneta API is purposely extremely similar to the Hash API. In order so support an
|
|
143
|
+
identical API across stores, it does not support iteration or partial matches.
|
|
144
|
+
|
|
145
|
+
### Creating a Store
|
|
146
|
+
|
|
147
|
+
There is a simple interface to create a store using `Moneta.new`:
|
|
148
|
+
|
|
149
|
+
~~~ ruby
|
|
150
|
+
store = Moneta.new(:Memcached, :server => 'localhost:11211')
|
|
151
|
+
~~~
|
|
152
|
+
|
|
153
|
+
If you want to have control over the proxies, you have to use `Moneta.build`:
|
|
154
|
+
|
|
155
|
+
~~~ ruby
|
|
156
|
+
store = Moneta.build do
|
|
157
|
+
# Adds expires proxy
|
|
158
|
+
use :Expires
|
|
159
|
+
# Transform key using Marshal and Base64 and value using Marshal
|
|
160
|
+
use :Transformer, :key => [:marshal, :base64], :value => :marshal
|
|
161
|
+
# Memory backend
|
|
162
|
+
adapter :Memory
|
|
163
|
+
end
|
|
164
|
+
~~~
|
|
165
|
+
|
|
166
|
+
### Expiration
|
|
167
|
+
|
|
168
|
+
The Cassandra, Memcached and Redis backends supports expires values directly:
|
|
169
|
+
|
|
170
|
+
~~~ ruby
|
|
171
|
+
cache = Moneta::Adapters::Memcached.new
|
|
172
|
+
|
|
173
|
+
# Or using the builder...
|
|
174
|
+
cache = Moneta.build do
|
|
175
|
+
adapter :Memcached
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
# Expires in 60 seconds
|
|
179
|
+
cache.store(key, value, :expires => 60)
|
|
180
|
+
|
|
181
|
+
# Update expires time if value is found
|
|
182
|
+
cache.load(key, :expires => 30)
|
|
183
|
+
cache.key?(key, :expires => 30)
|
|
184
|
+
~~~
|
|
185
|
+
|
|
186
|
+
You can add the expires feature to other backends using the Expires proxy:
|
|
187
|
+
|
|
188
|
+
~~~ ruby
|
|
189
|
+
# Using the :expires option
|
|
190
|
+
cache = Moneta.new(:File, :dir => '...', :expires => true)
|
|
191
|
+
|
|
192
|
+
# or manually by using the proxy...
|
|
193
|
+
cache = Moneta::Expires.new(Moneta::Adapters::File.new(:dir => '...'))
|
|
194
|
+
|
|
195
|
+
# or using the builder...
|
|
196
|
+
cache = Moneta.build do
|
|
197
|
+
use :Expires
|
|
198
|
+
adapter :File, :dir => '...'
|
|
199
|
+
end
|
|
200
|
+
~~~
|
|
201
|
+
|
|
202
|
+
### Incrementation and raw access
|
|
203
|
+
|
|
204
|
+
The stores support the `#increment` which allows atomic increments of unsigned integer values. If you increment
|
|
205
|
+
a non existing value, it will be created. If you increment a non integer value an exception will be raised.
|
|
206
|
+
|
|
207
|
+
~~~ ruby
|
|
208
|
+
store.increment('counter') => 1 # counter created
|
|
209
|
+
store.increment('counter') => 2
|
|
210
|
+
store.increment('counter', -1) => 1
|
|
211
|
+
store.increment('counter', 13) => 14
|
|
212
|
+
store.increment('counter', 0) => 14
|
|
213
|
+
store['name'] = 'Moneta'
|
|
214
|
+
store.increment('name') => Exception
|
|
215
|
+
~~~
|
|
216
|
+
|
|
217
|
+
If you want to access the counter value you have to use raw access to the datastore. This is only important
|
|
218
|
+
if you have a `Moneta::Transformer` somewhere in your proxy chain which transforms the values e.g. with `Marshal`.
|
|
219
|
+
|
|
220
|
+
~~~ ruby
|
|
221
|
+
store.increment('counter') => 1 # counter created
|
|
222
|
+
store.load('counter', :raw => true) => '1'
|
|
223
|
+
|
|
224
|
+
store.store('counter', '10', :raw => true)
|
|
225
|
+
store.increment('counter') => 11
|
|
226
|
+
~~~
|
|
227
|
+
|
|
228
|
+
Fortunately there is a nicer way to do this using some syntactic sugar!
|
|
229
|
+
|
|
230
|
+
~~~ ruby
|
|
231
|
+
store.increment('counter') => 1 # counter created
|
|
232
|
+
store.raw['counter'] => '1'
|
|
233
|
+
store.raw.load('counter') => '1'
|
|
234
|
+
|
|
235
|
+
store.raw['counter'] = '10'
|
|
236
|
+
store.increment('counter') => 11
|
|
237
|
+
~~~
|
|
238
|
+
|
|
239
|
+
You can also keep the `raw` store in a variable and use it like this:
|
|
240
|
+
|
|
241
|
+
~~~ ruby
|
|
242
|
+
counters = store.raw
|
|
243
|
+
|
|
244
|
+
counters.increment('counter') => 1 # counter created
|
|
245
|
+
counters['counter'] => '1'
|
|
246
|
+
counters.load('counter') => '1'
|
|
247
|
+
|
|
248
|
+
counters['counter'] = '10'
|
|
249
|
+
counters.increment('counter') => 11
|
|
250
|
+
~~~
|
|
251
|
+
|
|
252
|
+
Stores which support incrementation (you have to use `Moneta::Lock` if you want to use the store in a multithreading environment.)
|
|
253
|
+
|
|
254
|
+
* ActiveRecord
|
|
255
|
+
* File
|
|
256
|
+
* HBase
|
|
257
|
+
* LRUHash
|
|
258
|
+
* LevelDB
|
|
259
|
+
* Memcached
|
|
260
|
+
* Memory
|
|
261
|
+
* Redis
|
|
262
|
+
* SDBM/DBM/GDBM
|
|
263
|
+
* Sequel
|
|
264
|
+
* Sqlite
|
|
265
|
+
* TokyoCabinet
|
|
266
|
+
* YAML/PStore
|
|
267
|
+
|
|
268
|
+
Stores which don't support incrementation:
|
|
269
|
+
|
|
270
|
+
* Cassandra
|
|
271
|
+
* Couch
|
|
272
|
+
* DataMapper
|
|
273
|
+
* Fog
|
|
274
|
+
* LocalMemCache
|
|
275
|
+
* Mongo
|
|
276
|
+
* Riak
|
|
277
|
+
|
|
278
|
+
### Syntactic sugar and option merger
|
|
279
|
+
|
|
280
|
+
For raw data access as described before the class `Moneta::OptionMerger` is used. It works like this:
|
|
281
|
+
|
|
282
|
+
~~~ ruby
|
|
283
|
+
# All methods after `with` get the options passed
|
|
284
|
+
store.with(:raw => true).load('key')
|
|
285
|
+
|
|
286
|
+
# You can also specify the methods
|
|
287
|
+
store.with(:raw => true, :only => :load).load('key')
|
|
288
|
+
store.with(:raw => true, :except => [:key?, :increment]).load('key')
|
|
289
|
+
|
|
290
|
+
# Syntactic sugar for raw access
|
|
291
|
+
store.raw.load('key')
|
|
292
|
+
|
|
293
|
+
# Access substore where all keys get a prefix
|
|
294
|
+
substore = store.prefix('sub')
|
|
295
|
+
substore['key'] = 'value'
|
|
296
|
+
store['key'] => nil
|
|
297
|
+
store['subkey'] => 'value'
|
|
298
|
+
|
|
299
|
+
# Set expiration time for all keys
|
|
300
|
+
short_lived_store = long_lived_store.expires(60)
|
|
301
|
+
short_lived_store['key'] = 'value'
|
|
302
|
+
~~~
|
|
303
|
+
|
|
304
|
+
## Framework Integration
|
|
305
|
+
|
|
306
|
+
Inspired by [redis-store](https://github.com/jodosha/redis-store) there exist integration classes for [Rails](http://rubyonrails.org/), [Rack](http://rack.github.com/) and [Rack-Cache](https://github.com/rtomayko/rack-cache).
|
|
307
|
+
|
|
308
|
+
### Rack session store
|
|
309
|
+
|
|
310
|
+
Use Moneta as a [Rack](http://rack.github.com/) session store:
|
|
311
|
+
|
|
312
|
+
~~~ ruby
|
|
313
|
+
require 'rack/session/moneta'
|
|
314
|
+
|
|
315
|
+
# Use only the adapter name
|
|
316
|
+
use Rack::Session::Moneta, :store => :Redis
|
|
317
|
+
|
|
318
|
+
# Use Moneta.new
|
|
319
|
+
use Rack::Session::Moneta, :store => Moneta.new(:Memory, :expires => true)
|
|
320
|
+
|
|
321
|
+
# Use the Moneta builder
|
|
322
|
+
use Rack::Session::Moneta do
|
|
323
|
+
use :Expires
|
|
324
|
+
adapter :Memory
|
|
325
|
+
end
|
|
326
|
+
~~~
|
|
327
|
+
|
|
328
|
+
### Rack cache
|
|
329
|
+
|
|
330
|
+
Use Moneta as a [Rack-Cache](https://github.com/rtomayko/rack-cache) store:
|
|
331
|
+
|
|
332
|
+
~~~ ruby
|
|
333
|
+
require 'rack/cache/moneta'
|
|
334
|
+
|
|
335
|
+
use Rack::Cache,
|
|
336
|
+
:metastore => 'moneta://Memory?expires=true',
|
|
337
|
+
:entitystore => 'moneta://Memory?expires=true'
|
|
338
|
+
|
|
339
|
+
# Or used named Moneta stores
|
|
340
|
+
Rack::Cache::Moneta['named_metastore'] = Moneta.build do
|
|
341
|
+
use :Expires
|
|
342
|
+
adapter :Memory
|
|
343
|
+
end
|
|
344
|
+
use Rack::Cache,
|
|
345
|
+
:metastore => 'moneta://named_metastore',
|
|
346
|
+
:entity_store => 'moneta://named_entitystore'
|
|
347
|
+
~~~
|
|
348
|
+
|
|
349
|
+
### Rack cookies
|
|
350
|
+
|
|
351
|
+
Use Moneta to store cookies in [Rack](http://rack.github.com/). It uses the `Moneta::Adapters::Cookie`. You might
|
|
352
|
+
wonder what the purpose of this store or Rack middleware is: It makes it possible
|
|
353
|
+
to use all the transformers on the cookies (e.g. `:prefix`, `:marshal` and `:hmac` for value verification).
|
|
354
|
+
|
|
355
|
+
~~~ ruby
|
|
356
|
+
require 'rack/moneta_cookies'
|
|
357
|
+
|
|
358
|
+
use Rack::MonetaCookies, :domain => 'example.com', :path => '/path'
|
|
359
|
+
run lambda do |env|
|
|
360
|
+
req = Rack::Request.new(env)
|
|
361
|
+
req.cookies #=> is now a Moneta store!
|
|
362
|
+
env['rack.request.cookie_hash'] #=> is now a Moneta store!
|
|
363
|
+
req.cookies['key'] #=> retrieves 'key'
|
|
364
|
+
req.cookies['key'] = 'value' #=> sets 'key'
|
|
365
|
+
req.cookies.delete('key') #=> removes 'key'
|
|
366
|
+
[200, {}, []]
|
|
367
|
+
end
|
|
368
|
+
~~~
|
|
369
|
+
|
|
370
|
+
### Rails session store
|
|
371
|
+
|
|
372
|
+
Add the session store in your application configuration `config/environments/*.rb`.
|
|
373
|
+
|
|
374
|
+
~~~ ruby
|
|
375
|
+
require 'moneta'
|
|
376
|
+
|
|
377
|
+
# Only by adapter name
|
|
378
|
+
config.cache_store :moneta_store, :store => :Memory
|
|
379
|
+
|
|
380
|
+
# Use Moneta.new
|
|
381
|
+
config.cache_store :moneta_store, :store => Moneta.new(:Memory)
|
|
382
|
+
|
|
383
|
+
# Use the Moneta builder
|
|
384
|
+
config.cache_store :moneta_store, :store => Moneta.build do
|
|
385
|
+
use :Expires
|
|
386
|
+
adapter :Memory
|
|
387
|
+
end
|
|
388
|
+
~~~
|
|
389
|
+
|
|
390
|
+
### Rails cache store
|
|
391
|
+
|
|
392
|
+
Add the cache store in your application configuration `config/environments/*.rb`. Unfortunately the
|
|
393
|
+
Moneta cache store doesn't support matchers. If you need these features use a different server-specific implementation.
|
|
394
|
+
|
|
395
|
+
~~~ ruby
|
|
396
|
+
require 'moneta'
|
|
397
|
+
|
|
398
|
+
# Only by adapter name
|
|
399
|
+
config.cache_store :moneta_store, :store => :Memory
|
|
400
|
+
|
|
401
|
+
# Use Moneta.new
|
|
402
|
+
config.cache_store :moneta_store, :store => Moneta.new(:Memory)
|
|
403
|
+
|
|
404
|
+
# Use the Moneta builder
|
|
405
|
+
config.cache_store :moneta_store, :store => Moneta.build do
|
|
406
|
+
use :Expires
|
|
407
|
+
adapter :Memory
|
|
408
|
+
end
|
|
409
|
+
~~~
|
|
410
|
+
|
|
411
|
+
## Advanced - Build your own key value server
|
|
412
|
+
|
|
413
|
+
You can use Moneta to build your own key/value server which is shared between
|
|
414
|
+
multiple processes. If you run the following code in two different processes,
|
|
415
|
+
they will share the same data which will also be persistet in the database `shared.db`.
|
|
416
|
+
|
|
417
|
+
~~~ ruby
|
|
418
|
+
require 'moneta'
|
|
419
|
+
|
|
420
|
+
store = Moneta.build do
|
|
421
|
+
use :Transformer, :key => :marshal, :value => :marshal
|
|
422
|
+
use :Shared do
|
|
423
|
+
use :Cache do
|
|
424
|
+
cache do
|
|
425
|
+
adapter :LRUHash
|
|
426
|
+
end
|
|
427
|
+
backend do
|
|
428
|
+
adapter :GDBM, :file => 'shared.db'
|
|
429
|
+
end
|
|
430
|
+
end
|
|
431
|
+
end
|
|
432
|
+
end
|
|
433
|
+
~~~
|
|
434
|
+
|
|
435
|
+
## More information
|
|
436
|
+
|
|
437
|
+
* http://yehudakatz.com/2009/02/12/whats-the-point/
|
|
438
|
+
* http://yehudakatz.com/2009/02/12/initial-release-of-moneta-unified-keyvalue-store-api/
|
|
439
|
+
|
|
440
|
+
## Alternatives
|
|
441
|
+
|
|
442
|
+
* [Horcrux](https://github.com/technoweenie/horcrux): Used at github, supports batch operations but only Memcached backend
|
|
443
|
+
* [ToyStore](https://github.com/jnunemaker/toystore): ORM mapper for key/value stores
|
|
444
|
+
* [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
|
|
445
|
+
|
|
446
|
+
## Authors
|
|
447
|
+
|
|
448
|
+
* Daniel Mendler
|
|
449
|
+
* Hannes Georg
|
|
450
|
+
* Originally by Yehuda Katz and contributors
|