juno 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. data/Gemfile +2 -1
  2. data/README.md +9 -4
  3. data/lib/juno.rb +10 -9
  4. data/lib/juno/adapters/activerecord.rb +1 -1
  5. data/lib/juno/adapters/cassandra.rb +8 -1
  6. data/lib/juno/adapters/couch.rb +1 -1
  7. data/lib/juno/adapters/datamapper.rb +3 -3
  8. data/lib/juno/adapters/fog.rb +1 -1
  9. data/lib/juno/adapters/hbase.rb +64 -0
  10. data/lib/juno/adapters/lruhash.rb +69 -5
  11. data/lib/juno/adapters/memcached_dalli.rb +0 -4
  12. data/lib/juno/adapters/memcached_native.rb +0 -7
  13. data/lib/juno/adapters/mongo.rb +0 -4
  14. data/lib/juno/adapters/redis.rb +8 -1
  15. data/lib/juno/adapters/sequel.rb +1 -1
  16. data/lib/juno/adapters/tokyocabinet.rb +0 -4
  17. data/lib/juno/base.rb +10 -0
  18. data/lib/juno/expires.rb +1 -1
  19. data/lib/juno/transformer.rb +1 -0
  20. data/lib/juno/version.rb +1 -1
  21. data/spec/generate.rb +75 -17
  22. data/spec/juno/adapter_datamapper_spec.rb +0 -3
  23. data/spec/juno/adapter_hbase_spec.rb +13 -0
  24. data/spec/juno/adapter_lruhash_spec.rb +14 -16
  25. data/spec/juno/adapter_memory_spec.rb +6 -0
  26. data/spec/juno/expires_file_spec.rb +9 -0
  27. data/spec/juno/expires_memory_spec.rb +9 -0
  28. data/spec/juno/lock_spec.rb +6 -0
  29. data/spec/juno/null_adapter_spec.rb +3 -0
  30. data/spec/juno/proxy_expires_memory_spec.rb +9 -0
  31. data/spec/juno/simple_activerecord_spec.rb +7 -0
  32. data/spec/juno/simple_activerecord_with_expires_spec.rb +7 -0
  33. data/spec/juno/simple_cassandra_spec.rb +7 -0
  34. data/spec/juno/simple_couch_spec.rb +7 -0
  35. data/spec/juno/simple_couch_with_expires_spec.rb +7 -0
  36. data/spec/juno/simple_datamapper_spec.rb +7 -0
  37. data/spec/juno/simple_datamapper_with_expires_spec.rb +7 -0
  38. data/spec/juno/simple_datamapper_with_repository_spec.rb +7 -0
  39. data/spec/juno/simple_dbm_spec.rb +7 -0
  40. data/spec/juno/simple_dbm_with_expires_spec.rb +7 -0
  41. data/spec/juno/simple_file_spec.rb +7 -0
  42. data/spec/juno/simple_file_with_expires_spec.rb +7 -0
  43. data/spec/juno/simple_fog_spec.rb +7 -0
  44. data/spec/juno/simple_fog_with_expires_spec.rb +7 -0
  45. data/spec/juno/simple_gdbm_spec.rb +7 -0
  46. data/spec/juno/simple_gdbm_with_expires_spec.rb +7 -0
  47. data/spec/juno/simple_hashfile_spec.rb +7 -0
  48. data/spec/juno/simple_hashfile_with_expires_spec.rb +7 -0
  49. data/spec/juno/simple_hbase_spec.rb +45 -0
  50. data/spec/juno/simple_hbase_with_expires_spec.rb +46 -0
  51. data/spec/juno/simple_leveldb_spec.rb +7 -0
  52. data/spec/juno/simple_leveldb_with_expires_spec.rb +7 -0
  53. data/spec/juno/simple_localmemcache_spec.rb +7 -0
  54. data/spec/juno/simple_localmemcache_with_expires_spec.rb +7 -0
  55. data/spec/juno/simple_lruhash_spec.rb +7 -0
  56. data/spec/juno/simple_lruhash_with_expires_spec.rb +7 -0
  57. data/spec/juno/simple_memcached_dalli_spec.rb +7 -0
  58. data/spec/juno/simple_memcached_native_spec.rb +7 -0
  59. data/spec/juno/simple_memcached_spec.rb +7 -0
  60. data/spec/juno/simple_memory_spec.rb +7 -0
  61. data/spec/juno/simple_memory_with_compress_spec.rb +7 -0
  62. data/spec/juno/simple_memory_with_expires_spec.rb +7 -0
  63. data/spec/juno/simple_memory_with_json_key_serializer_spec.rb +4 -0
  64. data/spec/juno/simple_memory_with_json_md5_key_serializer_spec.rb +4 -0
  65. data/spec/juno/simple_memory_with_prefix_spec.rb +7 -0
  66. data/spec/juno/simple_memory_with_quicklz_compress_spec.rb +7 -0
  67. data/spec/juno/simple_mongo_spec.rb +7 -0
  68. data/spec/juno/simple_mongo_with_expires_spec.rb +7 -0
  69. data/spec/juno/simple_null_spec.rb +3 -0
  70. data/spec/juno/simple_pstore_spec.rb +7 -0
  71. data/spec/juno/simple_pstore_with_expires_spec.rb +7 -0
  72. data/spec/juno/simple_redis_spec.rb +7 -0
  73. data/spec/juno/simple_riak_spec.rb +7 -0
  74. data/spec/juno/simple_riak_with_expires_spec.rb +7 -0
  75. data/spec/juno/simple_sdbm_spec.rb +7 -0
  76. data/spec/juno/simple_sdbm_with_expires_spec.rb +7 -0
  77. data/spec/juno/simple_sequel_spec.rb +7 -0
  78. data/spec/juno/simple_sequel_with_expires_spec.rb +7 -0
  79. data/spec/juno/simple_sqlite_spec.rb +7 -0
  80. data/spec/juno/simple_sqlite_with_expires_spec.rb +7 -0
  81. data/spec/juno/simple_tokyocabinet_spec.rb +7 -0
  82. data/spec/juno/simple_tokyocabinet_with_expires_spec.rb +7 -0
  83. data/spec/juno/simple_yaml_spec.rb +6 -0
  84. data/spec/juno/simple_yaml_with_expires_spec.rb +6 -0
  85. data/spec/juno/transformer_bzip2_spec.rb +22 -0
  86. data/spec/juno/transformer_marshal_base64_spec.rb +7 -0
  87. data/spec/juno/transformer_marshal_escape_spec.rb +7 -0
  88. data/spec/juno/transformer_marshal_hmac_spec.rb +7 -0
  89. data/spec/juno/transformer_marshal_md5_spec.rb +7 -0
  90. data/spec/juno/transformer_marshal_md5_spread_spec.rb +7 -0
  91. data/spec/juno/transformer_marshal_prefix_spec.rb +7 -0
  92. data/spec/juno/transformer_marshal_rmd160_spec.rb +7 -0
  93. data/spec/juno/transformer_marshal_sha1_spec.rb +7 -0
  94. data/spec/juno/transformer_marshal_sha256_spec.rb +7 -0
  95. data/spec/juno/transformer_marshal_sha384_spec.rb +7 -0
  96. data/spec/juno/transformer_marshal_sha512_spec.rb +7 -0
  97. data/spec/juno/transformer_marshal_uuencode_spec.rb +7 -0
  98. data/spec/juno/transformer_ox_spec.rb +6 -0
  99. data/spec/juno/transformer_yaml_spec.rb +6 -0
  100. data/spec/junospecs.rb +990 -320
  101. 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
