juno 0.1.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 +4 -0
- data/.travis.yml +25 -0
- data/Gemfile +19 -0
- data/LICENSE +20 -0
- data/README.md +83 -0
- data/Rakefile +15 -0
- data/SPEC.md +95 -0
- data/juno.gemspec +22 -0
- data/lib/juno.rb +31 -0
- data/lib/juno/activerecord.rb +58 -0
- data/lib/juno/base.rb +113 -0
- data/lib/juno/couch.rb +43 -0
- data/lib/juno/datamapper.rb +63 -0
- data/lib/juno/dbm.rb +15 -0
- data/lib/juno/expires.rb +45 -0
- data/lib/juno/file.rb +62 -0
- data/lib/juno/gdbm.rb +15 -0
- data/lib/juno/hashfile.rb +12 -0
- data/lib/juno/localmemcache.rb +16 -0
- data/lib/juno/memcached.rb +7 -0
- data/lib/juno/memcached_dalli.rb +55 -0
- data/lib/juno/memcached_native.rb +56 -0
- data/lib/juno/memory.rb +7 -0
- data/lib/juno/mongodb.rb +43 -0
- data/lib/juno/proxy.rb +5 -0
- data/lib/juno/pstore.rb +49 -0
- data/lib/juno/redis.rb +34 -0
- data/lib/juno/riak.rb +45 -0
- data/lib/juno/sdbm.rb +15 -0
- data/lib/juno/sequel.rb +51 -0
- data/lib/juno/sqlite.rb +50 -0
- data/lib/juno/tokyocabinet.rb +36 -0
- data/lib/juno/version.rb +3 -0
- data/lib/juno/yaml.rb +9 -0
- data/test/helper.rb +182 -0
- data/test/test_active_record.rb +36 -0
- data/test/test_couch.rb +13 -0
- data/test/test_datamapper.rb +64 -0
- data/test/test_dbm.rb +13 -0
- data/test/test_expires.rb +10 -0
- data/test/test_file.rb +9 -0
- data/test/test_gdbm.rb +13 -0
- data/test/test_hashfile.rb +9 -0
- data/test/test_localmemcache.rb +13 -0
- data/test/test_memcached.rb +15 -0
- data/test/test_memcached_dalli.rb +15 -0
- data/test/test_memcached_native.rb +15 -0
- data/test/test_memory.rb +9 -0
- data/test/test_mongodb.rb +13 -0
- data/test/test_proxy.rb +9 -0
- data/test/test_pstore.rb +9 -0
- data/test/test_redis.rb +13 -0
- data/test/test_riak.rb +13 -0
- data/test/test_sdbm.rb +13 -0
- data/test/test_sequel.rb +13 -0
- data/test/test_sqlite.rb +13 -0
- data/test/test_tokyocabinet.rb +13 -0
- data/test/test_yaml.rb +9 -0
- data/unsupported/benchmarks.rb +234 -0
- data/unsupported/cassandra.rb +45 -0
- data/unsupported/fog.rb +60 -0
- data/unsupported/test_cassandra.rb +13 -0
- data/unsupported/test_rackspace.rb +15 -0
- data/unsupported/test_s3.rb +15 -0
- data/unsupported/test_tokyotyrant.rb +13 -0
- data/unsupported/tokyotyrant.rb +29 -0
- metadata +165 -0
data/lib/juno/couch.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'couchrest'
|
2
|
+
|
3
|
+
module Juno
|
4
|
+
class Couch < Base
|
5
|
+
def initialize(options = {})
|
6
|
+
@db = ::CouchRest.database!(options[:db])
|
7
|
+
end
|
8
|
+
|
9
|
+
def key?(key, options = {})
|
10
|
+
!!self[key_for(key)]
|
11
|
+
rescue RestClient::ResourceNotFound
|
12
|
+
false
|
13
|
+
end
|
14
|
+
|
15
|
+
def [](key)
|
16
|
+
deserialize(@db.get(key_for(key))['data'])
|
17
|
+
rescue RestClient::ResourceNotFound
|
18
|
+
nil
|
19
|
+
end
|
20
|
+
|
21
|
+
def store(key, value, options = {})
|
22
|
+
@db.save_doc('_id' => key_for(key), :data => serialize(value))
|
23
|
+
value
|
24
|
+
rescue RestClient::RequestFailed
|
25
|
+
value
|
26
|
+
end
|
27
|
+
|
28
|
+
def delete(key, options = {})
|
29
|
+
value = @db.get(key_for(key))
|
30
|
+
if value
|
31
|
+
@db.delete_doc({'_id' => value['_id'], '_rev' => value['_rev']}) if value
|
32
|
+
deserialize(value['data'])
|
33
|
+
end
|
34
|
+
rescue RestClient::ResourceNotFound
|
35
|
+
nil
|
36
|
+
end
|
37
|
+
|
38
|
+
def clear(options = {})
|
39
|
+
@db.recreate!
|
40
|
+
nil
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'dm-core'
|
2
|
+
require 'dm-migrations'
|
3
|
+
|
4
|
+
module Juno
|
5
|
+
class DataMapper < Base
|
6
|
+
class Store
|
7
|
+
include ::DataMapper::Resource
|
8
|
+
property :k, String, :key => true
|
9
|
+
property :v, Object, :lazy => false
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(options = {})
|
13
|
+
raise 'No option :setup specified' unless options[:setup]
|
14
|
+
@repository = options.delete(:repository) || :juno
|
15
|
+
Store.storage_names[@repository] = options.delete(:table) || :juno
|
16
|
+
::DataMapper.setup(@repository, options[:setup])
|
17
|
+
context { Store.auto_upgrade! }
|
18
|
+
end
|
19
|
+
|
20
|
+
def key?(key, options = {})
|
21
|
+
context { !!Store.get(key_for(key)) }
|
22
|
+
end
|
23
|
+
|
24
|
+
def [](key)
|
25
|
+
context do
|
26
|
+
record = Store.get(key_for(key))
|
27
|
+
record ? record.v : nil
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def store(key, value, options = {})
|
32
|
+
key = key_for(key)
|
33
|
+
context do
|
34
|
+
record = Store.get(key)
|
35
|
+
if record
|
36
|
+
record.update(key, value)
|
37
|
+
else
|
38
|
+
Store.create(:k => key, :v => value)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
value
|
42
|
+
end
|
43
|
+
|
44
|
+
def delete(key, options = {})
|
45
|
+
context do
|
46
|
+
value = self[key]
|
47
|
+
Store.all(:k => key_for(key)).destroy!
|
48
|
+
value
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def clear(options = {})
|
53
|
+
context { Store.all.destroy! }
|
54
|
+
nil
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def context
|
60
|
+
::DataMapper.repository(@repository) { yield }
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/lib/juno/dbm.rb
ADDED
data/lib/juno/expires.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
module Juno
|
2
|
+
class Expires < Proxy
|
3
|
+
def key?(key, options = {})
|
4
|
+
!!self[key]
|
5
|
+
end
|
6
|
+
|
7
|
+
def fetch(key, value = nil, options = {}, &block)
|
8
|
+
result = check_expired(key, super(key, value, options, &block))
|
9
|
+
if result && options.include?(:expires)
|
10
|
+
store(key, result, options)
|
11
|
+
else
|
12
|
+
result
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def [](key)
|
17
|
+
check_expired(key, super(key))
|
18
|
+
end
|
19
|
+
|
20
|
+
def store(key, value, options = {})
|
21
|
+
if expires = options.delete(:expires)
|
22
|
+
super(key, [value, Time.now.to_i + expires].compact, options)
|
23
|
+
else
|
24
|
+
super(key, [value], options)
|
25
|
+
end
|
26
|
+
value
|
27
|
+
end
|
28
|
+
|
29
|
+
def delete(key, options = {})
|
30
|
+
check_expired(key, super, false)
|
31
|
+
end
|
32
|
+
|
33
|
+
protected
|
34
|
+
|
35
|
+
def check_expired(key, value, delete_expired = true)
|
36
|
+
value, expires = value
|
37
|
+
if expires && Time.now.to_i > expires
|
38
|
+
delete(key) if delete_expired
|
39
|
+
nil
|
40
|
+
else
|
41
|
+
value
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/juno/file.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module Juno
|
4
|
+
class File < Base
|
5
|
+
def initialize(options = {})
|
6
|
+
raise 'No option :dir specified' unless @dir = options[:dir]
|
7
|
+
FileUtils.mkpath(@dir)
|
8
|
+
raise "#{@dir} is not a dir" unless ::File.directory?(@dir)
|
9
|
+
end
|
10
|
+
|
11
|
+
def key?(key, options = {})
|
12
|
+
::File.exist?(store_path(key))
|
13
|
+
end
|
14
|
+
|
15
|
+
def [](key)
|
16
|
+
deserialize(::File.read(store_path(key)))
|
17
|
+
rescue Errno::ENOENT
|
18
|
+
end
|
19
|
+
|
20
|
+
def store(key, value, options = {})
|
21
|
+
path = store_path(key)
|
22
|
+
temp_file = ::File.join(@dir, "value-#{$$}-#{Thread.current.object_id}")
|
23
|
+
FileUtils.mkpath(::File.dirname(path))
|
24
|
+
::File.open(temp_file, 'wb') {|file| file.write(serialize(value)) }
|
25
|
+
::File.unlink(path) if ::File.exist?(path)
|
26
|
+
::File.rename(temp_file, path)
|
27
|
+
value
|
28
|
+
rescue Errno::ENOENT
|
29
|
+
::File.unlink(temp_file) rescue nil
|
30
|
+
value
|
31
|
+
end
|
32
|
+
|
33
|
+
def delete(key, options = {})
|
34
|
+
value = self[key]
|
35
|
+
::File.unlink(store_path(key))
|
36
|
+
value
|
37
|
+
rescue Errno::ENOENT
|
38
|
+
end
|
39
|
+
|
40
|
+
def clear(options = {})
|
41
|
+
temp_dir = "#{@dir}-#{$$}-#{Thread.current.object_id}"
|
42
|
+
::File.rename(@dir, temp_dir)
|
43
|
+
FileUtils.mkpath(@dir)
|
44
|
+
FileUtils.rm_rf(temp_dir)
|
45
|
+
nil
|
46
|
+
rescue Errno::ENOENT
|
47
|
+
nil
|
48
|
+
end
|
49
|
+
|
50
|
+
protected
|
51
|
+
|
52
|
+
def escape(s)
|
53
|
+
s.gsub(/[^a-zA-Z0-9_-]+/) do
|
54
|
+
'%' + $&.unpack('H2' * $&.bytesize).join('%').upcase
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def store_path(key)
|
59
|
+
::File.join(@dir, escape(key_for(key)))
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
data/lib/juno/gdbm.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'localmemcache'
|
2
|
+
|
3
|
+
module Juno
|
4
|
+
class LocalMemCache < Base
|
5
|
+
def initialize(options = {})
|
6
|
+
raise 'No option :file specified' unless options[:file]
|
7
|
+
@store = ::LocalMemCache.new(:filename => options[:file])
|
8
|
+
end
|
9
|
+
|
10
|
+
def delete(key, options = {})
|
11
|
+
value = self[key]
|
12
|
+
@store.delete(key_for(key))
|
13
|
+
value
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'dalli'
|
2
|
+
|
3
|
+
module Juno
|
4
|
+
class MemcachedDalli < Base
|
5
|
+
def initialize(options = {})
|
6
|
+
server = options.delete(:server) || 'localhost:11211'
|
7
|
+
@cache = ::Dalli::Client.new(server, options)
|
8
|
+
end
|
9
|
+
|
10
|
+
def key?(key, options = {})
|
11
|
+
!!@cache.get(key_for(key))
|
12
|
+
end
|
13
|
+
|
14
|
+
def fetch(key, value = nil, options = {})
|
15
|
+
result = super
|
16
|
+
if result && options.include?(:expires)
|
17
|
+
store(key, result, options)
|
18
|
+
else
|
19
|
+
result
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def [](key)
|
24
|
+
deserialize(@cache.get(key_for(key)))
|
25
|
+
end
|
26
|
+
|
27
|
+
def store(key, value, options = {})
|
28
|
+
@cache.set(key_for(key), serialize(value), options[:expires])
|
29
|
+
value
|
30
|
+
end
|
31
|
+
|
32
|
+
def delete(key, options = {})
|
33
|
+
key = key_for(key)
|
34
|
+
value = deserialize(@cache.get(key))
|
35
|
+
@cache.delete(key)
|
36
|
+
value
|
37
|
+
end
|
38
|
+
|
39
|
+
def clear(options = {})
|
40
|
+
@cache.flush_all
|
41
|
+
nil
|
42
|
+
end
|
43
|
+
|
44
|
+
def close
|
45
|
+
@cache.close
|
46
|
+
nil
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def key_for(key)
|
52
|
+
[super].pack('m').strip
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'memcached'
|
2
|
+
|
3
|
+
module Juno
|
4
|
+
class MemcachedNative < Base
|
5
|
+
def initialize(options = {})
|
6
|
+
server = options.delete(:server) || 'localhost:11211'
|
7
|
+
@cache = ::Memcached.new(server, options)
|
8
|
+
end
|
9
|
+
|
10
|
+
def key?(key, options = {})
|
11
|
+
@cache.get(key_for(key), false)
|
12
|
+
true
|
13
|
+
rescue ::Memcached::NotFound
|
14
|
+
false
|
15
|
+
end
|
16
|
+
|
17
|
+
def fetch(key, value = nil, options = {})
|
18
|
+
result = super
|
19
|
+
if result && options.include?(:expires)
|
20
|
+
store(key, result, options)
|
21
|
+
else
|
22
|
+
result
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def [](key)
|
27
|
+
deserialize(@cache.get(key_for(key), false))
|
28
|
+
rescue ::Memcached::NotFound
|
29
|
+
end
|
30
|
+
|
31
|
+
def delete(key, options = {})
|
32
|
+
key = key_for(key)
|
33
|
+
value = deserialize(@cache.get(key, false))
|
34
|
+
@cache.delete(key)
|
35
|
+
value
|
36
|
+
rescue ::Memcached::NotFound
|
37
|
+
end
|
38
|
+
|
39
|
+
def store(key, value, options = {})
|
40
|
+
ttl = options[:expires] || ::Memcached::DEFAULTS[:default_ttl]
|
41
|
+
@cache.set(key_for(key), serialize(value), ttl, false)
|
42
|
+
value
|
43
|
+
end
|
44
|
+
|
45
|
+
def clear(options = {})
|
46
|
+
@cache.flush
|
47
|
+
nil
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def key_for(key)
|
53
|
+
[super].pack('m').strip
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/lib/juno/memory.rb
ADDED
data/lib/juno/mongodb.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'mongo'
|
2
|
+
require 'uri'
|
3
|
+
|
4
|
+
module Juno
|
5
|
+
class MongoDB < Base
|
6
|
+
def initialize(options = {})
|
7
|
+
collection = options.delete(:collection) || 'juno'
|
8
|
+
host = options.delete(:host) || 'localhost'
|
9
|
+
port = options.delete(:port) || Mongo::Connection::DEFAULT_PORT
|
10
|
+
db = options.delete(:db) || 'juno'
|
11
|
+
connection = Mongo::Connection.new(host, port, options)
|
12
|
+
@store = connection.db(db).collection(collection)
|
13
|
+
end
|
14
|
+
|
15
|
+
def key?(key, options = {})
|
16
|
+
!!self[key]
|
17
|
+
end
|
18
|
+
|
19
|
+
def [](key)
|
20
|
+
value = @store.find_one('_id' => key_for(key))
|
21
|
+
value ? deserialize(value['data']) : nil
|
22
|
+
end
|
23
|
+
|
24
|
+
def delete(key, options = {})
|
25
|
+
value = self[key]
|
26
|
+
@store.remove('_id' => key_for(key)) if value
|
27
|
+
value
|
28
|
+
end
|
29
|
+
|
30
|
+
def store(key, value, options = {})
|
31
|
+
key = key_for(key)
|
32
|
+
@store.update({ '_id' => key },
|
33
|
+
{ '_id' => key, 'data' => serialize(value) },
|
34
|
+
{ :upsert => true })
|
35
|
+
value
|
36
|
+
end
|
37
|
+
|
38
|
+
def clear(options = {})
|
39
|
+
@store.remove
|
40
|
+
nil
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|