juno 0.3.1 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +2 -277
- data/juno.gemspec +6 -5
- data/lib/juno.rb +3 -122
- metadata +23 -307
- data/.gitignore +0 -6
- data/.travis.yml +0 -30
- data/Gemfile +0 -56
- data/LICENSE +0 -20
- data/Rakefile +0 -33
- data/SPEC.md +0 -71
- data/benchmarks/run.rb +0 -180
- data/lib/juno/adapters/activerecord.rb +0 -74
- data/lib/juno/adapters/cassandra.rb +0 -89
- data/lib/juno/adapters/cookie.rb +0 -35
- data/lib/juno/adapters/couch.rb +0 -57
- data/lib/juno/adapters/datamapper.rb +0 -76
- data/lib/juno/adapters/dbm.rb +0 -25
- data/lib/juno/adapters/file.rb +0 -60
- data/lib/juno/adapters/fog.rb +0 -51
- data/lib/juno/adapters/gdbm.rb +0 -25
- data/lib/juno/adapters/hbase.rb +0 -64
- data/lib/juno/adapters/leveldb.rb +0 -35
- data/lib/juno/adapters/localmemcache.rb +0 -26
- data/lib/juno/adapters/lruhash.rb +0 -83
- data/lib/juno/adapters/memcached.rb +0 -11
- data/lib/juno/adapters/memcached_dalli.rb +0 -51
- data/lib/juno/adapters/memcached_native.rb +0 -52
- data/lib/juno/adapters/memory.rb +0 -32
- data/lib/juno/adapters/mongo.rb +0 -50
- data/lib/juno/adapters/null.rb +0 -30
- data/lib/juno/adapters/pstore.rb +0 -58
- data/lib/juno/adapters/redis.rb +0 -56
- data/lib/juno/adapters/riak.rb +0 -57
- data/lib/juno/adapters/sdbm.rb +0 -35
- data/lib/juno/adapters/sequel.rb +0 -67
- data/lib/juno/adapters/sqlite.rb +0 -61
- data/lib/juno/adapters/tokyocabinet.rb +0 -41
- data/lib/juno/adapters/yaml.rb +0 -15
- data/lib/juno/base.rb +0 -62
- data/lib/juno/builder.rb +0 -39
- data/lib/juno/cache.rb +0 -78
- data/lib/juno/expires.rb +0 -47
- data/lib/juno/lock.rb +0 -44
- data/lib/juno/logger.rb +0 -86
- data/lib/juno/proxy.rb +0 -72
- data/lib/juno/stack.rb +0 -72
- data/lib/juno/transformer.rb +0 -176
- data/lib/juno/version.rb +0 -5
- data/lib/rack/cache/juno.rb +0 -93
- data/lib/rack/juno_cookies.rb +0 -64
- data/lib/rack/session/juno.rb +0 -63
- data/spec/generate.rb +0 -1068
- data/spec/helper.rb +0 -78
- data/spec/juno/adapter_activerecord_spec.rb +0 -27
- data/spec/juno/adapter_cassandra_spec.rb +0 -13
- data/spec/juno/adapter_cookie_spec.rb +0 -13
- data/spec/juno/adapter_couch_spec.rb +0 -13
- data/spec/juno/adapter_datamapper_spec.rb +0 -44
- data/spec/juno/adapter_dbm_spec.rb +0 -13
- data/spec/juno/adapter_file_spec.rb +0 -13
- data/spec/juno/adapter_fog_spec.rb +0 -18
- data/spec/juno/adapter_gdbm_spec.rb +0 -13
- data/spec/juno/adapter_hbase_spec.rb +0 -13
- data/spec/juno/adapter_leveldb_spec.rb +0 -13
- data/spec/juno/adapter_localmemcache_spec.rb +0 -13
- data/spec/juno/adapter_lruhash_spec.rb +0 -26
- data/spec/juno/adapter_memcached_dalli_spec.rb +0 -14
- data/spec/juno/adapter_memcached_native_spec.rb +0 -14
- data/spec/juno/adapter_memcached_spec.rb +0 -14
- data/spec/juno/adapter_memory_spec.rb +0 -34
- data/spec/juno/adapter_mongo_spec.rb +0 -13
- data/spec/juno/adapter_pstore_spec.rb +0 -16
- data/spec/juno/adapter_redis_spec.rb +0 -14
- data/spec/juno/adapter_riak_spec.rb +0 -17
- data/spec/juno/adapter_sdbm_spec.rb +0 -13
- data/spec/juno/adapter_sequel_spec.rb +0 -13
- data/spec/juno/adapter_sqlite_spec.rb +0 -13
- data/spec/juno/adapter_tokyocabinet_bdb_spec.rb +0 -13
- data/spec/juno/adapter_tokyocabinet_hdb_spec.rb +0 -13
- data/spec/juno/adapter_yaml_spec.rb +0 -16
- data/spec/juno/cache_file_memory_spec.rb +0 -29
- data/spec/juno/cache_memory_null_spec.rb +0 -18
- data/spec/juno/expires_file_spec.rb +0 -71
- data/spec/juno/expires_memory_spec.rb +0 -49
- data/spec/juno/lock_spec.rb +0 -37
- data/spec/juno/null_adapter_spec.rb +0 -22
- data/spec/juno/proxy_expires_memory_spec.rb +0 -51
- data/spec/juno/proxy_redis_spec.rb +0 -18
- data/spec/juno/simple_activerecord_spec.rb +0 -45
- data/spec/juno/simple_activerecord_with_expires_spec.rb +0 -46
- data/spec/juno/simple_cassandra_spec.rb +0 -46
- data/spec/juno/simple_couch_spec.rb +0 -45
- data/spec/juno/simple_couch_with_expires_spec.rb +0 -46
- data/spec/juno/simple_datamapper_spec.rb +0 -47
- data/spec/juno/simple_datamapper_with_expires_spec.rb +0 -48
- data/spec/juno/simple_datamapper_with_repository_spec.rb +0 -47
- data/spec/juno/simple_dbm_spec.rb +0 -45
- data/spec/juno/simple_dbm_with_expires_spec.rb +0 -46
- data/spec/juno/simple_file_spec.rb +0 -45
- data/spec/juno/simple_file_with_expires_spec.rb +0 -46
- data/spec/juno/simple_fog_spec.rb +0 -50
- data/spec/juno/simple_fog_with_expires_spec.rb +0 -52
- data/spec/juno/simple_gdbm_spec.rb +0 -45
- data/spec/juno/simple_gdbm_with_expires_spec.rb +0 -46
- data/spec/juno/simple_hashfile_spec.rb +0 -45
- data/spec/juno/simple_hashfile_with_expires_spec.rb +0 -46
- data/spec/juno/simple_hbase_spec.rb +0 -45
- data/spec/juno/simple_hbase_with_expires_spec.rb +0 -46
- data/spec/juno/simple_leveldb_spec.rb +0 -45
- data/spec/juno/simple_leveldb_with_expires_spec.rb +0 -46
- data/spec/juno/simple_localmemcache_spec.rb +0 -45
- data/spec/juno/simple_localmemcache_with_expires_spec.rb +0 -46
- data/spec/juno/simple_lruhash_spec.rb +0 -45
- data/spec/juno/simple_lruhash_with_expires_spec.rb +0 -46
- data/spec/juno/simple_memcached_dalli_spec.rb +0 -46
- data/spec/juno/simple_memcached_native_spec.rb +0 -46
- data/spec/juno/simple_memcached_spec.rb +0 -46
- data/spec/juno/simple_memory_spec.rb +0 -45
- data/spec/juno/simple_memory_with_compress_spec.rb +0 -45
- data/spec/juno/simple_memory_with_expires_spec.rb +0 -46
- data/spec/juno/simple_memory_with_json_key_serializer_spec.rb +0 -32
- data/spec/juno/simple_memory_with_json_md5_key_serializer_spec.rb +0 -32
- data/spec/juno/simple_memory_with_json_serializer_spec.rb +0 -22
- data/spec/juno/simple_memory_with_json_value_serializer_spec.rb +0 -29
- data/spec/juno/simple_memory_with_prefix_spec.rb +0 -45
- data/spec/juno/simple_memory_with_quicklz_compress_spec.rb +0 -45
- data/spec/juno/simple_mongo_spec.rb +0 -45
- data/spec/juno/simple_mongo_with_expires_spec.rb +0 -46
- data/spec/juno/simple_null_spec.rb +0 -32
- data/spec/juno/simple_pstore_spec.rb +0 -45
- data/spec/juno/simple_pstore_with_expires_spec.rb +0 -46
- data/spec/juno/simple_redis_spec.rb +0 -46
- data/spec/juno/simple_riak_spec.rb +0 -49
- data/spec/juno/simple_riak_with_expires_spec.rb +0 -50
- data/spec/juno/simple_sdbm_spec.rb +0 -45
- data/spec/juno/simple_sdbm_with_expires_spec.rb +0 -46
- data/spec/juno/simple_sequel_spec.rb +0 -45
- data/spec/juno/simple_sequel_with_expires_spec.rb +0 -46
- data/spec/juno/simple_sqlite_spec.rb +0 -45
- data/spec/juno/simple_sqlite_with_expires_spec.rb +0 -46
- data/spec/juno/simple_tokyocabinet_spec.rb +0 -45
- data/spec/juno/simple_tokyocabinet_with_expires_spec.rb +0 -46
- data/spec/juno/simple_yaml_spec.rb +0 -44
- data/spec/juno/simple_yaml_with_expires_spec.rb +0 -45
- data/spec/juno/stack_file_memory_spec.rb +0 -20
- data/spec/juno/stack_memory_file_spec.rb +0 -19
- data/spec/juno/transformer_bencode_spec.rb +0 -25
- data/spec/juno/transformer_bert_spec.rb +0 -25
- data/spec/juno/transformer_bson_spec.rb +0 -25
- data/spec/juno/transformer_bzip2_spec.rb +0 -22
- data/spec/juno/transformer_json_spec.rb +0 -25
- data/spec/juno/transformer_lzma_spec.rb +0 -22
- data/spec/juno/transformer_lzo_spec.rb +0 -22
- data/spec/juno/transformer_marshal_base64_spec.rb +0 -48
- data/spec/juno/transformer_marshal_escape_spec.rb +0 -48
- data/spec/juno/transformer_marshal_hmac_spec.rb +0 -48
- data/spec/juno/transformer_marshal_md5_spec.rb +0 -48
- data/spec/juno/transformer_marshal_md5_spread_spec.rb +0 -48
- data/spec/juno/transformer_marshal_prefix_spec.rb +0 -48
- data/spec/juno/transformer_marshal_rmd160_spec.rb +0 -48
- data/spec/juno/transformer_marshal_sha1_spec.rb +0 -48
- data/spec/juno/transformer_marshal_sha256_spec.rb +0 -48
- data/spec/juno/transformer_marshal_sha384_spec.rb +0 -48
- data/spec/juno/transformer_marshal_sha512_spec.rb +0 -48
- data/spec/juno/transformer_marshal_uuencode_spec.rb +0 -48
- data/spec/juno/transformer_msgpack_spec.rb +0 -25
- data/spec/juno/transformer_ox_spec.rb +0 -46
- data/spec/juno/transformer_quicklz_spec.rb +0 -22
- data/spec/juno/transformer_snappy_spec.rb +0 -22
- data/spec/juno/transformer_tnet_spec.rb +0 -25
- data/spec/juno/transformer_yaml_spec.rb +0 -46
- data/spec/juno/transformer_zlib_spec.rb +0 -22
- data/spec/junospecs.rb +0 -2284
- data/spec/rack/cache_juno_spec.rb +0 -355
- data/spec/rack/juno_cookies_spec.rb +0 -81
- data/spec/rack/session_juno_spec.rb +0 -305
data/lib/juno/expires.rb
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
module Juno
|
2
|
-
# Adds expiration support to the underlying store
|
3
|
-
#
|
4
|
-
# #store and #load support the :expires option to set/update
|
5
|
-
# the expiration time.
|
6
|
-
#
|
7
|
-
# @api public
|
8
|
-
class Expires < Proxy
|
9
|
-
def key?(key, options = {})
|
10
|
-
load(key, options) != nil
|
11
|
-
end
|
12
|
-
|
13
|
-
def load(key, options = {})
|
14
|
-
value = check_expired(key, super(key, options))
|
15
|
-
if value && options.include?(:expires)
|
16
|
-
store(key, value, options)
|
17
|
-
else
|
18
|
-
value
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
def store(key, value, options = {})
|
23
|
-
if expires = options.delete(:expires)
|
24
|
-
super(key, [value, Time.now.to_i + expires].compact, options)
|
25
|
-
else
|
26
|
-
super(key, [value], options)
|
27
|
-
end
|
28
|
-
value
|
29
|
-
end
|
30
|
-
|
31
|
-
def delete(key, options = {})
|
32
|
-
check_expired(key, super, false)
|
33
|
-
end
|
34
|
-
|
35
|
-
protected
|
36
|
-
|
37
|
-
def check_expired(key, value, delete_expired = true)
|
38
|
-
value, expires = value
|
39
|
-
if expires && Time.now.to_i > expires
|
40
|
-
delete(key) if delete_expired
|
41
|
-
nil
|
42
|
-
else
|
43
|
-
value
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
data/lib/juno/lock.rb
DELETED
@@ -1,44 +0,0 @@
|
|
1
|
-
require 'thread'
|
2
|
-
|
3
|
-
module Juno
|
4
|
-
# Locks the underlying stores with a Mutex
|
5
|
-
# @api public
|
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)
|
14
|
-
def initialize(adapter, options = {})
|
15
|
-
super
|
16
|
-
@lock = options[:mutex] || Mutex.new
|
17
|
-
end
|
18
|
-
|
19
|
-
def key?(key, options = {})
|
20
|
-
@lock.synchronize { super }
|
21
|
-
end
|
22
|
-
|
23
|
-
def load(key, options = {})
|
24
|
-
@lock.synchronize { super }
|
25
|
-
end
|
26
|
-
|
27
|
-
def store(key, value, options = {})
|
28
|
-
@lock.synchronize { super }
|
29
|
-
end
|
30
|
-
|
31
|
-
def delete(key, options = {})
|
32
|
-
@lock.synchronize { super }
|
33
|
-
end
|
34
|
-
|
35
|
-
def clear(options = {})
|
36
|
-
@lock.synchronize { super }
|
37
|
-
self
|
38
|
-
end
|
39
|
-
|
40
|
-
def close
|
41
|
-
@lock.synchronize { super }
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
data/lib/juno/logger.rb
DELETED
@@ -1,86 +0,0 @@
|
|
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
DELETED
@@ -1,72 +0,0 @@
|
|
1
|
-
module Juno
|
2
|
-
# Proxy base class
|
3
|
-
# @api public
|
4
|
-
class Proxy < Base
|
5
|
-
attr_reader :adapter
|
6
|
-
|
7
|
-
# Constructor
|
8
|
-
#
|
9
|
-
# @param [Juno store] underlying adapter
|
10
|
-
# @param [Hash] options
|
11
|
-
def initialize(adapter, options = {})
|
12
|
-
@adapter = adapter
|
13
|
-
end
|
14
|
-
|
15
|
-
# Exists the value with key
|
16
|
-
#
|
17
|
-
# @param [Object] key
|
18
|
-
# @return [Boolean]
|
19
|
-
# @param [Hash] options
|
20
|
-
# @api public
|
21
|
-
def key?(key, options = {})
|
22
|
-
@adapter.key?(key, options)
|
23
|
-
end
|
24
|
-
|
25
|
-
# Fetch value with key. Return nil if the key doesn't exist
|
26
|
-
#
|
27
|
-
# @param [Object] key
|
28
|
-
# @param [Hash] options
|
29
|
-
# @return [Object] value
|
30
|
-
# @api public
|
31
|
-
def load(key, options = {})
|
32
|
-
@adapter.load(key, options)
|
33
|
-
end
|
34
|
-
|
35
|
-
# Store value with key
|
36
|
-
#
|
37
|
-
# @param [Object] key
|
38
|
-
# @param [Object] value
|
39
|
-
# @param [Hash] options
|
40
|
-
# @return value
|
41
|
-
# @api public
|
42
|
-
def store(key, value, options = {})
|
43
|
-
@adapter.store(key, value, options)
|
44
|
-
end
|
45
|
-
|
46
|
-
# Delete the key from the store and return the current value
|
47
|
-
#
|
48
|
-
# @param [Object] key
|
49
|
-
# @return [Object] current value
|
50
|
-
# @param [Hash] options
|
51
|
-
# @api public
|
52
|
-
def delete(key, options = {})
|
53
|
-
@adapter.delete(key, options)
|
54
|
-
end
|
55
|
-
|
56
|
-
# Clear all keys in this store
|
57
|
-
#
|
58
|
-
# @param [Hash] options
|
59
|
-
# @return [void]
|
60
|
-
# @api public
|
61
|
-
def clear(options = {})
|
62
|
-
@adapter.clear(options)
|
63
|
-
self
|
64
|
-
end
|
65
|
-
|
66
|
-
# Close this store
|
67
|
-
# @api public
|
68
|
-
def close
|
69
|
-
@adapter.close
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
data/lib/juno/stack.rb
DELETED
@@ -1,72 +0,0 @@
|
|
1
|
-
module Juno
|
2
|
-
# Combines multiple stores. Reads return the result from the first store,
|
3
|
-
# writes go to all stores.
|
4
|
-
#
|
5
|
-
# @example Add stack to chain
|
6
|
-
# Juno.build do
|
7
|
-
# use(:Stack) do
|
8
|
-
# add { adapter :Redis }
|
9
|
-
# add { adapter :File, :dir => 'data' }
|
10
|
-
# add { adapter :File, :dir => 'replicate' }
|
11
|
-
# end
|
12
|
-
# end
|
13
|
-
#
|
14
|
-
# @api public
|
15
|
-
class Stack < Base
|
16
|
-
# @api private
|
17
|
-
class DSL
|
18
|
-
attr_reader :stack
|
19
|
-
|
20
|
-
def initialize(options, &block)
|
21
|
-
@stack = options[:stack].to_a
|
22
|
-
instance_eval(&block)
|
23
|
-
end
|
24
|
-
|
25
|
-
def add(store = nil, &block)
|
26
|
-
raise ArgumentError, 'Only argument or block allowed' if store && block
|
27
|
-
@stack << (store || Juno.build(&block))
|
28
|
-
nil
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
attr_reader :stack
|
33
|
-
|
34
|
-
def initialize(options = {}, &block)
|
35
|
-
@stack = DSL.new(options, &block).stack
|
36
|
-
end
|
37
|
-
|
38
|
-
def key?(key, options = {})
|
39
|
-
@stack.any? {|s| s.key?(key) }
|
40
|
-
end
|
41
|
-
|
42
|
-
def load(key, options = {})
|
43
|
-
@stack.each do |s|
|
44
|
-
value = s.load(key, options)
|
45
|
-
return value if value
|
46
|
-
end
|
47
|
-
nil
|
48
|
-
end
|
49
|
-
|
50
|
-
def store(key, value, options = {})
|
51
|
-
@stack.each {|s| s.store(key, value, options) }
|
52
|
-
value
|
53
|
-
end
|
54
|
-
|
55
|
-
def delete(key, options = {})
|
56
|
-
@stack.inject(nil) do |value, s|
|
57
|
-
v = s.delete(key, options)
|
58
|
-
value || v
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
def clear(options = {})
|
63
|
-
@stack.each {|s| s.clear }
|
64
|
-
self
|
65
|
-
end
|
66
|
-
|
67
|
-
def close
|
68
|
-
@stack.each {|s| s.close }
|
69
|
-
nil
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
data/lib/juno/transformer.rb
DELETED
@@ -1,176 +0,0 @@
|
|
1
|
-
module Juno
|
2
|
-
# Transforms keys and values (Marshal, YAML, JSON, Base64, MD5, ...).
|
3
|
-
#
|
4
|
-
# @example Add transformer to chain
|
5
|
-
# Juno.build do
|
6
|
-
# transformer :key => [:marshal, :escape], :value => [:marshal]
|
7
|
-
# adapter :File, :dir => 'data'
|
8
|
-
# end
|
9
|
-
#
|
10
|
-
# @api public
|
11
|
-
class Transformer < Proxy
|
12
|
-
def initialize(adapter, options = {})
|
13
|
-
super
|
14
|
-
@prefix, @secret = options[:prefix], options[:secret]
|
15
|
-
end
|
16
|
-
|
17
|
-
class << self
|
18
|
-
alias_method :original_new, :new
|
19
|
-
|
20
|
-
# Constructor
|
21
|
-
#
|
22
|
-
# @param [Juno store] adapter The underlying store
|
23
|
-
# @param [Hash] options
|
24
|
-
#
|
25
|
-
# Options:
|
26
|
-
# * :key - List of key transformers in the order in which they should be applied
|
27
|
-
# * :value - List of value transformers in the order in which they should be applied
|
28
|
-
# * :prefix - Prefix string for key namespacing (Used by the :prefix key transformer)
|
29
|
-
# * :secret - HMAC secret to verify values (Used by the :hmac value transformer)
|
30
|
-
def new(adapter, options = {})
|
31
|
-
keys = [options[:key]].flatten.compact
|
32
|
-
values = [options[:value]].flatten.compact
|
33
|
-
raise ArgumentError, 'Option :key or :value is required' if keys.empty? && values.empty?
|
34
|
-
raise ArgumentError, 'Option :prefix is required for :prefix key transformer' if keys.include?(:prefix) && !options[:prefix]
|
35
|
-
raise ArgumentError, 'Option :secret is required for :hmac value transformer' if values.include?(:hmac) && !options[:secret]
|
36
|
-
name = class_name(keys, values)
|
37
|
-
const_set(name, compile(keys, values)) unless const_defined?(name)
|
38
|
-
const_get(name).original_new(adapter, options)
|
39
|
-
end
|
40
|
-
|
41
|
-
private
|
42
|
-
|
43
|
-
def compile(keys, values)
|
44
|
-
raise ArgumentError, 'Invalid key transformer chain' if KEY_TRANSFORMER !~ keys.map(&:inspect).join
|
45
|
-
raise ArgumentError, 'Invalid value transformer chain' if VALUE_TRANSFORMER !~ values.map(&:inspect).join
|
46
|
-
|
47
|
-
key = compile_transformer(keys, 'key')
|
48
|
-
|
49
|
-
klass = Class.new(self)
|
50
|
-
if values.empty?
|
51
|
-
klass.class_eval <<-end_eval, __FILE__, __LINE__
|
52
|
-
def key?(key, options = {})
|
53
|
-
@adapter.key?(#{key}, options)
|
54
|
-
end
|
55
|
-
def load(key, options = {})
|
56
|
-
@adapter.load(#{key}, options)
|
57
|
-
end
|
58
|
-
def store(key, value, options = {})
|
59
|
-
@adapter.store(#{key}, value, options)
|
60
|
-
end
|
61
|
-
def delete(key, options = {})
|
62
|
-
@adapter.delete(#{key}, options)
|
63
|
-
end
|
64
|
-
end_eval
|
65
|
-
else
|
66
|
-
dump = compile_transformer(values, 'value')
|
67
|
-
load = compile_transformer(values.reverse, 'value', 1)
|
68
|
-
|
69
|
-
klass.class_eval <<-end_eval, __FILE__, __LINE__
|
70
|
-
def key?(key, options = {})
|
71
|
-
@adapter.key?(#{key}, options)
|
72
|
-
end
|
73
|
-
def load(key, options = {})
|
74
|
-
value = @adapter.load(#{key}, options)
|
75
|
-
value && #{load}
|
76
|
-
end
|
77
|
-
def store(key, value, options = {})
|
78
|
-
@adapter.store(#{key}, #{dump}, options)
|
79
|
-
value
|
80
|
-
end
|
81
|
-
def delete(key, options = {})
|
82
|
-
value = @adapter.delete(#{key}, options)
|
83
|
-
value && #{load}
|
84
|
-
end
|
85
|
-
end_eval
|
86
|
-
end
|
87
|
-
klass
|
88
|
-
end
|
89
|
-
|
90
|
-
# Compile transformer validator regular expression
|
91
|
-
def compile_validator(s)
|
92
|
-
Regexp.new(s.gsub(/\w+/) do
|
93
|
-
'(' + TRANSFORMER.select {|k,v| v.first.to_s == $& }.map {|v| ":#{v.first}" }.join('|') + ')'
|
94
|
-
end.gsub(/\s+/, '').sub(/\A/, '\A').sub(/\Z/, '\Z'))
|
95
|
-
end
|
96
|
-
|
97
|
-
# Returned compiled transformer code string
|
98
|
-
def compile_transformer(transformer, var, i = 2)
|
99
|
-
transformer.inject(var) do |value, name|
|
100
|
-
raise ArgumentError, "Unknown transformer #{name}" unless t = TRANSFORMER[name]
|
101
|
-
require t[3] if t[3]
|
102
|
-
code = t[i]
|
103
|
-
if t[0] == :serialize && var == 'key'
|
104
|
-
"(tmp = #{value}; String === tmp ? tmp : #{code.gsub('value', 'tmp')})"
|
105
|
-
else
|
106
|
-
code.gsub('value', value)
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
def class_name(keys, values)
|
112
|
-
(keys.empty? ? '' : keys.map(&:to_s).map(&:capitalize).join << 'Key') <<
|
113
|
-
(values.empty? ? '' : values.map(&:to_s).map(&:capitalize).join << 'Value')
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
# Available key/value transformers
|
118
|
-
TRANSFORMER = {
|
119
|
-
# Name => [ Type, Load, Dump, Library ],
|
120
|
-
:bencode => [ :serialize, '::BEncode.load(value)', '::BEncode.dump(value)', 'bencode' ],
|
121
|
-
:bert => [ :serialize, '::BERT.decode(value)', '::BERT.encode(value)', 'bert' ],
|
122
|
-
:bson => [ :serialize, "::BSON.deserialize(value)['v']", "::BSON.serialize('v'=>value).to_s", 'bson' ],
|
123
|
-
:json => [ :serialize, '::MultiJson.load(value).first', '::MultiJson.dump([value])', 'multi_json' ],
|
124
|
-
:marshal => [ :serialize, '::Marshal.load(value)', '::Marshal.dump(value)' ],
|
125
|
-
:msgpack => [ :serialize, '::MessagePack.unpack(value)', '::MessagePack.pack(value)', 'msgpack' ],
|
126
|
-
:ox => [ :serialize, '::Ox.parse_obj(value)', '::Ox.dump(value)', 'ox' ],
|
127
|
-
:tnet => [ :serialize, '::TNetstring.parse(value).first', '::TNetstring.dump(value)', 'tnetstring' ],
|
128
|
-
:yaml => [ :serialize, '::YAML.load(value)', '::YAML.dump(value)', 'yaml' ],
|
129
|
-
:bzip2 => [ :compress, '::Bzip2.uncompress(value)', '::Bzip2.compress(value)', 'bzip2' ],
|
130
|
-
:lzma => [ :compress, '::LZMA.decompress(value)', '::LZMA.compress(value)', 'lzma' ],
|
131
|
-
:lzo => [ :compress, '::LZO.decompress(value)', '::LZO.compress(value)', 'lzoruby' ],
|
132
|
-
:snappy => [ :compress, '::Snappy.inflate(value)', '::Snappy.deflate(value)', 'snappy' ],
|
133
|
-
:quicklz => [ :compress, '::QuickLZ.decompress(value)', '::QuickLZ.compress(value)', 'qlzruby' ],
|
134
|
-
:zlib => [ :compress, '::Zlib::Inflate.inflate(value)', '::Zlib::Deflate.deflate(value)', 'zlib' ],
|
135
|
-
:base64 => [ :encode, "value.unpack('m').first", "[value].pack('m').strip" ],
|
136
|
-
:uuencode => [ :encode, "value.unpack('u').first", "[value].pack('u').strip" ],
|
137
|
-
:escape => [ :encode, 'Escape.unescape(value)', 'Escape.escape(value)' ],
|
138
|
-
:hmac => [ :hmac, 'HMAC.verify(value, @secret)', 'HMAC.sign(value, @secret)' , 'openssl' ],
|
139
|
-
:md5 => [ :digest, nil, '::Digest::MD5.hexdigest(value)', 'digest/md5' ],
|
140
|
-
:rmd160 => [ :digest, nil, '::Digest::RMD160.hexdigest(value)', 'digest/rmd160' ],
|
141
|
-
:sha1 => [ :digest, nil, '::Digest::SHA1.hexdigest(value)', 'digest/sha1' ],
|
142
|
-
:sha256 => [ :digest, nil, '::Digest::SHA256.hexdigest(value)', 'digest/sha2' ],
|
143
|
-
:sha384 => [ :digest, nil, '::Digest::SHA384.hexdigest(value)', 'digest/sha2' ],
|
144
|
-
:sha512 => [ :digest, nil, '::Digest::SHA512.hexdigest(value)', 'digest/sha2' ],
|
145
|
-
:prefix => [ :prefix, nil, '@prefix+value' ],
|
146
|
-
:spread => [ :spread, nil, '(tmp = value; ::File.join(tmp[0..1], tmp[2..-1]))' ],
|
147
|
-
}
|
148
|
-
|
149
|
-
# Allowed value transformers (Read it like a regular expression!)
|
150
|
-
VALUE_TRANSFORMER = compile_validator('serialize? compress? hmac? encode?')
|
151
|
-
|
152
|
-
# Allowed key transformers (Read it like a regular expression!)
|
153
|
-
KEY_TRANSFORMER = compile_validator('serialize? prefix? (encode | (digest spread?))?')
|
154
|
-
|
155
|
-
module Escape
|
156
|
-
def self.escape(value)
|
157
|
-
value.gsub(/[^a-zA-Z0-9_-]+/){ '%' + $&.unpack('H2' * $&.bytesize).join('%').upcase }
|
158
|
-
end
|
159
|
-
|
160
|
-
def self.unescape(value)
|
161
|
-
value.gsub(/((?:%[0-9a-fA-F]{2})+)/){ [$1.delete('%')].pack('H*') }
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
module HMAC
|
166
|
-
def self.verify(value, secret)
|
167
|
-
hash, value = value[0..31], value[32..-1]
|
168
|
-
value if hash == OpenSSL::HMAC.digest(OpenSSL::Digest::Digest.new('sha256'), secret, value)
|
169
|
-
end
|
170
|
-
|
171
|
-
def self.sign(value, secret)
|
172
|
-
OpenSSL::HMAC.digest(OpenSSL::Digest::Digest.new('sha256'), secret, value) << value
|
173
|
-
end
|
174
|
-
end
|
175
|
-
end
|
176
|
-
end
|