- * SDBM (`:SDBM`)
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 (default :marshal, disable with nil)
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) || :marshal
72
- key_serializer = options.delete(:key_serializer) || serializer
73
- value_serializer = options.delete(:value_serializer) || serializer
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, :DataMapper, :Null
89
- # For PStore, YAML and DataMapper only the key has to be a string
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
@@ -39,7 +39,7 @@ module Juno
39
39
  end
40
40
 
41
41
  def key?(key, options = {})
42
- !!@table.find_by_k(key)
42
+ @table.find_by_k(key) != nil
43
43
  end
44
44
 
45
45
  def load(key, options = {})
@@ -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 = {})
@@ -17,7 +17,7 @@ module Juno
17
17
  end
18
18
 
19
19
  def key?(key, options = {})
20
- !!@db.get(key)
20
+ @db.get(key) != nil
21
21
  rescue RestClient::ResourceNotFound
22
22
  false
23
23
  end
@@ -8,8 +8,8 @@ module Juno
8
8
  class DataMapper < Base
9
9
  class Store
10
10
  include ::DataMapper::Resource
11
- property :k, String, :key => true
12
- property :v, Object, :lazy => false
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 { !!Store.get(key) }
32
+ context { Store.get(key) != nil }
33
33
  end
34
34
 
35
35
  def load(key, options = {})
@@ -19,7 +19,7 @@ module Juno
19
19
  end
20
20
 
21
21
  def key?(key, options = {})
22
- !!@directory.files.head(key)
22
+ @directory.files.head(key) != nil
23
23
  end
24
24
 
25
25
  def load(key, options = {})
@@ -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 < Memory
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 1024)
14
+ # * :max_size - Maximum byte size of hash values (default 1024000)
14
15
  def initialize(options = {})
15
- @memory = Hashery::LRUHash.new(options[:max_size] || 1024)
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
@@ -17,10 +17,6 @@ module Juno
17
17
  @cache = ::Dalli::Client.new(server, options)
18
18
  end
19
19
 
20
- def key?(key, options = {})
21
- !!@cache.get(key)
22
- end
23
-
24
20
  def load(key, options = {})
25
21
  value = @cache.get(key)
26
22
  if value && options.include?(:expires)
@@ -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)
@@ -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
@@ -13,7 +13,14 @@ module Juno
13
13
  end
14
14
 
15
15
  def key?(key, options = {})
16
- @redis.exists(key)
16
+ if @redis.exists(key)
17
+ if expires = options[:expires]
18
+ @redis.expire(key, expires)
19
+ end
20
+ true
21
+ else
22
+ false
23
+ end
17
24
  end
18
25
 
19
26
  def load(key, options = {})
@@ -24,7 +24,7 @@ module Juno
24
24
  end
25
25
 
26
26
  def key?(key, options = {})
27
- !!sequel_table[:k => key]
27
+ sequel_table[:k => key] != nil
28
28
  end
29
29
 
30
30
  def load(key, options = {})
@@ -24,10 +24,6 @@ module Juno
24
24
  end or raise @memory.errmsg(@memory.ecode)
25
25
  end
26
26
 
27
- def key?(key, options = {})
28
- !!load(key, options)
29
- end
30
-
31
27
  def delete(key, options = {})
32
28
  value = load(key, options)
33
29
  if value
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
@@ -7,7 +7,7 @@ module Juno
7
7
  # @api public
8
8
  class Expires < Proxy
9
9
  def key?(key, options = {})
10
- !!load(key, options)
10
+ load(key, options) != nil
11
11
  end
12
12
 
13
13
  def load(key, options = {})
@@ -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
@@ -1,5 +1,5 @@
1
1
  module Juno
2
2
  # Juno version number
3
3
  # @api public
4
- VERSION = '0.3.0'
4
+ VERSION = '0.3.1'
5
5
  end