juno 0.2.8 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +1 -1
- data/Gemfile +2 -1
- data/README.md +79 -49
- data/SPEC.md +0 -13
- data/lib/juno.rb +2 -1
- data/lib/juno/adapters/cassandra.rb +38 -14
- data/lib/juno/adapters/couch.rb +4 -4
- data/lib/juno/adapters/datamapper.rb +1 -1
- data/lib/juno/adapters/dbm.rb +1 -1
- data/lib/juno/adapters/file.rb +2 -2
- data/lib/juno/adapters/fog.rb +1 -1
- data/lib/juno/adapters/gdbm.rb +1 -1
- data/lib/juno/adapters/leveldb.rb +35 -0
- data/lib/juno/adapters/localmemcache.rb +1 -1
- data/lib/juno/adapters/mongo.rb +2 -2
- data/lib/juno/adapters/pstore.rb +1 -1
- data/lib/juno/adapters/riak.rb +3 -1
- data/lib/juno/adapters/sdbm.rb +1 -1
- data/lib/juno/adapters/sequel.rb +1 -1
- data/lib/juno/adapters/sqlite.rb +1 -1
- data/lib/juno/adapters/tokyocabinet.rb +1 -1
- data/lib/juno/base.rb +16 -4
- data/lib/juno/builder.rb +2 -2
- data/lib/juno/cache.rb +2 -2
- data/lib/juno/stack.rb +1 -1
- data/lib/juno/transformer.rb +39 -13
- data/lib/juno/version.rb +1 -1
- data/lib/rack/juno_cookies.rb +10 -8
- data/lib/rack/session/juno.rb +2 -2
- data/spec/generate.rb +36 -14
- data/spec/juno/adapter_cassandra_spec.rb +1 -1
- data/spec/juno/adapter_leveldb_spec.rb +13 -0
- data/spec/juno/simple_cassandra_spec.rb +1 -1
- data/spec/juno/simple_leveldb_spec.rb +38 -0
- data/spec/juno/simple_leveldb_with_expires_spec.rb +39 -0
- data/spec/juno/transformer_marshal_hmac_spec.rb +41 -0
- data/spec/junospecs.rb +18 -9
- metadata +11 -2
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
@@ -42,8 +42,9 @@ gem 'sequel'
|
|
42
42
|
gem 'dalli'
|
43
43
|
gem 'riak-client'
|
44
44
|
gem 'hashery'
|
45
|
-
|
45
|
+
gem 'cassandra'
|
46
46
|
#gem 'localmemcache'
|
47
|
+
alternatives :mri => 'leveldb-ruby'
|
47
48
|
alternatives :mri => 'tokyocabinet'
|
48
49
|
alternatives :mri => 'memcached', :jruby => 'jruby-memcached'
|
49
50
|
alternatives :mri => 'sqlite3', :jruby => %w(jdbc-sqlite3 activerecord-jdbc-adapter activerecord-jdbcsqlite3-adapter)
|
data/README.md
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
Juno: A unified interface for key/value stores
|
2
|
-
|
2
|
+
==============================================
|
3
3
|
|
4
4
|
[![Build Status](https://secure.travis-ci.org/minad/juno.png?branch=master)](http://travis-ci.org/minad/juno) [![Dependency Status](https://gemnasium.com/minad/juno.png?travis)](https://gemnasium.com/minad/juno) [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/minad/juno)
|
5
5
|
|
@@ -14,8 +14,10 @@ Juno is very feature rich:
|
|
14
14
|
* Custom serialization via `Juno::Transformer` proxy (Marshal/JSON/YAML and many more)
|
15
15
|
* Custom key transformation via `Juno::Transformer` proxy
|
16
16
|
* Value compression via `Juno::Transformer` proxy (Zlib, Snappy, QuickLZ, LZO)
|
17
|
-
* Expiration for all stores (Added via proxy if not supported natively)
|
18
|
-
* Integration with Rack as session store and Rack-Cache
|
17
|
+
* Expiration for all stores (Added via proxy `Juno::Expires` if not supported natively)
|
18
|
+
* Integration with [Rack](http://rack.github.com/) as cookie and session store and [Rack-Cache](https://github.com/rtomayko/rack-cache)
|
19
|
+
|
20
|
+
Juno is tested thoroughly using [Travis-CI](http://travis-ci.org/minad/juno).
|
19
21
|
|
20
22
|
Supported backends
|
21
23
|
------------------
|
@@ -23,44 +25,40 @@ Supported backends
|
|
23
25
|
Out of the box, it supports the following backends:
|
24
26
|
|
25
27
|
* Memory:
|
26
|
-
* In-memory store (
|
27
|
-
* LRU hash (
|
28
|
-
* LocalMemCache (
|
29
|
-
* Memcached store (
|
28
|
+
* In-memory store (`:Memory`)
|
29
|
+
* LRU hash (`:LRUHash`)
|
30
|
+
* LocalMemCache (`:LocalMemCache`)
|
31
|
+
* Memcached store (`:Memcached`, `:MemcachedNative` and `:MemcachedDalli`)
|
30
32
|
* Relational Databases:
|
31
|
-
* DataMapper (
|
32
|
-
* ActiveRecord (
|
33
|
-
* Sequel (
|
34
|
-
* Sqlite3 (
|
33
|
+
* DataMapper (`:DataMapper`)
|
34
|
+
* ActiveRecord (`:ActiveRecord`)
|
35
|
+
* Sequel (`:Sequel`)
|
36
|
+
* Sqlite3 (`:Sqlite`)
|
35
37
|
* Filesystem:
|
36
|
-
* PStore (
|
37
|
-
* YAML store (
|
38
|
-
* Filesystem directory store (
|
39
|
-
* Filesystem directory store which spreads files in subdirectories using md5 hash (
|
38
|
+
* PStore (`:PStore`)
|
39
|
+
* YAML store (`:YAML`)
|
40
|
+
* Filesystem directory store (`:File`)
|
41
|
+
* Filesystem directory store which spreads files in subdirectories using md5 hash (`:HashFile`)
|
40
42
|
* Key/value databases:
|
41
|
-
* Berkeley DB (
|
42
|
-
* GDBM (
|
43
|
-
* SDBM (
|
44
|
-
* Redis (
|
45
|
-
* Riak (
|
46
|
-
* TokyoCabinet (
|
47
|
-
* Cassandra (
|
43
|
+
* Berkeley DB (`:DBM`)
|
44
|
+
* GDBM (`:GDBM`)
|
45
|
+
* SDBM (`:SDBM`)
|
46
|
+
* Redis (`:Redis`)
|
47
|
+
* Riak (`:Riak`)
|
48
|
+
* TokyoCabinet (`:TokyoCabinet`)
|
49
|
+
* Cassandra (`:Cassandra`)
|
50
|
+
* LevelDB (`:LevelDB`)
|
48
51
|
* Document databases:
|
49
|
-
* CouchDB (
|
50
|
-
* MongoDB (
|
52
|
+
* CouchDB (`:Couch`)
|
53
|
+
* MongoDB (`:Mongo`)
|
51
54
|
* Other
|
52
|
-
* Fog cloud storage which supports Amazon S3, Rackspace, etc. (
|
53
|
-
* Storage which doesn't store anything (
|
54
|
-
|
55
|
-
Supported serializers:
|
55
|
+
* Fog cloud storage which supports Amazon S3, Rackspace, etc. (`:Fog`)
|
56
|
+
* Storage which doesn't store anything (`:Null`)
|
56
57
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
* BSON
|
62
|
-
* Ox
|
63
|
-
* BERT
|
58
|
+
Some of the backends are not exactly based on key/value stores, e.g. the relational ones. These
|
59
|
+
are useful if you already use the corresponding backend in your application. You get a key/value
|
60
|
+
store for free then without installing any additional services and you still have the possibility
|
61
|
+
to upgrade to a real key/value store.
|
64
62
|
|
65
63
|
Proxies
|
66
64
|
-------
|
@@ -69,16 +67,45 @@ In addition it supports proxies (Similar to [Rack middlewares](http://rack.githu
|
|
69
67
|
add additional features to storage backends:
|
70
68
|
|
71
69
|
* `Juno::Proxy` proxy base class
|
72
|
-
* `Juno::Expires` to add expiration support to stores which don't support it natively
|
73
|
-
* `Juno::Stack` to stack multiple stores (Read returns result from first where the key is found, writes go to all stores)
|
74
|
-
* `Juno::Transformer` transforms keys and values (Marshal, YAML, JSON, Base64, MD5, ...)
|
75
|
-
* `Juno::Cache` combine two stores, one as backend and one as cache (e.g. Juno::Adapters::File + Juno::Adapters::Memory)
|
76
|
-
* `Juno::Lock` to make store thread safe
|
77
|
-
* `Juno::Logger` to log database accesses
|
70
|
+
* `Juno::Expires` to add expiration support to stores which don't support it natively. Add it in the builder using `use :Expires`.
|
71
|
+
* `Juno::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`.
|
72
|
+
* `Juno::Transformer` transforms keys and values (Marshal, YAML, JSON, Base64, MD5, ...). Add it in the builder using `use :Transformer`.
|
73
|
+
* `Juno::Cache` combine two stores, one as backend and one as cache (e.g. `Juno::Adapters::File` + `Juno::Adapters::Memory`). Add it in the builder using `use :Cache`.
|
74
|
+
* `Juno::Lock` to make store thread safe. Add it in the builder using `use :Lock`.
|
75
|
+
* `Juno::Logger` to log database accesses. Add it in the builder using `use :Logger`.
|
78
76
|
|
79
77
|
The Juno API is purposely extremely similar to the Hash API. In order so support an
|
80
78
|
identical API across stores, it does not support iteration or partial matches.
|
81
79
|
|
80
|
+
Supported serializers and compressors (`Juno::Transformer`)
|
81
|
+
-----------------------------------------------------------
|
82
|
+
|
83
|
+
Supported serializers:
|
84
|
+
|
85
|
+
* BEncode (`:bencode`)
|
86
|
+
* BERT (`:bert`)
|
87
|
+
* BSON (`:bson`)
|
88
|
+
* JSON (`:json`)
|
89
|
+
* Marshal (`:marshal`)
|
90
|
+
* MessagePack (`:msgpack`)
|
91
|
+
* Ox (`:ox`)
|
92
|
+
* TNetStrings (`:tnet`)
|
93
|
+
* YAML (`:yaml`)
|
94
|
+
|
95
|
+
Supported value compressors:
|
96
|
+
|
97
|
+
* LZMA (`:lzma`)
|
98
|
+
* LZO (`:lzo`)
|
99
|
+
* Snappy (`:snappy`)
|
100
|
+
* QuickLZ (`:quicklz`)
|
101
|
+
* Zlib (`:zlib`)
|
102
|
+
|
103
|
+
Special transformers:
|
104
|
+
|
105
|
+
* Digests (MD5, Shas, ...)
|
106
|
+
* Add prefix to keys (`:prefix`)
|
107
|
+
* HMAC to verify values (`:hmac`, useful for `Rack::JunoCookies`)
|
108
|
+
|
82
109
|
Links
|
83
110
|
-----
|
84
111
|
|
@@ -175,9 +202,9 @@ end
|
|
175
202
|
Framework Integration
|
176
203
|
---------------------
|
177
204
|
|
178
|
-
Inspired by [redis-store](https://github.com/jodosha/redis-store) there exist integration classes for Rack and Rack-Cache.
|
205
|
+
Inspired by [redis-store](https://github.com/jodosha/redis-store) there exist integration classes for [Rack](http://rack.github.com/) and [Rack-Cache](https://github.com/rtomayko/rack-cache).
|
179
206
|
|
180
|
-
Use Juno as a Rack session store:
|
207
|
+
Use Juno as a [Rack](http://rack.github.com/) session store:
|
181
208
|
|
182
209
|
~~~ ruby
|
183
210
|
require 'rack/session/juno'
|
@@ -191,7 +218,7 @@ use Rack::Session::Juno do
|
|
191
218
|
end
|
192
219
|
~~~
|
193
220
|
|
194
|
-
Use Juno as a Rack-Cache store:
|
221
|
+
Use Juno as a [Rack-Cache](https://github.com/rtomayko/rack-cache) store:
|
195
222
|
|
196
223
|
~~~ ruby
|
197
224
|
require 'rack/cache/juno'
|
@@ -210,20 +237,23 @@ use Rack::Cache,
|
|
210
237
|
:entity_store => 'juno://named_entitystore'
|
211
238
|
~~~
|
212
239
|
|
213
|
-
Use Juno to store cookies in Rack
|
240
|
+
Use Juno to store cookies in [Rack](http://rack.github.com/). It uses the `Juno::Adapters::Cookie`. You might
|
241
|
+
wonder what the purpose of this store or Rack middleware is: It makes it possible
|
242
|
+
to use all the transformers on the cookies (e.g. `:prefix`, `:marshal` and `:hmac` for value verification).
|
214
243
|
|
215
244
|
~~~ ruby
|
216
245
|
require 'rack/juno_cookies'
|
217
246
|
|
218
247
|
use Rack::JunoCookies, :domain => 'example.com', :path => '/path'
|
219
|
-
run lambda
|
248
|
+
run lambda do |env|
|
220
249
|
req = Rack::Request.new(env)
|
221
|
-
req.cookies #=> is now a Juno store
|
250
|
+
req.cookies #=> is now a Juno store!
|
251
|
+
env['rack.request.cookie_hash'] #=> is now a Juno store!
|
222
252
|
req.cookies['key'] #=> retrieves 'key'
|
223
253
|
req.cookies['key'] = 'value' #=> sets 'key'
|
224
254
|
req.cookies.delete('key') #=> removes 'key'
|
225
|
-
[200,{},[]]
|
226
|
-
|
255
|
+
[200, {}, []]
|
256
|
+
end
|
227
257
|
~~~
|
228
258
|
|
229
259
|
Alternatives
|
data/SPEC.md
CHANGED
@@ -65,20 +65,7 @@ The following methods may all take an additional Hash as a final argument. This
|
|
65
65
|
|
66
66
|
In the case of methods with optional arguments, the Hash MUST be provided as the final argument. Keys in this Hash MUST be Symbols.
|
67
67
|
|
68
|
-
# Key Equality
|
69
|
-
|
70
|
-
Adapters MUST consider keys as equal to one another if and only if the value of <code>Marshal.dump(keya)</code> is the same (byte-for-byte) as <code>Marshal.dump(keyb)</code>. This does not mean that adapters are required to use <code>Marshal.dump</code> to calculate the key to use for a given key specified by the consumer of the adapter. However, if an adapter does not, it MUST guarantee that the value returned for every key is identical to the value that would be returned if it did a byte-for-byte comparison of the result of <code>Marshal.dump</code> for every operation involving a key.
|
71
|
-
|
72
|
-
# Storage and Serialization
|
73
|
-
|
74
|
-
In a Juno-compliant adapter, any Ruby object that can be serialized using Ruby's marshalling system may be used for keys or values.
|
75
|
-
|
76
|
-
Adapters MAY use the marshalling system to serialize Ruby objects. Adapters MUST NOT return an Object from a fetch operation that existed on the heap prior to the fetch operation. The intention of this requirement is to prevent adapters that use the heap for persistence to store direct references to Objects passed into the <code>store</code> or <code>[]=</code> methods.
|
77
|
-
|
78
68
|
# Atomicity
|
79
69
|
|
80
70
|
The base Juno specification does not specify any atomicity guarantees. However, extensions to this spec may specify extensions that define additional guarantees for any of the defined operations.
|
81
71
|
|
82
|
-
# Expiry
|
83
|
-
|
84
|
-
The base Juno specification does not specify any mechanism for time-based expiry. However, extensions to this spec may specify mechanisms (using <code>store</code> to provide expiration semantics.
|
data/lib/juno.rb
CHANGED
@@ -19,6 +19,7 @@ module Juno
|
|
19
19
|
autoload :File, 'juno/adapters/file'
|
20
20
|
autoload :Fog, 'juno/adapters/fog'
|
21
21
|
autoload :GDBM, 'juno/adapters/gdbm'
|
22
|
+
autoload :LevelDB, 'juno/adapters/leveldb'
|
22
23
|
autoload :LocalMemCache, 'juno/adapters/localmemcache'
|
23
24
|
autoload :LRUHash, 'juno/adapters/lruhash'
|
24
25
|
autoload :Memcached, 'juno/adapters/memcached'
|
@@ -73,7 +74,7 @@ module Juno
|
|
73
74
|
transformer = { :key => [key_serializer], :value => [value_serializer], :prefix => options.delete(:prefix) }
|
74
75
|
transformer[:key] << :prefix if transformer[:prefix]
|
75
76
|
transformer[:value] << (Symbol === compress ? compress : :zlib) if compress
|
76
|
-
raise 'Name must be Symbol' unless Symbol === name
|
77
|
+
raise ArgumentError, 'Name must be Symbol' unless Symbol === name
|
77
78
|
case name
|
78
79
|
when :Sequel, :ActiveRecord, :Couch
|
79
80
|
# Sequel accept only base64 keys and values
|
@@ -13,42 +13,66 @@ module Juno
|
|
13
13
|
# @param [Hash] options
|
14
14
|
#
|
15
15
|
# Options:
|
16
|
-
# * :keyspace - Cassandra keyspace (default
|
17
|
-
# * :column_family - Cassandra column family (default
|
16
|
+
# * :keyspace - Cassandra keyspace (default 'juno')
|
17
|
+
# * :column_family - Cassandra column family (default 'juno')
|
18
18
|
# * :host - Server host name (default 127.0.0.1)
|
19
19
|
# * :port - Server port (default 9160)
|
20
20
|
def initialize(options = {})
|
21
|
-
options[:
|
22
|
-
options[:
|
23
|
-
options[:
|
24
|
-
@
|
25
|
-
@client = ::Cassandra.new(
|
21
|
+
options[:host] ||= '127.0.0.1'
|
22
|
+
options[:port] ||= 9160
|
23
|
+
keyspace = (options[:keyspace] ||= 'juno')
|
24
|
+
@cf = (options[:column_family] || 'juno').to_sym
|
25
|
+
@client = ::Cassandra.new('system', "#{options[:host]}:#{options[:port]}")
|
26
|
+
unless @client.keyspaces.include?(keyspace)
|
27
|
+
cf_def = ::Cassandra::ColumnFamily.new(:keyspace => keyspace, :name => @cf.to_s)
|
28
|
+
ks_def = ::Cassandra::Keyspace.new(:name => keyspace,
|
29
|
+
:strategy_class => 'SimpleStrategy',
|
30
|
+
:strategy_options => { 'replication_factor' => '1' },
|
31
|
+
:replication_factor => 1,
|
32
|
+
:cf_defs => [cf_def])
|
33
|
+
# Wait for keyspace to be created (issue #24)
|
34
|
+
10.times do
|
35
|
+
begin
|
36
|
+
@client.add_keyspace(ks_def)
|
37
|
+
rescue Exception => ex
|
38
|
+
puts "Cassandra: #{ex.message}"
|
39
|
+
end
|
40
|
+
break if @client.keyspaces.include?(keyspace)
|
41
|
+
sleep 0.1
|
42
|
+
end
|
43
|
+
end
|
44
|
+
@client.keyspace = keyspace
|
26
45
|
end
|
27
46
|
|
28
47
|
def key?(key, options = {})
|
29
|
-
@client.exists?(@
|
48
|
+
@client.exists?(@cf, key)
|
30
49
|
end
|
31
50
|
|
32
51
|
def load(key, options = {})
|
33
|
-
value = @client.get(@
|
34
|
-
|
52
|
+
value = @client.get(@cf, key)
|
53
|
+
if value
|
54
|
+
if options.include?(:expires)
|
55
|
+
store(key, value['value'], options)
|
56
|
+
else
|
57
|
+
value['value']
|
58
|
+
end
|
59
|
+
end
|
35
60
|
end
|
36
61
|
|
37
62
|
def delete(key, options = {})
|
38
63
|
if value = load(key, options)
|
39
|
-
@client.remove(@
|
64
|
+
@client.remove(@cf, key)
|
40
65
|
value
|
41
66
|
end
|
42
67
|
end
|
43
68
|
|
44
69
|
def store(key, value, options = {})
|
45
|
-
@client.insert(@
|
46
|
-
{'value' => value}, :ttl => options[:expires])
|
70
|
+
@client.insert(@cf, key, {'value' => value}, :ttl => options[:expires])
|
47
71
|
value
|
48
72
|
end
|
49
73
|
|
50
74
|
def clear(options = {})
|
51
|
-
@client.each_key(@
|
75
|
+
@client.each_key(@cf) do |key|
|
52
76
|
delete(key)
|
53
77
|
end
|
54
78
|
self
|
data/lib/juno/adapters/couch.rb
CHANGED
@@ -12,7 +12,7 @@ module Juno
|
|
12
12
|
# Options:
|
13
13
|
# * :db - Couch database
|
14
14
|
def initialize(options = {})
|
15
|
-
raise 'Option :db is required' unless options[:db]
|
15
|
+
raise ArgumentError, 'Option :db is required' unless options[:db]
|
16
16
|
@db = ::CouchRest.database!(options[:db])
|
17
17
|
end
|
18
18
|
|
@@ -23,13 +23,13 @@ module Juno
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def load(key, options = {})
|
26
|
-
@db.get(key)['
|
26
|
+
@db.get(key)['value']
|
27
27
|
rescue RestClient::ResourceNotFound
|
28
28
|
nil
|
29
29
|
end
|
30
30
|
|
31
31
|
def store(key, value, options = {})
|
32
|
-
doc = {'_id' => key, '
|
32
|
+
doc = {'_id' => key, 'value' => value}
|
33
33
|
begin
|
34
34
|
doc['_rev'] = @db.get(key)['_rev']
|
35
35
|
rescue RestClient::ResourceNotFound
|
@@ -43,7 +43,7 @@ module Juno
|
|
43
43
|
def delete(key, options = {})
|
44
44
|
value = @db.get(key)
|
45
45
|
@db.delete_doc('_id' => value['_id'], '_rev' => value['_rev'])
|
46
|
-
value['
|
46
|
+
value['value']
|
47
47
|
rescue RestClient::ResourceNotFound
|
48
48
|
nil
|
49
49
|
end
|
@@ -21,7 +21,7 @@ module Juno
|
|
21
21
|
# * :repository - Repository name (default :juno)
|
22
22
|
# * :table - Table name (default :juno)
|
23
23
|
def initialize(options = {})
|
24
|
-
raise 'Option :setup is required' unless options[:setup]
|
24
|
+
raise ArgumentError, 'Option :setup is required' unless options[:setup]
|
25
25
|
@repository = options.delete(:repository) || :juno
|
26
26
|
Store.storage_names[@repository] = (options.delete(:table) || :juno).to_s
|
27
27
|
::DataMapper.setup(@repository, options[:setup])
|
data/lib/juno/adapters/dbm.rb
CHANGED
@@ -12,7 +12,7 @@ module Juno
|
|
12
12
|
# Options:
|
13
13
|
# * :file - Database file
|
14
14
|
def initialize(options = {})
|
15
|
-
raise 'Option :file is required' unless options[:file]
|
15
|
+
raise ArgumentError, 'Option :file is required' unless options[:file]
|
16
16
|
@memory = ::DBM.new(options[:file])
|
17
17
|
end
|
18
18
|
|
data/lib/juno/adapters/file.rb
CHANGED
@@ -6,9 +6,9 @@ module Juno
|
|
6
6
|
# @api public
|
7
7
|
class File < Base
|
8
8
|
def initialize(options = {})
|
9
|
-
raise 'Option :dir is required' unless @dir = options[:dir]
|
9
|
+
raise ArgumentError, 'Option :dir is required' unless @dir = options[:dir]
|
10
10
|
FileUtils.mkpath(@dir)
|
11
|
-
raise "#{@dir} is not a
|
11
|
+
raise "#{@dir} is not a directory" unless ::File.directory?(@dir)
|
12
12
|
end
|
13
13
|
|
14
14
|
def key?(key, options = {})
|
data/lib/juno/adapters/fog.rb
CHANGED
@@ -13,7 +13,7 @@ module Juno
|
|
13
13
|
# * :dir - Fog directory
|
14
14
|
# * Other options passed to Fog::Storage#new
|
15
15
|
def initialize(options = {})
|
16
|
-
raise 'Option :dir is required' unless dir = options.delete(:dir)
|
16
|
+
raise ArgumentError, 'Option :dir is required' unless dir = options.delete(:dir)
|
17
17
|
storage = ::Fog::Storage.new(options)
|
18
18
|
@directory = storage.directories.create(:key => dir)
|
19
19
|
end
|
data/lib/juno/adapters/gdbm.rb
CHANGED
@@ -12,7 +12,7 @@ module Juno
|
|
12
12
|
# Options:
|
13
13
|
# * :file - Database file
|
14
14
|
def initialize(options = {})
|
15
|
-
raise 'Option :file is required' unless options[:file]
|
15
|
+
raise ArgumentError, 'Option :file is required' unless options[:file]
|
16
16
|
@memory = ::GDBM.new(options[:file])
|
17
17
|
end
|
18
18
|
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'leveldb'
|
2
|
+
|
3
|
+
module Juno
|
4
|
+
module Adapters
|
5
|
+
# LevelDB backend
|
6
|
+
# @api public
|
7
|
+
class LevelDB < Memory
|
8
|
+
# Constructor
|
9
|
+
#
|
10
|
+
# @param [Hash] options
|
11
|
+
#
|
12
|
+
# Options:
|
13
|
+
# * :dir - Database path
|
14
|
+
# * All other options passed to LevelDB::DB#new
|
15
|
+
def initialize(options = {})
|
16
|
+
raise ArgumentError, 'Option :dir is required' unless options[:dir]
|
17
|
+
@memory = ::LevelDB::DB.new(options[:dir])
|
18
|
+
end
|
19
|
+
|
20
|
+
def key?(key, options = {})
|
21
|
+
@memory.includes?(key)
|
22
|
+
end
|
23
|
+
|
24
|
+
def clear(options = {})
|
25
|
+
@memory.each {|k,v| delete(k, options) }
|
26
|
+
self
|
27
|
+
end
|
28
|
+
|
29
|
+
def close
|
30
|
+
@memory.close
|
31
|
+
nil
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|