juno 0.3.0 → 0.3.1

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.
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