juno 0.2.4 → 0.2.5
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +7 -2
- data/README.md +4 -2
- data/lib/juno/adapters/memcached_native.rb +3 -1
- data/lib/juno/builder.rb +4 -5
- data/lib/juno/cache.rb +6 -4
- data/lib/juno/expires.rb +4 -0
- data/lib/juno/lock.rb +8 -1
- data/lib/juno/logger.rb +86 -0
- data/lib/juno/proxy.rb +4 -0
- data/lib/juno/stack.rb +3 -2
- data/lib/juno/transformer.rb +61 -61
- data/lib/juno/version.rb +1 -1
- data/lib/juno.rb +10 -8
- data/spec/adapter_activerecord_spec.rb +2 -2
- data/spec/adapter_cassandra_spec.rb +1 -1
- data/spec/adapter_couch_spec.rb +1 -1
- data/spec/adapter_datamapper_spec.rb +1 -1
- data/spec/adapter_dbm_spec.rb +1 -1
- data/spec/adapter_file_spec.rb +1 -1
- data/spec/adapter_fog_spec.rb +1 -1
- data/spec/adapter_gdbm_spec.rb +1 -1
- data/spec/adapter_localmemcache_spec.rb +1 -1
- data/spec/adapter_lruhash_spec.rb +1 -1
- data/spec/adapter_memcached_dalli_spec.rb +1 -1
- data/spec/adapter_memcached_native_spec.rb +1 -1
- data/spec/adapter_memcached_spec.rb +1 -1
- data/spec/adapter_memory_spec.rb +1 -1
- data/spec/adapter_mongo_spec.rb +1 -1
- data/spec/adapter_pstore_spec.rb +1 -1
- data/spec/adapter_redis_spec.rb +1 -1
- data/spec/adapter_riak_spec.rb +1 -1
- data/spec/adapter_sdbm_spec.rb +1 -1
- data/spec/adapter_sequel_spec.rb +1 -1
- data/spec/adapter_sqlite_spec.rb +1 -1
- data/spec/adapter_tokyocabinet_bdb_spec.rb +1 -1
- data/spec/adapter_tokyocabinet_hdb_spec.rb +1 -1
- data/spec/adapter_yaml_spec.rb +1 -1
- data/spec/cache_file_memory_spec.rb +1 -1
- data/spec/cache_memory_null_spec.rb +1 -1
- data/spec/expires_file_spec.rb +1 -1
- data/spec/expires_memory_spec.rb +1 -1
- data/spec/generate.rb +37 -12
- data/spec/junospecs.rb +1 -1
- data/spec/lock_spec.rb +1 -1
- data/spec/null_adapter_spec.rb +1 -1
- data/spec/proxy_expires_memory_spec.rb +1 -1
- data/spec/proxy_redis_spec.rb +1 -1
- data/spec/simple_activerecord_spec.rb +2 -2
- data/spec/simple_activerecord_with_expires_spec.rb +2 -2
- data/spec/simple_cassandra_spec.rb +2 -2
- data/spec/simple_couch_spec.rb +2 -2
- data/spec/simple_couch_with_expires_spec.rb +2 -2
- data/spec/simple_datamapper_spec.rb +2 -2
- data/spec/simple_datamapper_with_expires_spec.rb +2 -2
- data/spec/simple_datamapper_with_repository_spec.rb +2 -2
- data/spec/simple_dbm_spec.rb +2 -2
- data/spec/simple_dbm_with_expires_spec.rb +2 -2
- data/spec/simple_file_spec.rb +2 -2
- data/spec/simple_file_with_expires_spec.rb +2 -2
- data/spec/simple_fog_spec.rb +2 -2
- data/spec/simple_fog_with_expires_spec.rb +2 -2
- data/spec/simple_gdbm_spec.rb +2 -2
- data/spec/simple_gdbm_with_expires_spec.rb +2 -2
- data/spec/simple_hashfile_spec.rb +2 -2
- data/spec/simple_hashfile_with_expires_spec.rb +2 -2
- data/spec/simple_localmemcache_spec.rb +2 -2
- data/spec/simple_localmemcache_with_expires_spec.rb +2 -2
- data/spec/simple_lruhash_spec.rb +2 -2
- data/spec/simple_lruhash_with_expires_spec.rb +2 -2
- data/spec/simple_memcached_dalli_spec.rb +2 -2
- data/spec/simple_memcached_native_spec.rb +2 -2
- data/spec/simple_memcached_spec.rb +2 -2
- data/spec/simple_memory_spec.rb +2 -2
- data/spec/simple_memory_with_expires_spec.rb +2 -2
- data/spec/simple_mongo_spec.rb +2 -2
- data/spec/simple_mongo_with_expires_spec.rb +2 -2
- data/spec/simple_null_spec.rb +2 -2
- data/spec/simple_pstore_spec.rb +2 -2
- data/spec/simple_pstore_with_expires_spec.rb +2 -2
- data/spec/simple_redis_spec.rb +2 -2
- data/spec/simple_riak_spec.rb +2 -2
- data/spec/simple_riak_with_expires_spec.rb +2 -2
- data/spec/simple_sdbm_spec.rb +2 -2
- data/spec/simple_sdbm_with_expires_spec.rb +2 -2
- data/spec/simple_sequel_spec.rb +2 -2
- data/spec/simple_sequel_with_expires_spec.rb +2 -2
- data/spec/simple_sqlite_spec.rb +2 -2
- data/spec/simple_sqlite_with_expires_spec.rb +2 -2
- data/spec/simple_tokyocabinet_spec.rb +2 -2
- data/spec/simple_tokyocabinet_with_expires_spec.rb +2 -2
- data/spec/simple_yaml_spec.rb +2 -2
- data/spec/simple_yaml_with_expires_spec.rb +2 -2
- data/spec/stack_file_memory_spec.rb +1 -1
- data/spec/stack_memory_file_spec.rb +1 -1
- data/spec/transformer_bencode_spec.rb +25 -0
- data/spec/transformer_bert_spec.rb +25 -0
- data/spec/transformer_bson_spec.rb +1 -1
- data/spec/transformer_compress_spec.rb +1 -1
- data/spec/transformer_json_spec.rb +1 -1
- data/spec/transformer_marshal_base64_spec.rb +1 -1
- data/spec/transformer_marshal_escape_spec.rb +1 -1
- data/spec/transformer_marshal_md5_spec.rb +1 -1
- data/spec/transformer_marshal_md5_spread_spec.rb +1 -1
- data/spec/transformer_marshal_uuencode_spec.rb +41 -0
- data/spec/transformer_msgpack_spec.rb +1 -1
- data/spec/transformer_ox_spec.rb +1 -1
- data/spec/transformer_tnet_spec.rb +25 -0
- data/spec/transformer_yaml_spec.rb +1 -1
- metadata +11 -2
data/Gemfile
CHANGED
@@ -7,10 +7,11 @@ gem 'rspec'
|
|
7
7
|
gem 'parallel_tests'
|
8
8
|
|
9
9
|
# Serializer
|
10
|
-
|
10
|
+
gem 'tnetstring'
|
11
|
+
gem 'bert'
|
12
|
+
gem 'bencode'
|
11
13
|
gem 'bson'
|
12
14
|
gem 'multi_json'
|
13
|
-
gem 'json' # Ripple/Riak needs json
|
14
15
|
|
15
16
|
# Backends
|
16
17
|
gem 'dm-core'
|
@@ -27,9 +28,13 @@ gem 'riak-client'
|
|
27
28
|
gem 'hashery'
|
28
29
|
|
29
30
|
if defined?(JRUBY_VERSION)
|
31
|
+
gem 'msgpack-jruby'
|
30
32
|
gem 'jdbc-sqlite3'
|
31
33
|
gem 'activerecord-jdbc-adapter'
|
32
34
|
gem 'activerecord-jdbcsqlite3-adapter'
|
35
|
+
gem 'jruby-memcached'
|
36
|
+
gem 'ffi' # gdbm for jruby needs ffi
|
37
|
+
gem 'gdbm'
|
33
38
|
else
|
34
39
|
gem 'msgpack'
|
35
40
|
gem 'tokyocabinet'
|
data/README.md
CHANGED
@@ -10,7 +10,7 @@ fork was that Moneta was unmaintained for a long time.
|
|
10
10
|
Juno is very feature rich:
|
11
11
|
|
12
12
|
* Supports for a lot of backends (See below)
|
13
|
-
* Supports proxies (Similar to [Rack middlewares](http://rack.
|
13
|
+
* Supports proxies (Similar to [Rack middlewares](http://rack.github.com/))
|
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
|
* Expiration for all stores (Added via proxy if not supported natively)
|
@@ -58,11 +58,12 @@ Supported serializers:
|
|
58
58
|
* MessagePack
|
59
59
|
* BSON
|
60
60
|
* Ox
|
61
|
+
* BERT
|
61
62
|
|
62
63
|
Proxies
|
63
64
|
-------
|
64
65
|
|
65
|
-
In addition it supports proxies (Similar to [Rack middlewares](http://rack.
|
66
|
+
In addition it supports proxies (Similar to [Rack middlewares](http://rack.github.com/)) which
|
66
67
|
add additional features to storage backends:
|
67
68
|
|
68
69
|
* `Juno::Proxy` proxy base class
|
@@ -71,6 +72,7 @@ add additional features to storage backends:
|
|
71
72
|
* `Juno::Transformer` transforms keys and values (Marshal, YAML, JSON, Base64, MD5, ...)
|
72
73
|
* `Juno::Cache` combine two stores, one as backend and one as cache (e.g. Juno::Adapters::File + Juno::Adapters::Memory)
|
73
74
|
* `Juno::Lock` to make store thread safe
|
75
|
+
* `Juno::Logger` to log database accesses
|
74
76
|
|
75
77
|
The Juno API is purposely extremely similar to the Hash API. In order so support an
|
76
78
|
identical API across stores, it does not support iteration or partial matches.
|
@@ -16,6 +16,7 @@ module Juno
|
|
16
16
|
def initialize(options = {})
|
17
17
|
server = options.delete(:server) || 'localhost:11211'
|
18
18
|
options.merge!(:prefix_key => options.delete(:namespace)) if options[:namespace]
|
19
|
+
@default_ttl = options[:default_ttl] || 604800
|
19
20
|
@cache = ::Memcached.new(server, options)
|
20
21
|
end
|
21
22
|
|
@@ -44,7 +45,8 @@ module Juno
|
|
44
45
|
end
|
45
46
|
|
46
47
|
def store(key, value, options = {})
|
47
|
-
|
48
|
+
# TTL must be Fixnum
|
49
|
+
@cache.set(key, value, options[:expires] || @default_ttl, false)
|
48
50
|
value
|
49
51
|
end
|
50
52
|
|
data/lib/juno/builder.rb
CHANGED
@@ -4,24 +4,23 @@ module Juno
|
|
4
4
|
class Builder
|
5
5
|
def build
|
6
6
|
klass, options, block = @proxies.first
|
7
|
-
store = klass.new(
|
7
|
+
store = klass.new(options, &block)
|
8
8
|
@proxies[1..-1].each do |proxy|
|
9
9
|
klass, options, block = proxy
|
10
|
-
store = klass.new(store,
|
10
|
+
store = klass.new(store, options, &block)
|
11
11
|
end
|
12
12
|
store
|
13
13
|
end
|
14
14
|
|
15
|
-
def initialize(
|
15
|
+
def initialize(&block)
|
16
16
|
raise 'No block given' unless block_given?
|
17
|
-
raise 'Options must be Hash' unless Hash === options
|
18
|
-
@options = options
|
19
17
|
@proxies = []
|
20
18
|
instance_eval(&block)
|
21
19
|
end
|
22
20
|
|
23
21
|
def use(proxy, options = {}, &block)
|
24
22
|
proxy = Juno.const_get(proxy) if Symbol === proxy
|
23
|
+
raise 'You must give a Class or a Symbol' unless Class === proxy
|
25
24
|
@proxies.unshift [proxy, options, block]
|
26
25
|
end
|
27
26
|
|
data/lib/juno/cache.rb
CHANGED
@@ -18,14 +18,16 @@ module Juno
|
|
18
18
|
instance_eval(&block)
|
19
19
|
end
|
20
20
|
|
21
|
-
def backend(
|
21
|
+
def backend(store = nil, &block)
|
22
22
|
raise 'Backend already set' if @backend
|
23
|
-
|
23
|
+
raise 'Only argument or block allowed' if store && block
|
24
|
+
@backend = store || Juno.build(&block)
|
24
25
|
end
|
25
26
|
|
26
|
-
def cache(
|
27
|
+
def cache(store = nil, &block)
|
27
28
|
raise 'Cache already set' if @cache
|
28
|
-
|
29
|
+
raise 'Only argument or block allowed' if store && block
|
30
|
+
@cache = store || Juno.build(&block)
|
29
31
|
end
|
30
32
|
|
31
33
|
def result
|
data/lib/juno/expires.rb
CHANGED
data/lib/juno/lock.rb
CHANGED
@@ -4,9 +4,16 @@ module Juno
|
|
4
4
|
# Locks the underlying stores with a Mutex
|
5
5
|
# @api public
|
6
6
|
class Lock < Proxy
|
7
|
+
# Constructor
|
8
|
+
#
|
9
|
+
# @param [Juno store] adapter The underlying store
|
10
|
+
# @param [Hash] options
|
11
|
+
#
|
12
|
+
# Options:
|
13
|
+
# * :mutex - Mutex object (default Mutex.new)
|
7
14
|
def initialize(adapter, options = {})
|
8
15
|
super
|
9
|
-
@lock = Mutex.new
|
16
|
+
@lock = options[:mutex] || Mutex.new
|
10
17
|
end
|
11
18
|
|
12
19
|
def key?(key, options = {})
|
data/lib/juno/logger.rb
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
module Juno
|
2
|
+
# Logger proxy
|
3
|
+
# @api public
|
4
|
+
class Logger < Proxy
|
5
|
+
# Standard formatter used by the logger
|
6
|
+
# @api public
|
7
|
+
class Format
|
8
|
+
def initialize(options)
|
9
|
+
@prefix = options[:prefix] || 'Juno '
|
10
|
+
@out = options[:out] || STDOUT
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(entry)
|
14
|
+
@out.write(format(entry))
|
15
|
+
end
|
16
|
+
|
17
|
+
protected
|
18
|
+
|
19
|
+
def format(entry)
|
20
|
+
args = entry[:args]
|
21
|
+
args.pop if Hash === args.last && args.last.empty?
|
22
|
+
args = args.map {|a| dump(a) }.join(', ')
|
23
|
+
if entry[:error]
|
24
|
+
"#{@prefix}#{entry[:method]}(#{args}) raised error: #{entry[:error].message}\n"
|
25
|
+
else
|
26
|
+
"#{@prefix}#{entry[:method]}(#{args}) -> #{dump entry[:return]}\n"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def dump(value)
|
31
|
+
value = value.inspect
|
32
|
+
value.size > 30 ? value[0..30] + '...' : value
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Constructor
|
37
|
+
#
|
38
|
+
# @param [Juno store] adapter The underlying store
|
39
|
+
# @param [Hash] options
|
40
|
+
#
|
41
|
+
# Options:
|
42
|
+
# * :logger - Callable logger object (default Juno::Logger::Format)
|
43
|
+
# * :logprefix - Prefix string (default 'Juno ')
|
44
|
+
# * :logout - Output (default STDOUT)
|
45
|
+
def initialize(adapter, options = {})
|
46
|
+
super
|
47
|
+
@logger = options[:logger] || Format.new(options)
|
48
|
+
end
|
49
|
+
|
50
|
+
def key?(key, options = {})
|
51
|
+
log(:key?, key, options) { super }
|
52
|
+
end
|
53
|
+
|
54
|
+
def load(key, options = {})
|
55
|
+
log(:load, key, options) { super }
|
56
|
+
end
|
57
|
+
|
58
|
+
def store(key, value, options = {})
|
59
|
+
log(:store, key, value, options) { super }
|
60
|
+
end
|
61
|
+
|
62
|
+
def delete(key, options = {})
|
63
|
+
log(:delete, key, options) { super }
|
64
|
+
end
|
65
|
+
|
66
|
+
def clear(options = {})
|
67
|
+
log(:clear, options) { super; nil }
|
68
|
+
self
|
69
|
+
end
|
70
|
+
|
71
|
+
def close
|
72
|
+
log(:close) { super }
|
73
|
+
end
|
74
|
+
|
75
|
+
protected
|
76
|
+
|
77
|
+
def log(method, *args)
|
78
|
+
ret = yield
|
79
|
+
@logger.call(:method => method, :args => args, :return => ret)
|
80
|
+
ret
|
81
|
+
rescue Exception => error
|
82
|
+
@logger.call(:method => method, :args => args, :error => error)
|
83
|
+
raise
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
data/lib/juno/proxy.rb
CHANGED
data/lib/juno/stack.rb
CHANGED
@@ -22,8 +22,9 @@ module Juno
|
|
22
22
|
instance_eval(&block)
|
23
23
|
end
|
24
24
|
|
25
|
-
def add(
|
26
|
-
|
25
|
+
def add(store = nil, &block)
|
26
|
+
raise 'Only argument or block allowed' if store && block
|
27
|
+
@stack << (store || Juno.build(&block))
|
27
28
|
nil
|
28
29
|
end
|
29
30
|
end
|
data/lib/juno/transformer.rb
CHANGED
@@ -11,29 +11,35 @@ module Juno
|
|
11
11
|
# @api public
|
12
12
|
class Transformer < Proxy
|
13
13
|
VALUE_TRANSFORMER = {
|
14
|
-
:
|
15
|
-
:
|
16
|
-
:
|
17
|
-
:
|
18
|
-
:
|
19
|
-
|
20
|
-
:
|
21
|
-
:
|
22
|
-
:
|
14
|
+
:base64 => { :load => "value.unpack('m').first", :dump => "[value].pack('m').strip" },
|
15
|
+
:bencode => { :load => '::BEncode.load(value)', :dump => '::BEncode.dump(value)', :require => 'bencode' },
|
16
|
+
:bert => { :load => '::BERT.decode(value)', :dump => '::BERT.encode(value)', :require => 'bert' },
|
17
|
+
:bson => { :load => "::BSON.deserialize(value)['v']", :dump => "::BSON.serialize('v'=>value)", :require => 'bson' },
|
18
|
+
:compress => { :load => '::Zlib::Inflate.inflate(value)', :dump => '::Zlib::Deflate.deflate(value)', :require => 'zlib' },
|
19
|
+
:json => { :load => '::MultiJson.load(value).first', :dump => '::MultiJson.dump([value])', :require => 'multi_json' },
|
20
|
+
:marshal => { :load => '::Marshal.load(value)', :dump => '::Marshal.dump(value)' },
|
21
|
+
:msgpack => { :load => '::MessagePack.unpack(value)', :dump => '::MessagePack.pack(value)', :require => 'msgpack' },
|
22
|
+
:ox => { :load => '::Ox.parse_obj(value)', :dump => '::Ox.dump(value)', :require => 'ox' },
|
23
|
+
:tnet => { :load => '::TNetstring.parse(value).first', :dump => '::TNetstring.dump(value)', :require => 'tnetstring' },
|
24
|
+
:uuencode => { :load => "value.unpack('u').first", :dump => "[value].pack('u').strip" },
|
25
|
+
:yaml => { :load => '::YAML.load(value)', :dump => '::YAML.dump(value)', :require => 'yaml' }
|
23
26
|
}
|
24
27
|
|
25
28
|
KEY_TRANSFORMER = {
|
26
|
-
:base64
|
27
|
-
:
|
28
|
-
:
|
29
|
-
:
|
30
|
-
:
|
31
|
-
:
|
32
|
-
:
|
33
|
-
:
|
34
|
-
:
|
35
|
-
|
36
|
-
:
|
29
|
+
:base64 => { :transform => "[key].pack('m').strip" },
|
30
|
+
:bencode => { :transform => '::BEncode.dump(key)', :require => 'bencode' },
|
31
|
+
:bert => { :transform => '::BERT.encode(key)', :require => 'bert' },
|
32
|
+
:bson => { :transform => "(tmp = key; String === tmp ? tmp : ::BSON.serialize('k'=>tmp).to_s)", :require => 'bson' },
|
33
|
+
:escape => { :transform => "key.gsub(/[^a-zA-Z0-9_-]+/) { '%%' + $&.unpack('H2' * $&.bytesize).join('%%').upcase }" },
|
34
|
+
:json => { :transform => '(tmp = key; String === tmp ? tmp : ::MultiJson.dump(tmp))', :require => 'multi_json' },
|
35
|
+
:marshal => { :transform => '(tmp = key; String === tmp ? tmp : ::Marshal.dump(tmp))' },
|
36
|
+
:md5 => { :transform => '::Digest::MD5.hexdigest(key)', :require => 'digest/md5' },
|
37
|
+
:msgpack => { :transform => '(tmp = key; String === tmp ? tmp : ::MessagePack.pack(tmp))', :require => 'msgpack' },
|
38
|
+
:ox => { :transform => '(tmp = key; String === tmp ? tmp : ::Ox.dump(tmp))' },
|
39
|
+
:spread => { :transform => '(tmp = key; ::File.join(tmp[0..1], tmp[2..-1]))' },
|
40
|
+
:tnet => { :transform => '(tmp = key; String === tmp ? tmp : ::TNetstring.dump(tmp))', :require => 'tnetstring' },
|
41
|
+
:uuencode => { :transform => "[key].pack('u').strip" },
|
42
|
+
:yaml => { :transform => '(tmp = key; String === tmp ? tmp : ::YAML.dump(tmp))', :require => 'yaml' },
|
37
43
|
}
|
38
44
|
|
39
45
|
@classes = {}
|
@@ -46,76 +52,70 @@ module Juno
|
|
46
52
|
keys.each do |tn|
|
47
53
|
raise "Unknown key transformer #{tn}" unless t = KEY_TRANSFORMER[tn]
|
48
54
|
require t[:require] if t[:require]
|
49
|
-
key = t[:transform].gsub('
|
55
|
+
key = t[:transform].gsub('key', key).gsub('tmp', "x#{tmp}")
|
50
56
|
tmp += 1
|
51
57
|
end
|
52
58
|
|
53
59
|
klass = Class.new(Transformer)
|
54
60
|
if values.empty?
|
55
61
|
klass.class_eval <<-end_eval, __FILE__, __LINE__
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
@adapter.delete(#{key}, options)
|
70
|
-
end
|
71
|
-
end_eval
|
62
|
+
def key?(key, options = {})
|
63
|
+
@adapter.key?(#{key}, options)
|
64
|
+
end
|
65
|
+
def load(key, options = {})
|
66
|
+
@adapter.load(#{key}, options)
|
67
|
+
end
|
68
|
+
def store(key, value, options = {})
|
69
|
+
@adapter.store(#{key}, value, options)
|
70
|
+
end
|
71
|
+
def delete(key, options = {})
|
72
|
+
@adapter.delete(#{key}, options)
|
73
|
+
end
|
74
|
+
end_eval
|
72
75
|
else
|
73
76
|
dumper, loader = 'value', 'value'
|
74
77
|
values.each_index do |i|
|
75
78
|
raise "Unknown value transformer #{values[i]}" unless t = VALUE_TRANSFORMER[values[i]]
|
76
79
|
require t[:require] if t[:require]
|
77
|
-
dumper = t[:dump].gsub('
|
78
|
-
loader = VALUE_TRANSFORMER[values[-i-1]][:load].gsub('
|
80
|
+
dumper = t[:dump].gsub('value', dumper)
|
81
|
+
loader = VALUE_TRANSFORMER[values[-i-1]][:load].gsub('value', loader)
|
79
82
|
end
|
80
83
|
|
81
84
|
klass.class_eval <<-end_eval, __FILE__, __LINE__
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
value && #{loader}
|
99
|
-
end
|
100
|
-
end_eval
|
85
|
+
def key?(key, options = {})
|
86
|
+
@adapter.key?(#{key}, options)
|
87
|
+
end
|
88
|
+
def load(key, options = {})
|
89
|
+
value = @adapter.load(#{key}, options)
|
90
|
+
value && #{loader}
|
91
|
+
end
|
92
|
+
def store(key, value, options = {})
|
93
|
+
@adapter.store(#{key}, #{dumper}, options)
|
94
|
+
value
|
95
|
+
end
|
96
|
+
def delete(key, options = {})
|
97
|
+
value = @adapter.delete(#{key}, options)
|
98
|
+
value && #{loader}
|
99
|
+
end
|
100
|
+
end_eval
|
101
101
|
end
|
102
102
|
klass
|
103
103
|
end
|
104
104
|
|
105
105
|
# Constructor
|
106
106
|
#
|
107
|
-
# @param [Juno store]
|
107
|
+
# @param [Juno store] adapter The underlying store
|
108
108
|
# @param [Hash] options
|
109
109
|
#
|
110
110
|
# Options:
|
111
111
|
# * :key - List of key transformers in the order in which they should be applied
|
112
112
|
# * :value - List of value transformers in the order in which they should be applied
|
113
|
-
def new(
|
113
|
+
def new(adapter, options = {})
|
114
114
|
keys = [options[:key]].flatten.compact
|
115
115
|
values = [options[:value]].flatten.compact
|
116
116
|
raise 'No option :key or :value specified' if keys.empty? && values.empty?
|
117
117
|
klass = @classes["#{keys.join('-')}+#{values.join('-')}"] ||= compile(keys, values)
|
118
|
-
klass.original_new(
|
118
|
+
klass.original_new(adapter, options)
|
119
119
|
end
|
120
120
|
end
|
121
121
|
end
|
data/lib/juno/version.rb
CHANGED
data/lib/juno.rb
CHANGED
@@ -4,6 +4,7 @@ module Juno
|
|
4
4
|
autoload :Cache, 'juno/cache'
|
5
5
|
autoload :Expires, 'juno/expires'
|
6
6
|
autoload :Lock, 'juno/lock'
|
7
|
+
autoload :Logger, 'juno/logger'
|
7
8
|
autoload :Proxy, 'juno/proxy'
|
8
9
|
autoload :Stack, 'juno/stack'
|
9
10
|
autoload :Transformer, 'juno/transformer'
|
@@ -44,9 +45,10 @@ module Juno
|
|
44
45
|
# @param [Hash] options
|
45
46
|
#
|
46
47
|
# Options:
|
47
|
-
# * :expires -
|
48
|
+
# * :expires - If options is true, ensure that store supports expiration by inserting
|
48
49
|
# Juno::Expires if the underlying adapter doesn't support it natively
|
49
|
-
# * :threadsafe -
|
50
|
+
# * :threadsafe - If options is true, ensure that the store is thread safe by inserting Juno::Lock
|
51
|
+
# * :logger - If options is a true or Hash, add logger to chain (Hash is passed to logger as options)
|
50
52
|
# * All other options passed to the adapter
|
51
53
|
#
|
52
54
|
# Supported adapters:
|
@@ -56,6 +58,7 @@ module Juno
|
|
56
58
|
# * ... (All other adapters from Juno::Adapters)
|
57
59
|
def self.new(name, options = {})
|
58
60
|
expires = options.delete(:expires)
|
61
|
+
logger = options.delete(:logger)
|
59
62
|
threadsafe = options.delete(:threadsafe)
|
60
63
|
transformer = {:key => :marshal, :value => :marshal}
|
61
64
|
raise 'Name must be Symbol' unless Symbol === name
|
@@ -82,25 +85,24 @@ module Juno
|
|
82
85
|
# Expires already supported
|
83
86
|
expires = false
|
84
87
|
end
|
85
|
-
build
|
88
|
+
build do
|
89
|
+
use :Logger, Hash === logger ? logger : {} if logger
|
86
90
|
use :Expires if expires
|
87
91
|
use :Transformer, transformer
|
88
92
|
use :Lock if threadsafe
|
89
|
-
adapter name
|
93
|
+
adapter name, options
|
90
94
|
end
|
91
95
|
end
|
92
96
|
|
93
97
|
# Build your own store chain!
|
94
98
|
#
|
95
|
-
# @params [Hash] options Options passed to the proxies and adapter
|
96
|
-
#
|
97
99
|
# Example:
|
98
100
|
#
|
99
101
|
# Juno.build do
|
100
102
|
# use :Expires
|
101
103
|
# adapter :Memory
|
102
104
|
# end
|
103
|
-
def self.build(
|
104
|
-
Builder.new(
|
105
|
+
def self.build(&block)
|
106
|
+
Builder.new(&block).build
|
105
107
|
end
|
106
108
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Generated by generate.rb
|
1
|
+
# Generated by generate.rb
|
2
2
|
require 'helper'
|
3
3
|
|
4
4
|
describe_juno "adapter_activerecord" do
|
@@ -21,7 +21,7 @@ describe_juno "adapter_activerecord" do
|
|
21
21
|
ActiveRecord::Base.establish_connection :adapter => (defined?(JRUBY_VERSION) ? 'jdbcsqlite3' : 'sqlite3'), :database => File.join(make_tempdir, 'activerecord-existing')
|
22
22
|
|
23
23
|
store = Juno::Adapters::ActiveRecord.new
|
24
|
-
store.table.
|
24
|
+
store.table.should be_table_exists
|
25
25
|
end
|
26
26
|
|
27
27
|
end
|
data/spec/adapter_couch_spec.rb
CHANGED
data/spec/adapter_dbm_spec.rb
CHANGED
data/spec/adapter_file_spec.rb
CHANGED
data/spec/adapter_fog_spec.rb
CHANGED
data/spec/adapter_gdbm_spec.rb
CHANGED
data/spec/adapter_memory_spec.rb
CHANGED
data/spec/adapter_mongo_spec.rb
CHANGED
data/spec/adapter_pstore_spec.rb
CHANGED
data/spec/adapter_redis_spec.rb
CHANGED