juno 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -1
- data/.travis.yml +6 -0
- data/Gemfile +16 -9
- data/README.md +92 -34
- data/Rakefile +23 -5
- data/benchmarks/run.rb +19 -22
- data/juno.gemspec +0 -3
- data/lib/juno/adapters/activerecord.rb +58 -0
- data/lib/juno/adapters/cassandra.rb +47 -0
- data/lib/juno/adapters/couch.rb +43 -0
- data/lib/juno/adapters/datamapper.rb +64 -0
- data/lib/juno/adapters/dbm.rb +17 -0
- data/lib/juno/adapters/file.rb +58 -0
- data/lib/juno/adapters/fog.rb +42 -0
- data/lib/juno/adapters/gdbm.rb +17 -0
- data/lib/juno/adapters/localmemcache.rb +18 -0
- data/lib/juno/adapters/memcached.rb +11 -0
- data/lib/juno/adapters/memcached_dalli.rb +46 -0
- data/lib/juno/adapters/memcached_native.rb +47 -0
- data/lib/juno/adapters/memory.rb +30 -0
- data/lib/juno/adapters/mongo.rb +43 -0
- data/lib/juno/adapters/null.rb +28 -0
- data/lib/juno/adapters/pstore.rb +51 -0
- data/lib/juno/adapters/redis.rb +43 -0
- data/lib/juno/adapters/riak.rb +46 -0
- data/lib/juno/adapters/sdbm.rb +27 -0
- data/lib/juno/adapters/sequel.rb +50 -0
- data/lib/juno/adapters/sqlite.rb +52 -0
- data/lib/juno/adapters/tokyocabinet.rb +33 -0
- data/lib/juno/adapters/yaml.rb +13 -0
- data/lib/juno/base.rb +11 -89
- data/lib/juno/builder.rb +30 -0
- data/lib/juno/cache.rb +64 -0
- data/lib/juno/expires.rb +6 -10
- data/lib/juno/proxy.rb +62 -3
- data/lib/juno/stack.rb +27 -11
- data/lib/juno/transformer.rb +106 -0
- data/lib/juno/version.rb +1 -1
- data/lib/juno.rb +81 -29
- data/spec/adapter_activerecord_spec.rb +41 -0
- data/spec/adapter_cassandra_spec.rb +27 -0
- data/spec/adapter_couch_spec.rb +27 -0
- data/spec/adapter_datamapper_spec.rb +61 -0
- data/spec/adapter_dbm_spec.rb +27 -0
- data/spec/adapter_file_spec.rb +27 -0
- data/spec/adapter_fog_spec.rb +35 -0
- data/spec/adapter_gdbm_spec.rb +27 -0
- data/spec/adapter_localmemcache_spec.rb +27 -0
- data/spec/adapter_memcached_dalli_spec.rb +28 -0
- data/spec/adapter_memcached_native_spec.rb +28 -0
- data/spec/adapter_memcached_spec.rb +28 -0
- data/spec/adapter_memory_spec.rb +42 -0
- data/spec/adapter_mongo_spec.rb +27 -0
- data/spec/adapter_pstore_spec.rb +30 -0
- data/spec/adapter_redis_spec.rb +28 -0
- data/spec/adapter_riak_spec.rb +31 -0
- data/spec/adapter_sdbm_spec.rb +27 -0
- data/spec/adapter_sequel_spec.rb +27 -0
- data/spec/adapter_sqlite_spec.rb +27 -0
- data/spec/adapter_tokyocabinet_spec.rb +27 -0
- data/spec/adapter_yaml_spec.rb +30 -0
- data/spec/cache_file_memory_spec.rb +50 -0
- data/spec/cache_memory_null_spec.rb +39 -0
- data/spec/expires_file_spec.rb +82 -0
- data/spec/expires_memory_spec.rb +59 -0
- data/spec/generate.rb +736 -0
- data/spec/helper.rb +39 -0
- data/spec/junospecs.rb +1540 -0
- data/spec/null_adapter_spec.rb +33 -0
- data/spec/proxy_expires_memory_spec.rb +63 -0
- data/spec/proxy_redis_spec.rb +38 -0
- data/spec/simple_activerecord_spec.rb +52 -0
- data/spec/simple_cassandra_spec.rb +53 -0
- data/spec/simple_couch_spec.rb +52 -0
- data/spec/simple_datamapper_spec.rb +54 -0
- data/spec/simple_datamapper_with_repository_spec.rb +54 -0
- data/spec/simple_dbm_spec.rb +52 -0
- data/spec/simple_file_spec.rb +52 -0
- data/spec/simple_fog_spec.rb +60 -0
- data/spec/simple_gdbm_spec.rb +52 -0
- data/spec/simple_hashfile_spec.rb +52 -0
- data/spec/simple_localmemcache_spec.rb +52 -0
- data/spec/simple_memcached_dalli_spec.rb +53 -0
- data/spec/simple_memcached_native_spec.rb +53 -0
- data/spec/simple_memcached_spec.rb +53 -0
- data/spec/simple_memory_spec.rb +52 -0
- data/spec/simple_mongo_spec.rb +52 -0
- data/spec/simple_null_spec.rb +43 -0
- data/spec/simple_pstore_spec.rb +52 -0
- data/spec/simple_redis_spec.rb +53 -0
- data/spec/simple_riak_spec.rb +56 -0
- data/spec/simple_sdbm_spec.rb +52 -0
- data/spec/simple_sequel_spec.rb +52 -0
- data/spec/simple_sqlite_spec.rb +52 -0
- data/spec/simple_tokyocabinet_spec.rb +52 -0
- data/spec/simple_yaml_spec.rb +52 -0
- data/spec/stack_file_memory_spec.rb +43 -0
- data/spec/stack_memory_file_spec.rb +42 -0
- data/spec/transformer_bson_spec.rb +44 -0
- data/spec/transformer_json_spec.rb +44 -0
- data/spec/transformer_marshal_base64_spec.rb +60 -0
- data/spec/transformer_marshal_escape_spec.rb +60 -0
- data/spec/transformer_marshal_md5_spec.rb +60 -0
- data/spec/transformer_marshal_md5_spread_spec.rb +60 -0
- data/spec/transformer_msgpack_spec.rb +44 -0
- data/spec/transformer_yaml_spec.rb +59 -0
- metadata +164 -108
- data/lib/juno/activerecord.rb +0 -55
- data/lib/juno/cassandra.rb +0 -45
- data/lib/juno/couch.rb +0 -43
- data/lib/juno/datamapper.rb +0 -63
- data/lib/juno/dbm.rb +0 -15
- data/lib/juno/file.rb +0 -62
- data/lib/juno/fog.rb +0 -48
- data/lib/juno/gdbm.rb +0 -15
- data/lib/juno/hashfile.rb +0 -12
- data/lib/juno/localmemcache.rb +0 -16
- data/lib/juno/memcached.rb +0 -7
- data/lib/juno/memcached_dalli.rb +0 -55
- data/lib/juno/memcached_native.rb +0 -56
- data/lib/juno/memory.rb +0 -7
- data/lib/juno/mongodb.rb +0 -43
- data/lib/juno/null.rb +0 -23
- data/lib/juno/pstore.rb +0 -49
- data/lib/juno/redis.rb +0 -46
- data/lib/juno/riak.rb +0 -45
- data/lib/juno/sdbm.rb +0 -15
- data/lib/juno/sequel.rb +0 -48
- data/lib/juno/sqlite.rb +0 -50
- data/lib/juno/tokyocabinet.rb +0 -36
- data/lib/juno/yaml.rb +0 -9
- data/test/helper.rb +0 -212
- data/test/test_activerecord.rb +0 -33
- data/test/test_cassandra.rb +0 -13
- data/test/test_couch.rb +0 -13
- data/test/test_datamapper.rb +0 -64
- data/test/test_dbm.rb +0 -13
- data/test/test_expires.rb +0 -9
- data/test/test_file.rb +0 -9
- data/test/test_fog.rb +0 -17
- data/test/test_gdbm.rb +0 -13
- data/test/test_hashfile.rb +0 -9
- data/test/test_localmemcache.rb +0 -13
- data/test/test_memcached.rb +0 -14
- data/test/test_memcached_dalli.rb +0 -14
- data/test/test_memcached_native.rb +0 -14
- data/test/test_memory.rb +0 -9
- data/test/test_mongodb.rb +0 -13
- data/test/test_null.rb +0 -9
- data/test/test_proxy.rb +0 -9
- data/test/test_pstore.rb +0 -9
- data/test/test_redis.rb +0 -13
- data/test/test_riak.rb +0 -13
- data/test/test_sdbm.rb +0 -13
- data/test/test_sequel.rb +0 -13
- data/test/test_sqlite.rb +0 -13
- data/test/test_stack.rb +0 -10
- data/test/test_tokyocabinet.rb +0 -13
- data/test/test_yaml.rb +0 -9
- data/unsupported/test_tokyotyrant.rb +0 -13
- data/unsupported/tokyotyrant.rb +0 -29
data/lib/juno/builder.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
module Juno
|
2
|
+
class Builder
|
3
|
+
def build
|
4
|
+
klass, options, block = @proxies.first
|
5
|
+
store = klass.new(@options.merge(options), &block)
|
6
|
+
@proxies[1..-1].each do |proxy|
|
7
|
+
klass, options, block = proxy
|
8
|
+
store = klass.new(store, @options.merge(options), &block)
|
9
|
+
end
|
10
|
+
store
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(options = {}, &block)
|
14
|
+
raise 'No block given' unless block_given?
|
15
|
+
raise 'Options must be Hash' unless Hash === options
|
16
|
+
@options = options
|
17
|
+
@proxies = []
|
18
|
+
instance_eval(&block)
|
19
|
+
end
|
20
|
+
|
21
|
+
def use(proxy, options = {}, &block)
|
22
|
+
proxy = Juno.const_get(proxy) if Symbol === proxy
|
23
|
+
@proxies.unshift [proxy, options, block]
|
24
|
+
end
|
25
|
+
|
26
|
+
def adapter(name, options = {}, &block)
|
27
|
+
use(Adapters.const_get(name), options, &block)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/juno/cache.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
module Juno
|
2
|
+
class Cache < Base
|
3
|
+
class DSL
|
4
|
+
def initialize(options, &block)
|
5
|
+
@cache, @backend = options[:cache], options[:backend]
|
6
|
+
instance_eval(&block)
|
7
|
+
end
|
8
|
+
|
9
|
+
def backend(options = {}, &block)
|
10
|
+
raise 'Backend already set' if @backend
|
11
|
+
@backend = Hash === options ? Juno.build(options, &block) : options
|
12
|
+
end
|
13
|
+
|
14
|
+
def cache(options = {}, &block)
|
15
|
+
raise 'Cache already set' if @cache
|
16
|
+
@cache = Hash === options ? Juno.build(options, &block) : options
|
17
|
+
end
|
18
|
+
|
19
|
+
def result
|
20
|
+
[@cache, @backend]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
attr_reader :cache, :backend
|
25
|
+
|
26
|
+
def initialize(options = {}, &block)
|
27
|
+
@cache, @backend = DSL.new(options, &block).result
|
28
|
+
end
|
29
|
+
|
30
|
+
def key?(key, options = {})
|
31
|
+
@cache.key?(key, options) || @backend.key?(key, options)
|
32
|
+
end
|
33
|
+
|
34
|
+
def load(key, options = {})
|
35
|
+
value = @cache.load(key, options)
|
36
|
+
unless value
|
37
|
+
value = @backend.load(key, options)
|
38
|
+
@cache.store(key, value, options) if value
|
39
|
+
end
|
40
|
+
value
|
41
|
+
end
|
42
|
+
|
43
|
+
def store(key, value, options = {})
|
44
|
+
@cache.store(key, value, options)
|
45
|
+
@backend.store(key, value, options)
|
46
|
+
end
|
47
|
+
|
48
|
+
def delete(key, options = {})
|
49
|
+
@cache.delete(key, options)
|
50
|
+
@backend.delete(key, options)
|
51
|
+
end
|
52
|
+
|
53
|
+
def clear(options = {})
|
54
|
+
@cache.clear(options)
|
55
|
+
@backend.clear(options)
|
56
|
+
self
|
57
|
+
end
|
58
|
+
|
59
|
+
def close
|
60
|
+
@cache.close
|
61
|
+
@backend.close
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
data/lib/juno/expires.rb
CHANGED
@@ -1,22 +1,18 @@
|
|
1
1
|
module Juno
|
2
2
|
class Expires < Proxy
|
3
3
|
def key?(key, options = {})
|
4
|
-
!!
|
4
|
+
!!load(key, options)
|
5
5
|
end
|
6
6
|
|
7
|
-
def
|
8
|
-
|
9
|
-
if
|
10
|
-
store(key,
|
7
|
+
def load(key, options = {})
|
8
|
+
value = check_expired(key, super(key, options))
|
9
|
+
if value && options.include?(:expires)
|
10
|
+
store(key, value, options)
|
11
11
|
else
|
12
|
-
|
12
|
+
value
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
-
def [](key)
|
17
|
-
check_expired(key, super(key))
|
18
|
-
end
|
19
|
-
|
20
16
|
def store(key, value, options = {})
|
21
17
|
if expires = options.delete(:expires)
|
22
18
|
super(key, [value, Time.now.to_i + expires].compact, options)
|
data/lib/juno/proxy.rb
CHANGED
@@ -1,5 +1,64 @@
|
|
1
|
-
require 'delegate'
|
2
|
-
|
3
1
|
module Juno
|
4
|
-
Proxy
|
2
|
+
class Proxy < Base
|
3
|
+
attr_reader :adapter
|
4
|
+
|
5
|
+
def initialize(adapter, options = {})
|
6
|
+
@adapter = adapter
|
7
|
+
end
|
8
|
+
|
9
|
+
# Exists the value with key
|
10
|
+
#
|
11
|
+
# @param [Object] key
|
12
|
+
# @return [Boolean]
|
13
|
+
# @param [Hash] options
|
14
|
+
# @api public
|
15
|
+
def key?(key, options = {})
|
16
|
+
@adapter.key?(key, options)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Fetch value with key. Return nil if the key doesn't exist
|
20
|
+
#
|
21
|
+
# @param [Object] key
|
22
|
+
# @param [Hash] options
|
23
|
+
# @return [Object] value
|
24
|
+
# @api public
|
25
|
+
def load(key, options = {})
|
26
|
+
@adapter.load(key, options)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Store value with key
|
30
|
+
#
|
31
|
+
# @param [Object] key
|
32
|
+
# @param [Object] value
|
33
|
+
# @param [Hash] options
|
34
|
+
# @return value
|
35
|
+
# @api public
|
36
|
+
def store(key, value, options = {})
|
37
|
+
@adapter.store(key, value, options)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Delete the key from the store and return the current value
|
41
|
+
#
|
42
|
+
# @param [Object] key
|
43
|
+
# @return [Object] current value
|
44
|
+
# @param [Hash] options
|
45
|
+
# @api public
|
46
|
+
def delete(key, options = {})
|
47
|
+
@adapter.delete(key, options)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Clear all keys in this store
|
51
|
+
#
|
52
|
+
# @param [Hash] options
|
53
|
+
# @return [void]
|
54
|
+
# @api public
|
55
|
+
def clear(options = {})
|
56
|
+
@adapter.clear(options)
|
57
|
+
self
|
58
|
+
end
|
59
|
+
|
60
|
+
def close
|
61
|
+
@adapter.close
|
62
|
+
end
|
63
|
+
end
|
5
64
|
end
|
data/lib/juno/stack.rb
CHANGED
@@ -1,40 +1,56 @@
|
|
1
1
|
module Juno
|
2
2
|
class Stack < Base
|
3
|
-
|
4
|
-
|
3
|
+
class DSL
|
4
|
+
attr_reader :stack
|
5
|
+
|
6
|
+
def initialize(options, &block)
|
7
|
+
@stack = options[:stack].to_a
|
8
|
+
instance_eval(&block)
|
9
|
+
end
|
10
|
+
|
11
|
+
def add(options = {}, &block)
|
12
|
+
@stack << (Hash === options ? Juno.build(options, &block) : options)
|
13
|
+
nil
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
attr_reader :stack
|
18
|
+
|
19
|
+
def initialize(options = {}, &block)
|
20
|
+
@stack = DSL.new(options, &block).stack
|
5
21
|
end
|
6
22
|
|
7
23
|
def key?(key, options = {})
|
8
|
-
@
|
24
|
+
@stack.any? {|s| s.key?(key) }
|
9
25
|
end
|
10
26
|
|
11
|
-
def
|
12
|
-
@
|
13
|
-
value = s
|
27
|
+
def load(key, options = {})
|
28
|
+
@stack.each do |s|
|
29
|
+
value = s.load(key, options)
|
14
30
|
return value if value
|
15
31
|
end
|
16
32
|
nil
|
17
33
|
end
|
18
34
|
|
19
35
|
def store(key, value, options = {})
|
20
|
-
@
|
36
|
+
@stack.each {|s| s.store(key, value, options) }
|
21
37
|
value
|
22
38
|
end
|
23
39
|
|
24
40
|
def delete(key, options = {})
|
25
|
-
@
|
41
|
+
@stack.inject(nil) do |value, s|
|
26
42
|
v = s.delete(key, options)
|
27
43
|
value || v
|
28
44
|
end
|
29
45
|
end
|
30
46
|
|
31
47
|
def clear(options = {})
|
32
|
-
@
|
33
|
-
|
48
|
+
@stack.each {|s| s.clear }
|
49
|
+
self
|
34
50
|
end
|
35
51
|
|
36
52
|
def close
|
37
|
-
@
|
53
|
+
@stack.each {|s| s.close }
|
38
54
|
nil
|
39
55
|
end
|
40
56
|
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
module Juno
|
2
|
+
class Transformer < Proxy
|
3
|
+
@classes = {}
|
4
|
+
|
5
|
+
class << self
|
6
|
+
alias_method :original_new, :new
|
7
|
+
end
|
8
|
+
|
9
|
+
VALUE_TRANSFORMER = {
|
10
|
+
:marshal => { :load => '::Marshal.load(VALUE)', :dump => '::Marshal.dump(VALUE)' },
|
11
|
+
:base64 => { :load => "VALUE.unpack('m').first", :dump => "[VALUE].pack('m').strip" },
|
12
|
+
:json => { :load => '::MultiJson.load(VALUE).first', :dump => '::MultiJson.dump([VALUE])', :require => 'multi_json' },
|
13
|
+
:yaml => { :load => '::YAML.load(VALUE)', :dump => '::YAML.dump(VALUE)', :require => 'yaml' },
|
14
|
+
#:tnet => { :load => '::TNetstring.parse(VALUE)', :dump => '::TNetstring.dump(VALUE)', :require => 'tnetstring' },
|
15
|
+
:msgpack => { :load => '::MessagePack.unpack(VALUE)', :dump => '::MessagePack.pack(VALUE)', :require => 'msgpack' },
|
16
|
+
:bson => { :load => '::BSON.deserialize(VALUE)["v"]', :dump => '::BSON.serialize({"v"=>VALUE})', :require => 'bson' },
|
17
|
+
}
|
18
|
+
|
19
|
+
KEY_TRANSFORMER = {
|
20
|
+
:base64 => { :transform => "[KEY].pack('m').strip" },
|
21
|
+
:spread => { :transform => '(TMP = KEY; ::File.join(TMP[0..1], TMP[2..-1]))' },
|
22
|
+
:escape => { :transform => "KEY.gsub(/[^a-zA-Z0-9_-]+/) { '%%' + $&.unpack('H2' * $&.bytesize).join('%%').upcase }" },
|
23
|
+
:md5 => { :transform => '::Digest::MD5.hexdigest(KEY)', :require => 'digest/md5' },
|
24
|
+
:json => { :transform => '(TMP = KEY; String === TMP ? TMP : ::MultiJson.dump(TMP))', :require => 'multi_json' },
|
25
|
+
:bson => { :transform => '(TMP = KEY; String === TMP ? TMP : ::BSON.serialize({"k"=>TMP}).to_s)', :require => 'bson' },
|
26
|
+
:yaml => { :transform => '(TMP = KEY; String === TMP ? TMP : ::YAML.dump(TMP))', :require => 'yaml' },
|
27
|
+
:marshal => { :transform => '(TMP = KEY; String === TMP ? TMP : ::Marshal.dump(TMP))' },
|
28
|
+
#:tnet => { :transform => '(TMP = KEY; String === TMP ? TMP : ::TNetstring.dump(TMP))', :require => 'tnetstring' },
|
29
|
+
:msgpack => { :transform => '(TMP = KEY; String === TMP ? TMP : ::MessagePack.pack(TMP))', :require => 'msgpack' },
|
30
|
+
}
|
31
|
+
|
32
|
+
class << self
|
33
|
+
def compile(keys, values)
|
34
|
+
tmp, key = 0, 'key'
|
35
|
+
keys.each do |tn|
|
36
|
+
raise "Unknown key transformer #{tn}" unless t = KEY_TRANSFORMER[tn]
|
37
|
+
require t[:require] if t[:require]
|
38
|
+
key = t[:transform].gsub('KEY', key).gsub('TMP', "x#{tmp}")
|
39
|
+
tmp += 1
|
40
|
+
end
|
41
|
+
|
42
|
+
dumper = 'value'
|
43
|
+
values.each do |tn|
|
44
|
+
raise "Unknown value transformer #{tn}" unless t = VALUE_TRANSFORMER[tn]
|
45
|
+
require t[:require] if t[:require]
|
46
|
+
dumper = t[:dump].gsub('VALUE', dumper)
|
47
|
+
end
|
48
|
+
|
49
|
+
loader = 'value'
|
50
|
+
values.reverse.each do |t|
|
51
|
+
loader = VALUE_TRANSFORMER[t][:load].gsub('VALUE', loader)
|
52
|
+
end
|
53
|
+
|
54
|
+
klass = Class.new(Transformer)
|
55
|
+
if loader == 'value'
|
56
|
+
klass.class_eval <<-end_eval, __FILE__, __LINE__
|
57
|
+
def key?(key, options = {})
|
58
|
+
@adapter.key?(#{key}, options)
|
59
|
+
end
|
60
|
+
|
61
|
+
def load(key, options = {})
|
62
|
+
@adapter.load(#{key}, options)
|
63
|
+
end
|
64
|
+
|
65
|
+
def store(key, value, options = {})
|
66
|
+
@adapter.store(#{key}, value, options)
|
67
|
+
end
|
68
|
+
|
69
|
+
def delete(key, options = {})
|
70
|
+
@adapter.delete(#{key}, options)
|
71
|
+
end
|
72
|
+
end_eval
|
73
|
+
else
|
74
|
+
klass.class_eval <<-end_eval, __FILE__, __LINE__
|
75
|
+
def key?(key, options = {})
|
76
|
+
@adapter.key?(#{key}, options)
|
77
|
+
end
|
78
|
+
|
79
|
+
def load(key, options = {})
|
80
|
+
value = @adapter.load(#{key}, options)
|
81
|
+
value && #{loader}
|
82
|
+
end
|
83
|
+
|
84
|
+
def store(key, value, options = {})
|
85
|
+
@adapter.store(#{key}, #{dumper}, options)
|
86
|
+
value
|
87
|
+
end
|
88
|
+
|
89
|
+
def delete(key, options = {})
|
90
|
+
value = @adapter.delete(#{key}, options)
|
91
|
+
value && #{loader}
|
92
|
+
end
|
93
|
+
end_eval
|
94
|
+
end
|
95
|
+
klass
|
96
|
+
end
|
97
|
+
|
98
|
+
def new(store, options = {})
|
99
|
+
keys = [options[:key]].flatten.compact
|
100
|
+
values = [options[:value]].flatten.compact
|
101
|
+
klass = @classes["#{keys.join('-')}+#{values.join('-')}"] ||= compile(keys, values)
|
102
|
+
klass.original_new(store, options)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
data/lib/juno/version.rb
CHANGED
data/lib/juno.rb
CHANGED
@@ -1,31 +1,83 @@
|
|
1
1
|
module Juno
|
2
|
-
autoload :
|
3
|
-
autoload :
|
4
|
-
autoload :
|
5
|
-
autoload :
|
6
|
-
autoload :
|
7
|
-
autoload :
|
8
|
-
autoload :
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
2
|
+
autoload :Base, 'juno/base'
|
3
|
+
autoload :Builder, 'juno/builder'
|
4
|
+
autoload :Cache, 'juno/cache'
|
5
|
+
autoload :Expires, 'juno/expires'
|
6
|
+
autoload :Proxy, 'juno/proxy'
|
7
|
+
autoload :Stack, 'juno/stack'
|
8
|
+
autoload :Transformer, 'juno/transformer'
|
9
|
+
|
10
|
+
module Adapters
|
11
|
+
autoload :ActiveRecord, 'juno/adapters/activerecord'
|
12
|
+
autoload :Cassandra, 'juno/adapters/cassandra'
|
13
|
+
autoload :Couch, 'juno/adapters/couch'
|
14
|
+
autoload :DataMapper, 'juno/adapters/datamapper'
|
15
|
+
autoload :DBM, 'juno/adapters/dbm'
|
16
|
+
autoload :File, 'juno/adapters/file'
|
17
|
+
autoload :Fog, 'juno/adapters/fog'
|
18
|
+
autoload :GDBM, 'juno/adapters/gdbm'
|
19
|
+
autoload :LocalMemCache, 'juno/adapters/localmemcache'
|
20
|
+
autoload :Memcached, 'juno/adapters/memcached'
|
21
|
+
autoload :MemcachedDalli, 'juno/adapters/memcached_dalli'
|
22
|
+
autoload :MemcachedNative, 'juno/adapters/memcached_native'
|
23
|
+
autoload :Memory, 'juno/adapters/memory'
|
24
|
+
autoload :Mongo, 'juno/adapters/mongo'
|
25
|
+
autoload :Null, 'juno/adapters/null'
|
26
|
+
autoload :PStore, 'juno/adapters/pstore'
|
27
|
+
autoload :Redis, 'juno/adapters/redis'
|
28
|
+
autoload :Riak, 'juno/adapters/riak'
|
29
|
+
autoload :SDBM, 'juno/adapters/sdbm'
|
30
|
+
autoload :Sequel, 'juno/adapters/sequel'
|
31
|
+
autoload :Sqlite, 'juno/adapters/sqlite'
|
32
|
+
autoload :TokyoCabinet, 'juno/adapters/tokyocabinet'
|
33
|
+
autoload :YAML, 'juno/adapters/yaml'
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.new(name, options = {})
|
37
|
+
raise 'Name must be Symbol' unless Symbol === name
|
38
|
+
case name
|
39
|
+
when :Sequel, :ActiveRecord, :Couch
|
40
|
+
# Sequel accept only base64 keys and values
|
41
|
+
# FIXME: ActiveRecord and Couch should work only with :marshal but this
|
42
|
+
# raises an error on 1.9
|
43
|
+
build(options) do
|
44
|
+
use :Transformer, :key => [:marshal, :base64], :value => [:marshal, :base64]
|
45
|
+
adapter name
|
46
|
+
end
|
47
|
+
when :Memcached, :MemcachedDalli, :MemcachedNative
|
48
|
+
# Memcached accept only base64 keys
|
49
|
+
build(options) do
|
50
|
+
use :Transformer, :key => [:marshal, :base64], :value => :marshal
|
51
|
+
adapter name
|
52
|
+
end
|
53
|
+
when :PStore, :YAML, :DataMapper, :Null
|
54
|
+
# For PStore, YAML and DataMapper only the key has to be a string
|
55
|
+
build(options) do
|
56
|
+
use :Transformer, :key => :marshal
|
57
|
+
adapter name
|
58
|
+
end
|
59
|
+
when :HashFile
|
60
|
+
# Use spreading hashes
|
61
|
+
build(options) do
|
62
|
+
use :Transformer, :key => [:marshal, :md5, :spread], :value => :marshal
|
63
|
+
adapter :File
|
64
|
+
end
|
65
|
+
when :File
|
66
|
+
# Use escaping
|
67
|
+
build(options) do
|
68
|
+
use :Transformer, :key => [:marshal, :escape], :value => :marshal
|
69
|
+
adapter :File
|
70
|
+
end
|
71
|
+
else
|
72
|
+
# For all other stores marshal key and value
|
73
|
+
build(options) do
|
74
|
+
use :Transformer, :key => :marshal, :value => :marshal
|
75
|
+
adapter name
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.build(options = {}, &block)
|
81
|
+
Builder.new(options, &block).build
|
82
|
+
end
|
31
83
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# Generated file
|
2
|
+
require 'helper'
|
3
|
+
|
4
|
+
begin
|
5
|
+
Juno::Adapters::ActiveRecord.new(:connection => { :adapter => (defined?(JRUBY_VERSION) ? 'jdbcsqlite3' : 'sqlite3'), :database => File.join(make_tempdir, 'adapter_activerecord.sqlite3') }).close
|
6
|
+
|
7
|
+
describe "adapter_activerecord" do
|
8
|
+
before do
|
9
|
+
@store = Juno::Adapters::ActiveRecord.new(:connection => { :adapter => (defined?(JRUBY_VERSION) ? 'jdbcsqlite3' : 'sqlite3'), :database => File.join(make_tempdir, 'adapter_activerecord.sqlite3') })
|
10
|
+
@store.clear
|
11
|
+
end
|
12
|
+
|
13
|
+
after do
|
14
|
+
@store.close.should == nil if @store
|
15
|
+
end
|
16
|
+
|
17
|
+
it_should_behave_like 'null_stringkey_stringvalue'
|
18
|
+
it_should_behave_like 'store_stringkey_stringvalue'
|
19
|
+
it_should_behave_like 'returndifferent_stringkey_stringvalue'
|
20
|
+
|
21
|
+
it 'updates an existing key/value' do
|
22
|
+
@store['foo/bar'] = '1'
|
23
|
+
@store['foo/bar'] = '2'
|
24
|
+
records = @store.table.find :all, :conditions => { :key => 'foo/bar' }
|
25
|
+
records.count.should == 1
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'uses an existing connection' do
|
29
|
+
ActiveRecord::Base.establish_connection :adapter => (defined?(JRUBY_VERSION) ? 'jdbcsqlite3' : 'sqlite3'), :database => File.join(make_tempdir, 'activerecord-existing.sqlite3')
|
30
|
+
|
31
|
+
store = Juno::Adapters::ActiveRecord.new
|
32
|
+
store.table.table_exists?.should == true
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
rescue LoadError => ex
|
37
|
+
puts "Test adapter_activerecord not executed: #{ex.message}"
|
38
|
+
rescue Exception => ex
|
39
|
+
puts "Test adapter_activerecord not executed: #{ex.message}"
|
40
|
+
#puts "#{ex.backtrace.join("\n")}"
|
41
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# Generated file
|
2
|
+
require 'helper'
|
3
|
+
|
4
|
+
begin
|
5
|
+
Juno::Adapters::Cassandra.new.close
|
6
|
+
|
7
|
+
describe "adapter_cassandra" do
|
8
|
+
before do
|
9
|
+
@store = Juno::Adapters::Cassandra.new
|
10
|
+
@store.clear
|
11
|
+
end
|
12
|
+
|
13
|
+
after do
|
14
|
+
@store.close.should == nil if @store
|
15
|
+
end
|
16
|
+
|
17
|
+
it_should_behave_like 'null_stringkey_stringvalue'
|
18
|
+
it_should_behave_like 'store_stringkey_stringvalue'
|
19
|
+
it_should_behave_like 'returndifferent_stringkey_stringvalue'
|
20
|
+
|
21
|
+
end
|
22
|
+
rescue LoadError => ex
|
23
|
+
puts "Test adapter_cassandra not executed: #{ex.message}"
|
24
|
+
rescue Exception => ex
|
25
|
+
puts "Test adapter_cassandra not executed: #{ex.message}"
|
26
|
+
#puts "#{ex.backtrace.join("\n")}"
|
27
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# Generated file
|
2
|
+
require 'helper'
|
3
|
+
|
4
|
+
begin
|
5
|
+
Juno::Adapters::Couch.new(:db => 'adapter_couch').close
|
6
|
+
|
7
|
+
describe "adapter_couch" do
|
8
|
+
before do
|
9
|
+
@store = Juno::Adapters::Couch.new(:db => 'adapter_couch')
|
10
|
+
@store.clear
|
11
|
+
end
|
12
|
+
|
13
|
+
after do
|
14
|
+
@store.close.should == nil if @store
|
15
|
+
end
|
16
|
+
|
17
|
+
it_should_behave_like 'null_stringkey_stringvalue'
|
18
|
+
it_should_behave_like 'store_stringkey_stringvalue'
|
19
|
+
it_should_behave_like 'returndifferent_stringkey_stringvalue'
|
20
|
+
|
21
|
+
end
|
22
|
+
rescue LoadError => ex
|
23
|
+
puts "Test adapter_couch not executed: #{ex.message}"
|
24
|
+
rescue Exception => ex
|
25
|
+
puts "Test adapter_couch not executed: #{ex.message}"
|
26
|
+
#puts "#{ex.backtrace.join("\n")}"
|
27
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# Generated file
|
2
|
+
require 'helper'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'dm-core'
|
6
|
+
DataMapper.setup(:default, :adapter => :in_memory)
|
7
|
+
Juno::Adapters::DataMapper.new(:setup => "sqlite3://#{make_tempdir}/adapter_datamapper.sqlite3").close
|
8
|
+
|
9
|
+
describe "adapter_datamapper" do
|
10
|
+
before do
|
11
|
+
@store = Juno::Adapters::DataMapper.new(:setup => "sqlite3://#{make_tempdir}/adapter_datamapper.sqlite3")
|
12
|
+
@store.clear
|
13
|
+
end
|
14
|
+
|
15
|
+
after do
|
16
|
+
@store.close.should == nil if @store
|
17
|
+
end
|
18
|
+
|
19
|
+
it_should_behave_like 'null_stringkey_stringvalue'
|
20
|
+
it_should_behave_like 'store_stringkey_stringvalue'
|
21
|
+
it_should_behave_like 'returndifferent_stringkey_stringvalue'
|
22
|
+
it_should_behave_like 'returndifferent_stringkey_objectvalue'
|
23
|
+
it_should_behave_like 'null_stringkey_objectvalue'
|
24
|
+
it_should_behave_like 'store_stringkey_objectvalue'
|
25
|
+
|
26
|
+
it 'does not cross contaminate when storing' do
|
27
|
+
first = Juno::Adapters::DataMapper.new(:setup => "sqlite3://#{make_tempdir}/datamapper-first.sqlite3")
|
28
|
+
first.clear
|
29
|
+
|
30
|
+
second = Juno::Adapters::DataMapper.new(:repository => :sample, :setup => "sqlite3://#{make_tempdir}/datamapper-second.sqlite3")
|
31
|
+
second.clear
|
32
|
+
|
33
|
+
first['key'] = 'value'
|
34
|
+
second['key'] = 'value2'
|
35
|
+
|
36
|
+
first['key'].should == 'value'
|
37
|
+
second['key'].should == 'value2'
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'does not cross contaminate when deleting' do
|
41
|
+
first = Juno::Adapters::DataMapper.new(:setup => "sqlite3://#{make_tempdir}/datamapper-first.sqlite3")
|
42
|
+
first.clear
|
43
|
+
|
44
|
+
second = Juno::Adapters::DataMapper.new(:repository => :sample, :setup => "sqlite3://#{make_tempdir}/datamapper-second.sqlite3")
|
45
|
+
second.clear
|
46
|
+
|
47
|
+
first['key'] = 'value'
|
48
|
+
second['key'] = 'value2'
|
49
|
+
|
50
|
+
first.delete('key').should == 'value'
|
51
|
+
first.key?('key').should == false
|
52
|
+
second['key'].should == 'value2'
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
rescue LoadError => ex
|
57
|
+
puts "Test adapter_datamapper not executed: #{ex.message}"
|
58
|
+
rescue Exception => ex
|
59
|
+
puts "Test adapter_datamapper not executed: #{ex.message}"
|
60
|
+
#puts "#{ex.backtrace.join("\n")}"
|
61
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# Generated file
|
2
|
+
require 'helper'
|
3
|
+
|
4
|
+
begin
|
5
|
+
Juno::Adapters::DBM.new(:file => File.join(make_tempdir, "adapter_dbm")).close
|
6
|
+
|
7
|
+
describe "adapter_dbm" do
|
8
|
+
before do
|
9
|
+
@store = Juno::Adapters::DBM.new(:file => File.join(make_tempdir, "adapter_dbm"))
|
10
|
+
@store.clear
|
11
|
+
end
|
12
|
+
|
13
|
+
after do
|
14
|
+
@store.close.should == nil if @store
|
15
|
+
end
|
16
|
+
|
17
|
+
it_should_behave_like 'null_stringkey_stringvalue'
|
18
|
+
it_should_behave_like 'store_stringkey_stringvalue'
|
19
|
+
it_should_behave_like 'returndifferent_stringkey_stringvalue'
|
20
|
+
|
21
|
+
end
|
22
|
+
rescue LoadError => ex
|
23
|
+
puts "Test adapter_dbm not executed: #{ex.message}"
|
24
|
+
rescue Exception => ex
|
25
|
+
puts "Test adapter_dbm not executed: #{ex.message}"
|
26
|
+
#puts "#{ex.backtrace.join("\n")}"
|
27
|
+
end
|