juno 0.3.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +2 -1
- data/README.md +9 -4
- data/lib/juno.rb +10 -9
- data/lib/juno/adapters/activerecord.rb +1 -1
- data/lib/juno/adapters/cassandra.rb +8 -1
- data/lib/juno/adapters/couch.rb +1 -1
- data/lib/juno/adapters/datamapper.rb +3 -3
- data/lib/juno/adapters/fog.rb +1 -1
- data/lib/juno/adapters/hbase.rb +64 -0
- data/lib/juno/adapters/lruhash.rb +69 -5
- data/lib/juno/adapters/memcached_dalli.rb +0 -4
- data/lib/juno/adapters/memcached_native.rb +0 -7
- data/lib/juno/adapters/mongo.rb +0 -4
- data/lib/juno/adapters/redis.rb +8 -1
- data/lib/juno/adapters/sequel.rb +1 -1
- data/lib/juno/adapters/tokyocabinet.rb +0 -4
- data/lib/juno/base.rb +10 -0
- data/lib/juno/expires.rb +1 -1
- data/lib/juno/transformer.rb +1 -0
- data/lib/juno/version.rb +1 -1
- data/spec/generate.rb +75 -17
- data/spec/juno/adapter_datamapper_spec.rb +0 -3
- data/spec/juno/adapter_hbase_spec.rb +13 -0
- data/spec/juno/adapter_lruhash_spec.rb +14 -16
- data/spec/juno/adapter_memory_spec.rb +6 -0
- data/spec/juno/expires_file_spec.rb +9 -0
- data/spec/juno/expires_memory_spec.rb +9 -0
- data/spec/juno/lock_spec.rb +6 -0
- data/spec/juno/null_adapter_spec.rb +3 -0
- data/spec/juno/proxy_expires_memory_spec.rb +9 -0
- data/spec/juno/simple_activerecord_spec.rb +7 -0
- data/spec/juno/simple_activerecord_with_expires_spec.rb +7 -0
- data/spec/juno/simple_cassandra_spec.rb +7 -0
- data/spec/juno/simple_couch_spec.rb +7 -0
- data/spec/juno/simple_couch_with_expires_spec.rb +7 -0
- data/spec/juno/simple_datamapper_spec.rb +7 -0
- data/spec/juno/simple_datamapper_with_expires_spec.rb +7 -0
- data/spec/juno/simple_datamapper_with_repository_spec.rb +7 -0
- data/spec/juno/simple_dbm_spec.rb +7 -0
- data/spec/juno/simple_dbm_with_expires_spec.rb +7 -0
- data/spec/juno/simple_file_spec.rb +7 -0
- data/spec/juno/simple_file_with_expires_spec.rb +7 -0
- data/spec/juno/simple_fog_spec.rb +7 -0
- data/spec/juno/simple_fog_with_expires_spec.rb +7 -0
- data/spec/juno/simple_gdbm_spec.rb +7 -0
- data/spec/juno/simple_gdbm_with_expires_spec.rb +7 -0
- data/spec/juno/simple_hashfile_spec.rb +7 -0
- data/spec/juno/simple_hashfile_with_expires_spec.rb +7 -0
- data/spec/juno/simple_hbase_spec.rb +45 -0
- data/spec/juno/simple_hbase_with_expires_spec.rb +46 -0
- data/spec/juno/simple_leveldb_spec.rb +7 -0
- data/spec/juno/simple_leveldb_with_expires_spec.rb +7 -0
- data/spec/juno/simple_localmemcache_spec.rb +7 -0
- data/spec/juno/simple_localmemcache_with_expires_spec.rb +7 -0
- data/spec/juno/simple_lruhash_spec.rb +7 -0
- data/spec/juno/simple_lruhash_with_expires_spec.rb +7 -0
- data/spec/juno/simple_memcached_dalli_spec.rb +7 -0
- data/spec/juno/simple_memcached_native_spec.rb +7 -0
- data/spec/juno/simple_memcached_spec.rb +7 -0
- data/spec/juno/simple_memory_spec.rb +7 -0
- data/spec/juno/simple_memory_with_compress_spec.rb +7 -0
- data/spec/juno/simple_memory_with_expires_spec.rb +7 -0
- data/spec/juno/simple_memory_with_json_key_serializer_spec.rb +4 -0
- data/spec/juno/simple_memory_with_json_md5_key_serializer_spec.rb +4 -0
- data/spec/juno/simple_memory_with_prefix_spec.rb +7 -0
- data/spec/juno/simple_memory_with_quicklz_compress_spec.rb +7 -0
- data/spec/juno/simple_mongo_spec.rb +7 -0
- data/spec/juno/simple_mongo_with_expires_spec.rb +7 -0
- data/spec/juno/simple_null_spec.rb +3 -0
- data/spec/juno/simple_pstore_spec.rb +7 -0
- data/spec/juno/simple_pstore_with_expires_spec.rb +7 -0
- data/spec/juno/simple_redis_spec.rb +7 -0
- data/spec/juno/simple_riak_spec.rb +7 -0
- data/spec/juno/simple_riak_with_expires_spec.rb +7 -0
- data/spec/juno/simple_sdbm_spec.rb +7 -0
- data/spec/juno/simple_sdbm_with_expires_spec.rb +7 -0
- data/spec/juno/simple_sequel_spec.rb +7 -0
- data/spec/juno/simple_sequel_with_expires_spec.rb +7 -0
- data/spec/juno/simple_sqlite_spec.rb +7 -0
- data/spec/juno/simple_sqlite_with_expires_spec.rb +7 -0
- data/spec/juno/simple_tokyocabinet_spec.rb +7 -0
- data/spec/juno/simple_tokyocabinet_with_expires_spec.rb +7 -0
- data/spec/juno/simple_yaml_spec.rb +6 -0
- data/spec/juno/simple_yaml_with_expires_spec.rb +6 -0
- data/spec/juno/transformer_bzip2_spec.rb +22 -0
- data/spec/juno/transformer_marshal_base64_spec.rb +7 -0
- data/spec/juno/transformer_marshal_escape_spec.rb +7 -0
- data/spec/juno/transformer_marshal_hmac_spec.rb +7 -0
- data/spec/juno/transformer_marshal_md5_spec.rb +7 -0
- data/spec/juno/transformer_marshal_md5_spread_spec.rb +7 -0
- data/spec/juno/transformer_marshal_prefix_spec.rb +7 -0
- data/spec/juno/transformer_marshal_rmd160_spec.rb +7 -0
- data/spec/juno/transformer_marshal_sha1_spec.rb +7 -0
- data/spec/juno/transformer_marshal_sha256_spec.rb +7 -0
- data/spec/juno/transformer_marshal_sha384_spec.rb +7 -0
- data/spec/juno/transformer_marshal_sha512_spec.rb +7 -0
- data/spec/juno/transformer_marshal_uuencode_spec.rb +7 -0
- data/spec/juno/transformer_ox_spec.rb +6 -0
- data/spec/juno/transformer_yaml_spec.rb +6 -0
- data/spec/junospecs.rb +990 -320
- metadata +11 -2
data/Gemfile
CHANGED
@@ -24,6 +24,7 @@ alternatives :mri => 'msgpack', :jruby => 'msgpack-jruby'
|
|
24
24
|
alternatives :mri => 'bert'
|
25
25
|
|
26
26
|
# Compressors used by Transformer
|
27
|
+
alternatives :mri => 'bzip2-ruby'
|
27
28
|
alternatives :mri => 'ruby-lzma'
|
28
29
|
alternatives :mri => 'qlzruby'
|
29
30
|
alternatives :mri => 'lzoruby'
|
@@ -41,8 +42,8 @@ gem 'couchrest'
|
|
41
42
|
gem 'sequel'
|
42
43
|
gem 'dalli'
|
43
44
|
gem 'riak-client'
|
44
|
-
gem 'hashery'
|
45
45
|
gem 'cassandra'
|
46
|
+
#gem 'hbaserb'
|
46
47
|
#gem 'localmemcache'
|
47
48
|
alternatives :mri => 'leveldb-ruby'
|
48
49
|
alternatives :mri => 'tokyocabinet'
|
data/README.md
CHANGED
@@ -26,7 +26,7 @@ Out of the box, it supports the following backends:
|
|
26
26
|
|
27
27
|
* Memory:
|
28
28
|
* In-memory store (`:Memory`)
|
29
|
-
* LRU hash (`:LRUHash`)
|
29
|
+
* LRU hash - prefer this over :Memory! (`:LRUHash`)
|
30
30
|
* LocalMemCache (`:LocalMemCache`)
|
31
31
|
* Memcached store (`:Memcached`, `:MemcachedNative` and `:MemcachedDalli`)
|
32
32
|
* Relational Databases:
|
@@ -41,13 +41,14 @@ Out of the box, it supports the following backends:
|
|
41
41
|
* Filesystem directory store which spreads files in subdirectories using md5 hash (`:HashFile`)
|
42
42
|
* Key/value databases:
|
43
43
|
* Berkeley DB (`:DBM`)
|
44
|
+
* Cassandra (`:Cassandra`)
|
44
45
|
* GDBM (`:GDBM`)
|
45
|
-
*
|
46
|
+
* HBase (`:HBase`)
|
47
|
+
* LevelDB (`:LevelDB`)
|
46
48
|
* Redis (`:Redis`)
|
47
49
|
* Riak (`:Riak`)
|
50
|
+
* SDBM (`:SDBM`)
|
48
51
|
* TokyoCabinet (`:TokyoCabinet`)
|
49
|
-
* Cassandra (`:Cassandra`)
|
50
|
-
* LevelDB (`:LevelDB`)
|
51
52
|
* Document databases:
|
52
53
|
* CouchDB (`:Couch`)
|
53
54
|
* MongoDB (`:Mongo`)
|
@@ -181,6 +182,10 @@ end
|
|
181
182
|
|
182
183
|
# Expires in 60 seconds
|
183
184
|
cache.store(key, value, :expires => 60)
|
185
|
+
|
186
|
+
# Update expires time if value is found
|
187
|
+
cache.load(key, :expires => 30)
|
188
|
+
cache.key?(key, :expires => 30)
|
184
189
|
~~~
|
185
190
|
|
186
191
|
You can add the expires feature to other backends using the Expires proxy:
|
data/lib/juno.rb
CHANGED
@@ -19,6 +19,7 @@ module Juno
|
|
19
19
|
autoload :File, 'juno/adapters/file'
|
20
20
|
autoload :Fog, 'juno/adapters/fog'
|
21
21
|
autoload :GDBM, 'juno/adapters/gdbm'
|
22
|
+
autoload :HBase, 'juno/adapters/hbase'
|
22
23
|
autoload :LevelDB, 'juno/adapters/leveldb'
|
23
24
|
autoload :LocalMemCache, 'juno/adapters/localmemcache'
|
24
25
|
autoload :LRUHash, 'juno/adapters/lruhash'
|
@@ -52,9 +53,9 @@ module Juno
|
|
52
53
|
# * :threadsafe - If true, ensure that the store is thread safe by inserting Juno::Lock
|
53
54
|
# * :logger - If true or Hash, add logger to chain (Hash is passed to logger as options)
|
54
55
|
# * :compress - If true, compress value with zlib, or specify custom compress, e.g. :quicklz
|
55
|
-
# * :serializer - Serializer used for key and value
|
56
|
-
# * :key_serializer - Serializer used for key (default options[:serializer])
|
57
|
-
# * :value_serializer - Serializer used for key (default options[:serializer])
|
56
|
+
# * :serializer - Serializer used for key and value, disable with nil (default :marshal)
|
57
|
+
# * :key_serializer - Serializer used for key, disable with nil (default options[:serializer] if not provided)
|
58
|
+
# * :value_serializer - Serializer used for key, disable with nil (default options[:serializer] if not provided)
|
58
59
|
# * :prefix - Key prefix used for namespacing (default none)
|
59
60
|
# * All other options passed to the adapter
|
60
61
|
#
|
@@ -68,15 +69,15 @@ module Juno
|
|
68
69
|
logger = options.delete(:logger)
|
69
70
|
threadsafe = options.delete(:threadsafe)
|
70
71
|
compress = options.delete(:compress)
|
71
|
-
serializer = options.delete(:serializer)
|
72
|
-
key_serializer = options.delete(:key_serializer)
|
73
|
-
value_serializer = options.
|
72
|
+
serializer = options.include?(:serializer) ? options.delete(:serializer) : :marshal
|
73
|
+
key_serializer = options.include?(:key_serializer) ? options.delete(:key_serializer) : serializer
|
74
|
+
value_serializer = options.include?(:value_serializer) ? options.delete(:value_serialiizer) : serializer
|
74
75
|
transformer = { :key => [key_serializer], :value => [value_serializer], :prefix => options.delete(:prefix) }
|
75
76
|
transformer[:key] << :prefix if transformer[:prefix]
|
76
77
|
transformer[:value] << (Symbol === compress ? compress : :zlib) if compress
|
77
78
|
raise ArgumentError, 'Name must be Symbol' unless Symbol === name
|
78
79
|
case name
|
79
|
-
when :Sequel, :ActiveRecord, :Couch
|
80
|
+
when :Sequel, :ActiveRecord, :Couch, :DataMapper
|
80
81
|
# Sequel accept only base64 keys and values
|
81
82
|
# FIXME: Couch should work only with :marshal but this raises an error on 1.9
|
82
83
|
transformer[:key] << :base64
|
@@ -85,8 +86,8 @@ module Juno
|
|
85
86
|
# Memcached accept only base64 keys, expires already supported
|
86
87
|
expires = false
|
87
88
|
transformer[:key] << :base64
|
88
|
-
when :PStore, :YAML, :
|
89
|
-
# For PStore
|
89
|
+
when :PStore, :YAML, :Null
|
90
|
+
# For PStore and YAML only the key has to be a string
|
90
91
|
transformer.delete(:value) if transformer[:value] == [:marshal]
|
91
92
|
when :HashFile
|
92
93
|
# Use spreading hashes
|
@@ -45,7 +45,14 @@ module Juno
|
|
45
45
|
end
|
46
46
|
|
47
47
|
def key?(key, options = {})
|
48
|
-
@client.exists?(@cf, key)
|
48
|
+
if @client.exists?(@cf, key)
|
49
|
+
if options.include?(:expires) && (value = load(key))
|
50
|
+
store(key, value, options)
|
51
|
+
end
|
52
|
+
true
|
53
|
+
else
|
54
|
+
false
|
55
|
+
end
|
49
56
|
end
|
50
57
|
|
51
58
|
def load(key, options = {})
|
data/lib/juno/adapters/couch.rb
CHANGED
@@ -8,8 +8,8 @@ module Juno
|
|
8
8
|
class DataMapper < Base
|
9
9
|
class Store
|
10
10
|
include ::DataMapper::Resource
|
11
|
-
property :k,
|
12
|
-
property :v,
|
11
|
+
property :k, Text, :key => true
|
12
|
+
property :v, Text, :lazy => false
|
13
13
|
end
|
14
14
|
|
15
15
|
# Constructor
|
@@ -29,7 +29,7 @@ module Juno
|
|
29
29
|
end
|
30
30
|
|
31
31
|
def key?(key, options = {})
|
32
|
-
context {
|
32
|
+
context { Store.get(key) != nil }
|
33
33
|
end
|
34
34
|
|
35
35
|
def load(key, options = {})
|
data/lib/juno/adapters/fog.rb
CHANGED
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'hbaserb'
|
2
|
+
|
3
|
+
module Juno
|
4
|
+
module Adapters
|
5
|
+
# HBase thrift backend
|
6
|
+
# @api public
|
7
|
+
class HBase < Base
|
8
|
+
# Constructor
|
9
|
+
#
|
10
|
+
# @param [Hash] options
|
11
|
+
#
|
12
|
+
# Options:
|
13
|
+
# * :host - Server host name (default 127.0.0.1)
|
14
|
+
# * :port - Server port (default 9090)
|
15
|
+
# * :table - Table name (default juno)
|
16
|
+
# * :column_family - Column family (default juno)
|
17
|
+
# * :column - Column (default value)
|
18
|
+
def initialize(options = {})
|
19
|
+
options[:host] ||= '127.0.0.1'
|
20
|
+
options[:port] ||= '9090'
|
21
|
+
options[:table] ||= 'juno'
|
22
|
+
options[:column] ||= 'value'
|
23
|
+
cf = (options[:column_family] || 'juno')
|
24
|
+
@db = HBaseRb::Client.new(options[:host], options[:port])
|
25
|
+
@db.create_table(options[:table], cf) unless @db.has_table?(options[:table])
|
26
|
+
@table = @db.get_table(options[:table])
|
27
|
+
@column = "#{cf}:#{options[:column]}"
|
28
|
+
end
|
29
|
+
|
30
|
+
def key?(key, options = {})
|
31
|
+
@table.get(key, @column).first != nil
|
32
|
+
end
|
33
|
+
|
34
|
+
def load(key, options = {})
|
35
|
+
value = @table.get(key, @column).first
|
36
|
+
value ? value.value : nil
|
37
|
+
end
|
38
|
+
|
39
|
+
def delete(key, options = {})
|
40
|
+
if value = load(key, options)
|
41
|
+
@table.delete_row(key)
|
42
|
+
value
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def store(key, value, options = {})
|
47
|
+
@table.mutate_row(key, @column => value)
|
48
|
+
value
|
49
|
+
end
|
50
|
+
|
51
|
+
def clear(options = {})
|
52
|
+
@table.create_scanner do |row|
|
53
|
+
@table.delete_row(row.row)
|
54
|
+
end
|
55
|
+
self
|
56
|
+
end
|
57
|
+
|
58
|
+
def close
|
59
|
+
@db.close
|
60
|
+
nil
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -1,18 +1,82 @@
|
|
1
|
-
require 'hashery/lru_hash'
|
2
|
-
|
3
1
|
module Juno
|
4
2
|
module Adapters
|
5
3
|
# LRUHash backend
|
4
|
+
#
|
5
|
+
# Based on Hashery::LRUHash but simpler and measures memory usage instead of hash size.
|
6
|
+
#
|
6
7
|
# @api public
|
7
|
-
class LRUHash <
|
8
|
+
class LRUHash < Base
|
8
9
|
# Constructor
|
9
10
|
#
|
10
11
|
# @param [Hash] options
|
11
12
|
#
|
12
13
|
# Options:
|
13
|
-
# * :max_size - Maximum size of hash (default
|
14
|
+
# * :max_size - Maximum byte size of hash values (default 1024000)
|
14
15
|
def initialize(options = {})
|
15
|
-
@
|
16
|
+
@max_size = options[:max_size] || 1024000
|
17
|
+
clear
|
18
|
+
end
|
19
|
+
|
20
|
+
def key?(key, options = {})
|
21
|
+
@entry.key?(key)
|
22
|
+
end
|
23
|
+
|
24
|
+
def load(key, options = {})
|
25
|
+
if entry = @entry[key]
|
26
|
+
entry.insert_after(@list)
|
27
|
+
entry.value
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def store(key, value, options = {})
|
32
|
+
if entry = @entry[key]
|
33
|
+
@size -= entry.value.bytesize
|
34
|
+
else
|
35
|
+
@entry[key] = entry = Entry.new
|
36
|
+
entry.key = key
|
37
|
+
end
|
38
|
+
entry.value = value
|
39
|
+
@size += entry.value.bytesize
|
40
|
+
entry.insert_after(@list)
|
41
|
+
delete(@list.prev.key) while @list.next != @list.prev && @size > @max_size
|
42
|
+
value
|
43
|
+
end
|
44
|
+
|
45
|
+
def delete(key, options = {})
|
46
|
+
if entry = @entry.delete(key)
|
47
|
+
@size -= entry.value.bytesize
|
48
|
+
entry.unlink
|
49
|
+
entry.value
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def clear(options = {})
|
54
|
+
@entry, @size = {}, 0
|
55
|
+
@list = Entry.new
|
56
|
+
@list.prev = @list.next = @list
|
57
|
+
self
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
class Entry
|
63
|
+
attr_accessor :key, :value, :prev, :next
|
64
|
+
|
65
|
+
def unlink
|
66
|
+
@prev.next = @next if @prev
|
67
|
+
@next.prev = @prev if @next
|
68
|
+
@prev = @next = nil
|
69
|
+
end
|
70
|
+
|
71
|
+
def insert_after(entry)
|
72
|
+
if entry.next != self
|
73
|
+
unlink
|
74
|
+
@next = entry.next
|
75
|
+
@prev = entry
|
76
|
+
entry.next.prev = self
|
77
|
+
entry.next = self
|
78
|
+
end
|
79
|
+
end
|
16
80
|
end
|
17
81
|
end
|
18
82
|
end
|
@@ -20,13 +20,6 @@ module Juno
|
|
20
20
|
@cache = ::Memcached.new(server, options)
|
21
21
|
end
|
22
22
|
|
23
|
-
def key?(key, options = {})
|
24
|
-
@cache.get(key, false)
|
25
|
-
true
|
26
|
-
rescue ::Memcached::NotFound
|
27
|
-
false
|
28
|
-
end
|
29
|
-
|
30
23
|
def load(key, options = {})
|
31
24
|
value = @cache.get(key, false)
|
32
25
|
if value && options.include?(:expires)
|
data/lib/juno/adapters/mongo.rb
CHANGED
@@ -23,10 +23,6 @@ module Juno
|
|
23
23
|
@collection = connection.db(db).collection(collection)
|
24
24
|
end
|
25
25
|
|
26
|
-
def key?(key, options = {})
|
27
|
-
!!load(key, options)
|
28
|
-
end
|
29
|
-
|
30
26
|
def load(key, options = {})
|
31
27
|
value = @collection.find_one('_id' => key)
|
32
28
|
value ? value['value'].to_s : nil
|
data/lib/juno/adapters/redis.rb
CHANGED
data/lib/juno/adapters/sequel.rb
CHANGED
data/lib/juno/base.rb
CHANGED
@@ -2,6 +2,16 @@ module Juno
|
|
2
2
|
# Simple interface to key/value stores with Hash-like interface.
|
3
3
|
# @api public
|
4
4
|
class Base
|
5
|
+
# Exists the value with key
|
6
|
+
#
|
7
|
+
# @param [Object] key
|
8
|
+
# @return [Boolean]
|
9
|
+
# @param [Hash] options
|
10
|
+
# @api public
|
11
|
+
def key?(key, options = {})
|
12
|
+
load(key, options) != nil
|
13
|
+
end
|
14
|
+
|
5
15
|
# Explicitly close the store
|
6
16
|
# @api public
|
7
17
|
def close
|
data/lib/juno/expires.rb
CHANGED
data/lib/juno/transformer.rb
CHANGED
@@ -126,6 +126,7 @@ module Juno
|
|
126
126
|
:ox => [ :serialize, '::Ox.parse_obj(value)', '::Ox.dump(value)', 'ox' ],
|
127
127
|
:tnet => [ :serialize, '::TNetstring.parse(value).first', '::TNetstring.dump(value)', 'tnetstring' ],
|
128
128
|
:yaml => [ :serialize, '::YAML.load(value)', '::YAML.dump(value)', 'yaml' ],
|
129
|
+
:bzip2 => [ :compress, '::Bzip2.uncompress(value)', '::Bzip2.compress(value)', 'bzip2' ],
|
129
130
|
:lzma => [ :compress, '::LZMA.decompress(value)', '::LZMA.compress(value)', 'lzma' ],
|
130
131
|
:lzo => [ :compress, '::LZO.decompress(value)', '::LZO.compress(value)', 'lzoruby' ],
|
131
132
|
:snappy => [ :compress, '::Snappy.inflate(value)', '::Snappy.deflate(value)', 'snappy' ],
|
data/lib/juno/version.rb
CHANGED