juno 0.2.4 → 0.2.5
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/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