juno 0.1.1 → 0.2.0

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 (161) hide show
  1. data/.gitignore +2 -1
  2. data/.travis.yml +6 -0
  3. data/Gemfile +16 -9
  4. data/README.md +92 -34
  5. data/Rakefile +23 -5
  6. data/benchmarks/run.rb +19 -22
  7. data/juno.gemspec +0 -3
  8. data/lib/juno/adapters/activerecord.rb +58 -0
  9. data/lib/juno/adapters/cassandra.rb +47 -0
  10. data/lib/juno/adapters/couch.rb +43 -0
  11. data/lib/juno/adapters/datamapper.rb +64 -0
  12. data/lib/juno/adapters/dbm.rb +17 -0
  13. data/lib/juno/adapters/file.rb +58 -0
  14. data/lib/juno/adapters/fog.rb +42 -0
  15. data/lib/juno/adapters/gdbm.rb +17 -0
  16. data/lib/juno/adapters/localmemcache.rb +18 -0
  17. data/lib/juno/adapters/memcached.rb +11 -0
  18. data/lib/juno/adapters/memcached_dalli.rb +46 -0
  19. data/lib/juno/adapters/memcached_native.rb +47 -0
  20. data/lib/juno/adapters/memory.rb +30 -0
  21. data/lib/juno/adapters/mongo.rb +43 -0
  22. data/lib/juno/adapters/null.rb +28 -0
  23. data/lib/juno/adapters/pstore.rb +51 -0
  24. data/lib/juno/adapters/redis.rb +43 -0
  25. data/lib/juno/adapters/riak.rb +46 -0
  26. data/lib/juno/adapters/sdbm.rb +27 -0
  27. data/lib/juno/adapters/sequel.rb +50 -0
  28. data/lib/juno/adapters/sqlite.rb +52 -0
  29. data/lib/juno/adapters/tokyocabinet.rb +33 -0
  30. data/lib/juno/adapters/yaml.rb +13 -0
  31. data/lib/juno/base.rb +11 -89
  32. data/lib/juno/builder.rb +30 -0
  33. data/lib/juno/cache.rb +64 -0
  34. data/lib/juno/expires.rb +6 -10
  35. data/lib/juno/proxy.rb +62 -3
  36. data/lib/juno/stack.rb +27 -11
  37. data/lib/juno/transformer.rb +106 -0
  38. data/lib/juno/version.rb +1 -1
  39. data/lib/juno.rb +81 -29
  40. data/spec/adapter_activerecord_spec.rb +41 -0
  41. data/spec/adapter_cassandra_spec.rb +27 -0
  42. data/spec/adapter_couch_spec.rb +27 -0
  43. data/spec/adapter_datamapper_spec.rb +61 -0
  44. data/spec/adapter_dbm_spec.rb +27 -0
  45. data/spec/adapter_file_spec.rb +27 -0
  46. data/spec/adapter_fog_spec.rb +35 -0
  47. data/spec/adapter_gdbm_spec.rb +27 -0
  48. data/spec/adapter_localmemcache_spec.rb +27 -0
  49. data/spec/adapter_memcached_dalli_spec.rb +28 -0
  50. data/spec/adapter_memcached_native_spec.rb +28 -0
  51. data/spec/adapter_memcached_spec.rb +28 -0
  52. data/spec/adapter_memory_spec.rb +42 -0
  53. data/spec/adapter_mongo_spec.rb +27 -0
  54. data/spec/adapter_pstore_spec.rb +30 -0
  55. data/spec/adapter_redis_spec.rb +28 -0
  56. data/spec/adapter_riak_spec.rb +31 -0
  57. data/spec/adapter_sdbm_spec.rb +27 -0
  58. data/spec/adapter_sequel_spec.rb +27 -0
  59. data/spec/adapter_sqlite_spec.rb +27 -0
  60. data/spec/adapter_tokyocabinet_spec.rb +27 -0
  61. data/spec/adapter_yaml_spec.rb +30 -0
  62. data/spec/cache_file_memory_spec.rb +50 -0
  63. data/spec/cache_memory_null_spec.rb +39 -0
  64. data/spec/expires_file_spec.rb +82 -0
  65. data/spec/expires_memory_spec.rb +59 -0
  66. data/spec/generate.rb +736 -0
  67. data/spec/helper.rb +39 -0
  68. data/spec/junospecs.rb +1540 -0
  69. data/spec/null_adapter_spec.rb +33 -0
  70. data/spec/proxy_expires_memory_spec.rb +63 -0
  71. data/spec/proxy_redis_spec.rb +38 -0
  72. data/spec/simple_activerecord_spec.rb +52 -0
  73. data/spec/simple_cassandra_spec.rb +53 -0
  74. data/spec/simple_couch_spec.rb +52 -0
  75. data/spec/simple_datamapper_spec.rb +54 -0
  76. data/spec/simple_datamapper_with_repository_spec.rb +54 -0
  77. data/spec/simple_dbm_spec.rb +52 -0
  78. data/spec/simple_file_spec.rb +52 -0
  79. data/spec/simple_fog_spec.rb +60 -0
  80. data/spec/simple_gdbm_spec.rb +52 -0
  81. data/spec/simple_hashfile_spec.rb +52 -0
  82. data/spec/simple_localmemcache_spec.rb +52 -0
  83. data/spec/simple_memcached_dalli_spec.rb +53 -0
  84. data/spec/simple_memcached_native_spec.rb +53 -0
  85. data/spec/simple_memcached_spec.rb +53 -0
  86. data/spec/simple_memory_spec.rb +52 -0
  87. data/spec/simple_mongo_spec.rb +52 -0
  88. data/spec/simple_null_spec.rb +43 -0
  89. data/spec/simple_pstore_spec.rb +52 -0
  90. data/spec/simple_redis_spec.rb +53 -0
  91. data/spec/simple_riak_spec.rb +56 -0
  92. data/spec/simple_sdbm_spec.rb +52 -0
  93. data/spec/simple_sequel_spec.rb +52 -0
  94. data/spec/simple_sqlite_spec.rb +52 -0
  95. data/spec/simple_tokyocabinet_spec.rb +52 -0
  96. data/spec/simple_yaml_spec.rb +52 -0
  97. data/spec/stack_file_memory_spec.rb +43 -0
  98. data/spec/stack_memory_file_spec.rb +42 -0
  99. data/spec/transformer_bson_spec.rb +44 -0
  100. data/spec/transformer_json_spec.rb +44 -0
  101. data/spec/transformer_marshal_base64_spec.rb +60 -0
  102. data/spec/transformer_marshal_escape_spec.rb +60 -0
  103. data/spec/transformer_marshal_md5_spec.rb +60 -0
  104. data/spec/transformer_marshal_md5_spread_spec.rb +60 -0
  105. data/spec/transformer_msgpack_spec.rb +44 -0
  106. data/spec/transformer_yaml_spec.rb +59 -0
  107. metadata +164 -108
  108. data/lib/juno/activerecord.rb +0 -55
  109. data/lib/juno/cassandra.rb +0 -45
  110. data/lib/juno/couch.rb +0 -43
  111. data/lib/juno/datamapper.rb +0 -63
  112. data/lib/juno/dbm.rb +0 -15
  113. data/lib/juno/file.rb +0 -62
  114. data/lib/juno/fog.rb +0 -48
  115. data/lib/juno/gdbm.rb +0 -15
  116. data/lib/juno/hashfile.rb +0 -12
  117. data/lib/juno/localmemcache.rb +0 -16
  118. data/lib/juno/memcached.rb +0 -7
  119. data/lib/juno/memcached_dalli.rb +0 -55
  120. data/lib/juno/memcached_native.rb +0 -56
  121. data/lib/juno/memory.rb +0 -7
  122. data/lib/juno/mongodb.rb +0 -43
  123. data/lib/juno/null.rb +0 -23
  124. data/lib/juno/pstore.rb +0 -49
  125. data/lib/juno/redis.rb +0 -46
  126. data/lib/juno/riak.rb +0 -45
  127. data/lib/juno/sdbm.rb +0 -15
  128. data/lib/juno/sequel.rb +0 -48
  129. data/lib/juno/sqlite.rb +0 -50
  130. data/lib/juno/tokyocabinet.rb +0 -36
  131. data/lib/juno/yaml.rb +0 -9
  132. data/test/helper.rb +0 -212
  133. data/test/test_activerecord.rb +0 -33
  134. data/test/test_cassandra.rb +0 -13
  135. data/test/test_couch.rb +0 -13
  136. data/test/test_datamapper.rb +0 -64
  137. data/test/test_dbm.rb +0 -13
  138. data/test/test_expires.rb +0 -9
  139. data/test/test_file.rb +0 -9
  140. data/test/test_fog.rb +0 -17
  141. data/test/test_gdbm.rb +0 -13
  142. data/test/test_hashfile.rb +0 -9
  143. data/test/test_localmemcache.rb +0 -13
  144. data/test/test_memcached.rb +0 -14
  145. data/test/test_memcached_dalli.rb +0 -14
  146. data/test/test_memcached_native.rb +0 -14
  147. data/test/test_memory.rb +0 -9
  148. data/test/test_mongodb.rb +0 -13
  149. data/test/test_null.rb +0 -9
  150. data/test/test_proxy.rb +0 -9
  151. data/test/test_pstore.rb +0 -9
  152. data/test/test_redis.rb +0 -13
  153. data/test/test_riak.rb +0 -13
  154. data/test/test_sdbm.rb +0 -13
  155. data/test/test_sequel.rb +0 -13
  156. data/test/test_sqlite.rb +0 -13
  157. data/test/test_stack.rb +0 -10
  158. data/test/test_tokyocabinet.rb +0 -13
  159. data/test/test_yaml.rb +0 -9
  160. data/unsupported/test_tokyotyrant.rb +0 -13
  161. data/unsupported/tokyotyrant.rb +0 -29
@@ -0,0 +1,30 @@
1
+ module Juno
2
+ class Builder
3
+ def build
4
+ klass, options, block = @proxies.first
5
+ store = klass.new(@options.merge(options), &block)
6
+ @proxies[1..-1].each do |proxy|
7
+ klass, options, block = proxy
8
+ store = klass.new(store, @options.merge(options), &block)
9
+ end
10
+ store
11
+ end
12
+
13
+ def initialize(options = {}, &block)
14
+ raise 'No block given' unless block_given?
15
+ raise 'Options must be Hash' unless Hash === options
16
+ @options = options
17
+ @proxies = []
18
+ instance_eval(&block)
19
+ end
20
+
21
+ def use(proxy, options = {}, &block)
22
+ proxy = Juno.const_get(proxy) if Symbol === proxy
23
+ @proxies.unshift [proxy, options, block]
24
+ end
25
+
26
+ def adapter(name, options = {}, &block)
27
+ use(Adapters.const_get(name), options, &block)
28
+ end
29
+ end
30
+ end
data/lib/juno/cache.rb ADDED
@@ -0,0 +1,64 @@
1
+ module Juno
2
+ class Cache < Base
3
+ class DSL
4
+ def initialize(options, &block)
5
+ @cache, @backend = options[:cache], options[:backend]
6
+ instance_eval(&block)
7
+ end
8
+
9
+ def backend(options = {}, &block)
10
+ raise 'Backend already set' if @backend
11
+ @backend = Hash === options ? Juno.build(options, &block) : options
12
+ end
13
+
14
+ def cache(options = {}, &block)
15
+ raise 'Cache already set' if @cache
16
+ @cache = Hash === options ? Juno.build(options, &block) : options
17
+ end
18
+
19
+ def result
20
+ [@cache, @backend]
21
+ end
22
+ end
23
+
24
+ attr_reader :cache, :backend
25
+
26
+ def initialize(options = {}, &block)
27
+ @cache, @backend = DSL.new(options, &block).result
28
+ end
29
+
30
+ def key?(key, options = {})
31
+ @cache.key?(key, options) || @backend.key?(key, options)
32
+ end
33
+
34
+ def load(key, options = {})
35
+ value = @cache.load(key, options)
36
+ unless value
37
+ value = @backend.load(key, options)
38
+ @cache.store(key, value, options) if value
39
+ end
40
+ value
41
+ end
42
+
43
+ def store(key, value, options = {})
44
+ @cache.store(key, value, options)
45
+ @backend.store(key, value, options)
46
+ end
47
+
48
+ def delete(key, options = {})
49
+ @cache.delete(key, options)
50
+ @backend.delete(key, options)
51
+ end
52
+
53
+ def clear(options = {})
54
+ @cache.clear(options)
55
+ @backend.clear(options)
56
+ self
57
+ end
58
+
59
+ def close
60
+ @cache.close
61
+ @backend.close
62
+ end
63
+ end
64
+ end
data/lib/juno/expires.rb CHANGED
@@ -1,22 +1,18 @@
1
1
  module Juno
2
2
  class Expires < Proxy
3
3
  def key?(key, options = {})
4
- !!self[key]
4
+ !!load(key, options)
5
5
  end
6
6
 
7
- def fetch(key, value = nil, options = {}, &block)
8
- result = check_expired(key, super(key, value, options, &block))
9
- if result && options.include?(:expires)
10
- store(key, result, options)
7
+ def load(key, options = {})
8
+ value = check_expired(key, super(key, options))
9
+ if value && options.include?(:expires)
10
+ store(key, value, options)
11
11
  else
12
- result
12
+ value
13
13
  end
14
14
  end
15
15
 
16
- def [](key)
17
- check_expired(key, super(key))
18
- end
19
-
20
16
  def store(key, value, options = {})
21
17
  if expires = options.delete(:expires)
22
18
  super(key, [value, Time.now.to_i + expires].compact, options)
data/lib/juno/proxy.rb CHANGED
@@ -1,5 +1,64 @@
1
- require 'delegate'
2
-
3
1
  module Juno
4
- Proxy = DelegateClass(Base)
2
+ class Proxy < Base
3
+ attr_reader :adapter
4
+
5
+ def initialize(adapter, options = {})
6
+ @adapter = adapter
7
+ end
8
+
9
+ # Exists the value with key
10
+ #
11
+ # @param [Object] key
12
+ # @return [Boolean]
13
+ # @param [Hash] options
14
+ # @api public
15
+ def key?(key, options = {})
16
+ @adapter.key?(key, options)
17
+ end
18
+
19
+ # Fetch value with key. Return nil if the key doesn't exist
20
+ #
21
+ # @param [Object] key
22
+ # @param [Hash] options
23
+ # @return [Object] value
24
+ # @api public
25
+ def load(key, options = {})
26
+ @adapter.load(key, options)
27
+ end
28
+
29
+ # Store value with key
30
+ #
31
+ # @param [Object] key
32
+ # @param [Object] value
33
+ # @param [Hash] options
34
+ # @return value
35
+ # @api public
36
+ def store(key, value, options = {})
37
+ @adapter.store(key, value, options)
38
+ end
39
+
40
+ # Delete the key from the store and return the current value
41
+ #
42
+ # @param [Object] key
43
+ # @return [Object] current value
44
+ # @param [Hash] options
45
+ # @api public
46
+ def delete(key, options = {})
47
+ @adapter.delete(key, options)
48
+ end
49
+
50
+ # Clear all keys in this store
51
+ #
52
+ # @param [Hash] options
53
+ # @return [void]
54
+ # @api public
55
+ def clear(options = {})
56
+ @adapter.clear(options)
57
+ self
58
+ end
59
+
60
+ def close
61
+ @adapter.close
62
+ end
63
+ end
5
64
  end
data/lib/juno/stack.rb CHANGED
@@ -1,40 +1,56 @@
1
1
  module Juno
2
2
  class Stack < Base
3
- def initialize(options = {})
4
- raise 'No option :stores specified' unless @stores = options[:stores]
3
+ class DSL
4
+ attr_reader :stack
5
+
6
+ def initialize(options, &block)
7
+ @stack = options[:stack].to_a
8
+ instance_eval(&block)
9
+ end
10
+
11
+ def add(options = {}, &block)
12
+ @stack << (Hash === options ? Juno.build(options, &block) : options)
13
+ nil
14
+ end
15
+ end
16
+
17
+ attr_reader :stack
18
+
19
+ def initialize(options = {}, &block)
20
+ @stack = DSL.new(options, &block).stack
5
21
  end
6
22
 
7
23
  def key?(key, options = {})
8
- @stores.any? {|s| s.key?(key) }
24
+ @stack.any? {|s| s.key?(key) }
9
25
  end
10
26
 
11
- def [](key)
12
- @stores.each do |s|
13
- value = s[key]
27
+ def load(key, options = {})
28
+ @stack.each do |s|
29
+ value = s.load(key, options)
14
30
  return value if value
15
31
  end
16
32
  nil
17
33
  end
18
34
 
19
35
  def store(key, value, options = {})
20
- @stores.each {|s| s.store(key, value, options) }
36
+ @stack.each {|s| s.store(key, value, options) }
21
37
  value
22
38
  end
23
39
 
24
40
  def delete(key, options = {})
25
- @stores.inject(nil) do |value, s|
41
+ @stack.inject(nil) do |value, s|
26
42
  v = s.delete(key, options)
27
43
  value || v
28
44
  end
29
45
  end
30
46
 
31
47
  def clear(options = {})
32
- @stores.each {|s| s.clear }
33
- nil
48
+ @stack.each {|s| s.clear }
49
+ self
34
50
  end
35
51
 
36
52
  def close
37
- @stores.each {|s| s.close }
53
+ @stack.each {|s| s.close }
38
54
  nil
39
55
  end
40
56
  end
@@ -0,0 +1,106 @@
1
+ module Juno
2
+ class Transformer < Proxy
3
+ @classes = {}
4
+
5
+ class << self
6
+ alias_method :original_new, :new
7
+ end
8
+
9
+ VALUE_TRANSFORMER = {
10
+ :marshal => { :load => '::Marshal.load(VALUE)', :dump => '::Marshal.dump(VALUE)' },
11
+ :base64 => { :load => "VALUE.unpack('m').first", :dump => "[VALUE].pack('m').strip" },
12
+ :json => { :load => '::MultiJson.load(VALUE).first', :dump => '::MultiJson.dump([VALUE])', :require => 'multi_json' },
13
+ :yaml => { :load => '::YAML.load(VALUE)', :dump => '::YAML.dump(VALUE)', :require => 'yaml' },
14
+ #:tnet => { :load => '::TNetstring.parse(VALUE)', :dump => '::TNetstring.dump(VALUE)', :require => 'tnetstring' },
15
+ :msgpack => { :load => '::MessagePack.unpack(VALUE)', :dump => '::MessagePack.pack(VALUE)', :require => 'msgpack' },
16
+ :bson => { :load => '::BSON.deserialize(VALUE)["v"]', :dump => '::BSON.serialize({"v"=>VALUE})', :require => 'bson' },
17
+ }
18
+
19
+ KEY_TRANSFORMER = {
20
+ :base64 => { :transform => "[KEY].pack('m').strip" },
21
+ :spread => { :transform => '(TMP = KEY; ::File.join(TMP[0..1], TMP[2..-1]))' },
22
+ :escape => { :transform => "KEY.gsub(/[^a-zA-Z0-9_-]+/) { '%%' + $&.unpack('H2' * $&.bytesize).join('%%').upcase }" },
23
+ :md5 => { :transform => '::Digest::MD5.hexdigest(KEY)', :require => 'digest/md5' },
24
+ :json => { :transform => '(TMP = KEY; String === TMP ? TMP : ::MultiJson.dump(TMP))', :require => 'multi_json' },
25
+ :bson => { :transform => '(TMP = KEY; String === TMP ? TMP : ::BSON.serialize({"k"=>TMP}).to_s)', :require => 'bson' },
26
+ :yaml => { :transform => '(TMP = KEY; String === TMP ? TMP : ::YAML.dump(TMP))', :require => 'yaml' },
27
+ :marshal => { :transform => '(TMP = KEY; String === TMP ? TMP : ::Marshal.dump(TMP))' },
28
+ #:tnet => { :transform => '(TMP = KEY; String === TMP ? TMP : ::TNetstring.dump(TMP))', :require => 'tnetstring' },
29
+ :msgpack => { :transform => '(TMP = KEY; String === TMP ? TMP : ::MessagePack.pack(TMP))', :require => 'msgpack' },
30
+ }
31
+
32
+ class << self
33
+ def compile(keys, values)
34
+ tmp, key = 0, 'key'
35
+ keys.each do |tn|
36
+ raise "Unknown key transformer #{tn}" unless t = KEY_TRANSFORMER[tn]
37
+ require t[:require] if t[:require]
38
+ key = t[:transform].gsub('KEY', key).gsub('TMP', "x#{tmp}")
39
+ tmp += 1
40
+ end
41
+
42
+ dumper = 'value'
43
+ values.each do |tn|
44
+ raise "Unknown value transformer #{tn}" unless t = VALUE_TRANSFORMER[tn]
45
+ require t[:require] if t[:require]
46
+ dumper = t[:dump].gsub('VALUE', dumper)
47
+ end
48
+
49
+ loader = 'value'
50
+ values.reverse.each do |t|
51
+ loader = VALUE_TRANSFORMER[t][:load].gsub('VALUE', loader)
52
+ end
53
+
54
+ klass = Class.new(Transformer)
55
+ if loader == 'value'
56
+ klass.class_eval <<-end_eval, __FILE__, __LINE__
57
+ def key?(key, options = {})
58
+ @adapter.key?(#{key}, options)
59
+ end
60
+
61
+ def load(key, options = {})
62
+ @adapter.load(#{key}, options)
63
+ end
64
+
65
+ def store(key, value, options = {})
66
+ @adapter.store(#{key}, value, options)
67
+ end
68
+
69
+ def delete(key, options = {})
70
+ @adapter.delete(#{key}, options)
71
+ end
72
+ end_eval
73
+ else
74
+ klass.class_eval <<-end_eval, __FILE__, __LINE__
75
+ def key?(key, options = {})
76
+ @adapter.key?(#{key}, options)
77
+ end
78
+
79
+ def load(key, options = {})
80
+ value = @adapter.load(#{key}, options)
81
+ value && #{loader}
82
+ end
83
+
84
+ def store(key, value, options = {})
85
+ @adapter.store(#{key}, #{dumper}, options)
86
+ value
87
+ end
88
+
89
+ def delete(key, options = {})
90
+ value = @adapter.delete(#{key}, options)
91
+ value && #{loader}
92
+ end
93
+ end_eval
94
+ end
95
+ klass
96
+ end
97
+
98
+ def new(store, options = {})
99
+ keys = [options[:key]].flatten.compact
100
+ values = [options[:value]].flatten.compact
101
+ klass = @classes["#{keys.join('-')}+#{values.join('-')}"] ||= compile(keys, values)
102
+ klass.original_new(store, options)
103
+ end
104
+ end
105
+ end
106
+ end
data/lib/juno/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Juno
2
- VERSION = '0.1.1'
2
+ VERSION = '0.2.0'
3
3
  end
data/lib/juno.rb CHANGED
@@ -1,31 +1,83 @@
1
1
  module Juno
2
- autoload :ActiveRecord, 'juno/activerecord'
3
- autoload :Base, 'juno/base'
4
- autoload :Cassandra, 'juno/cassandra'
5
- autoload :Couch, 'juno/couch'
6
- autoload :DataMapper, 'juno/datamapper'
7
- autoload :DBM, 'juno/dbm'
8
- autoload :Expires, 'juno/expires'
9
- autoload :File, 'juno/file'
10
- autoload :Fog, 'juno/fog'
11
- autoload :GDBM, 'juno/gdbm'
12
- autoload :HashFile, 'juno/hashfile'
13
- autoload :LocalMemCache, 'juno/localmemcache'
14
- autoload :Memcached, 'juno/memcached'
15
- autoload :MemcachedDalli, 'juno/memcached_dalli'
16
- autoload :MemcachedNative, 'juno/memcached_native'
17
- autoload :Memory, 'juno/memory'
18
- autoload :MongoDB, 'juno/mongodb'
19
- autoload :Null, 'juno/null'
20
- autoload :Proxy, 'juno/proxy'
21
- autoload :PStore, 'juno/pstore'
22
- autoload :Redis, 'juno/redis'
23
- autoload :Riak, 'juno/riak'
24
- autoload :SDBM, 'juno/sdbm'
25
- autoload :Sequel, 'juno/sequel'
26
- autoload :Stack, 'juno/stack'
27
- autoload :Sqlite, 'juno/sqlite'
28
- autoload :TokyoCabinet, 'juno/tokyocabinet'
29
- #autoload :TokyoTyrant, 'juno/tokyotyrant'
30
- autoload :YAML, 'juno/yaml'
2
+ autoload :Base, 'juno/base'
3
+ autoload :Builder, 'juno/builder'
4
+ autoload :Cache, 'juno/cache'
5
+ autoload :Expires, 'juno/expires'
6
+ autoload :Proxy, 'juno/proxy'
7
+ autoload :Stack, 'juno/stack'
8
+ autoload :Transformer, 'juno/transformer'
9
+
10
+ module Adapters
11
+ autoload :ActiveRecord, 'juno/adapters/activerecord'
12
+ autoload :Cassandra, 'juno/adapters/cassandra'
13
+ autoload :Couch, 'juno/adapters/couch'
14
+ autoload :DataMapper, 'juno/adapters/datamapper'
15
+ autoload :DBM, 'juno/adapters/dbm'
16
+ autoload :File, 'juno/adapters/file'
17
+ autoload :Fog, 'juno/adapters/fog'
18
+ autoload :GDBM, 'juno/adapters/gdbm'
19
+ autoload :LocalMemCache, 'juno/adapters/localmemcache'
20
+ autoload :Memcached, 'juno/adapters/memcached'
21
+ autoload :MemcachedDalli, 'juno/adapters/memcached_dalli'
22
+ autoload :MemcachedNative, 'juno/adapters/memcached_native'
23
+ autoload :Memory, 'juno/adapters/memory'
24
+ autoload :Mongo, 'juno/adapters/mongo'
25
+ autoload :Null, 'juno/adapters/null'
26
+ autoload :PStore, 'juno/adapters/pstore'
27
+ autoload :Redis, 'juno/adapters/redis'
28
+ autoload :Riak, 'juno/adapters/riak'
29
+ autoload :SDBM, 'juno/adapters/sdbm'
30
+ autoload :Sequel, 'juno/adapters/sequel'
31
+ autoload :Sqlite, 'juno/adapters/sqlite'
32
+ autoload :TokyoCabinet, 'juno/adapters/tokyocabinet'
33
+ autoload :YAML, 'juno/adapters/yaml'
34
+ end
35
+
36
+ def self.new(name, options = {})
37
+ raise 'Name must be Symbol' unless Symbol === name
38
+ case name
39
+ when :Sequel, :ActiveRecord, :Couch
40
+ # Sequel accept only base64 keys and values
41
+ # FIXME: ActiveRecord and Couch should work only with :marshal but this
42
+ # raises an error on 1.9
43
+ build(options) do
44
+ use :Transformer, :key => [:marshal, :base64], :value => [:marshal, :base64]
45
+ adapter name
46
+ end
47
+ when :Memcached, :MemcachedDalli, :MemcachedNative
48
+ # Memcached accept only base64 keys
49
+ build(options) do
50
+ use :Transformer, :key => [:marshal, :base64], :value => :marshal
51
+ adapter name
52
+ end
53
+ when :PStore, :YAML, :DataMapper, :Null
54
+ # For PStore, YAML and DataMapper only the key has to be a string
55
+ build(options) do
56
+ use :Transformer, :key => :marshal
57
+ adapter name
58
+ end
59
+ when :HashFile
60
+ # Use spreading hashes
61
+ build(options) do
62
+ use :Transformer, :key => [:marshal, :md5, :spread], :value => :marshal
63
+ adapter :File
64
+ end
65
+ when :File
66
+ # Use escaping
67
+ build(options) do
68
+ use :Transformer, :key => [:marshal, :escape], :value => :marshal
69
+ adapter :File
70
+ end
71
+ else
72
+ # For all other stores marshal key and value
73
+ build(options) do
74
+ use :Transformer, :key => :marshal, :value => :marshal
75
+ adapter name
76
+ end
77
+ end
78
+ end
79
+
80
+ def self.build(options = {}, &block)
81
+ Builder.new(options, &block).build
82
+ end
31
83
  end
@@ -0,0 +1,41 @@
1
+ # Generated file
2
+ require 'helper'
3
+
4
+ begin
5
+ Juno::Adapters::ActiveRecord.new(:connection => { :adapter => (defined?(JRUBY_VERSION) ? 'jdbcsqlite3' : 'sqlite3'), :database => File.join(make_tempdir, 'adapter_activerecord.sqlite3') }).close
6
+
7
+ describe "adapter_activerecord" do
8
+ before do
9
+ @store = Juno::Adapters::ActiveRecord.new(:connection => { :adapter => (defined?(JRUBY_VERSION) ? 'jdbcsqlite3' : 'sqlite3'), :database => File.join(make_tempdir, 'adapter_activerecord.sqlite3') })
10
+ @store.clear
11
+ end
12
+
13
+ after do
14
+ @store.close.should == nil if @store
15
+ end
16
+
17
+ it_should_behave_like 'null_stringkey_stringvalue'
18
+ it_should_behave_like 'store_stringkey_stringvalue'
19
+ it_should_behave_like 'returndifferent_stringkey_stringvalue'
20
+
21
+ it 'updates an existing key/value' do
22
+ @store['foo/bar'] = '1'
23
+ @store['foo/bar'] = '2'
24
+ records = @store.table.find :all, :conditions => { :key => 'foo/bar' }
25
+ records.count.should == 1
26
+ end
27
+
28
+ it 'uses an existing connection' do
29
+ ActiveRecord::Base.establish_connection :adapter => (defined?(JRUBY_VERSION) ? 'jdbcsqlite3' : 'sqlite3'), :database => File.join(make_tempdir, 'activerecord-existing.sqlite3')
30
+
31
+ store = Juno::Adapters::ActiveRecord.new
32
+ store.table.table_exists?.should == true
33
+ end
34
+
35
+ end
36
+ rescue LoadError => ex
37
+ puts "Test adapter_activerecord not executed: #{ex.message}"
38
+ rescue Exception => ex
39
+ puts "Test adapter_activerecord not executed: #{ex.message}"
40
+ #puts "#{ex.backtrace.join("\n")}"
41
+ end
@@ -0,0 +1,27 @@
1
+ # Generated file
2
+ require 'helper'
3
+
4
+ begin
5
+ Juno::Adapters::Cassandra.new.close
6
+
7
+ describe "adapter_cassandra" do
8
+ before do
9
+ @store = Juno::Adapters::Cassandra.new
10
+ @store.clear
11
+ end
12
+
13
+ after do
14
+ @store.close.should == nil if @store
15
+ end
16
+
17
+ it_should_behave_like 'null_stringkey_stringvalue'
18
+ it_should_behave_like 'store_stringkey_stringvalue'
19
+ it_should_behave_like 'returndifferent_stringkey_stringvalue'
20
+
21
+ end
22
+ rescue LoadError => ex
23
+ puts "Test adapter_cassandra not executed: #{ex.message}"
24
+ rescue Exception => ex
25
+ puts "Test adapter_cassandra not executed: #{ex.message}"
26
+ #puts "#{ex.backtrace.join("\n")}"
27
+ end
@@ -0,0 +1,27 @@
1
+ # Generated file
2
+ require 'helper'
3
+
4
+ begin
5
+ Juno::Adapters::Couch.new(:db => 'adapter_couch').close
6
+
7
+ describe "adapter_couch" do
8
+ before do
9
+ @store = Juno::Adapters::Couch.new(:db => 'adapter_couch')
10
+ @store.clear
11
+ end
12
+
13
+ after do
14
+ @store.close.should == nil if @store
15
+ end
16
+
17
+ it_should_behave_like 'null_stringkey_stringvalue'
18
+ it_should_behave_like 'store_stringkey_stringvalue'
19
+ it_should_behave_like 'returndifferent_stringkey_stringvalue'
20
+
21
+ end
22
+ rescue LoadError => ex
23
+ puts "Test adapter_couch not executed: #{ex.message}"
24
+ rescue Exception => ex
25
+ puts "Test adapter_couch not executed: #{ex.message}"
26
+ #puts "#{ex.backtrace.join("\n")}"
27
+ end
@@ -0,0 +1,61 @@
1
+ # Generated file
2
+ require 'helper'
3
+
4
+ begin
5
+ require 'dm-core'
6
+ DataMapper.setup(:default, :adapter => :in_memory)
7
+ Juno::Adapters::DataMapper.new(:setup => "sqlite3://#{make_tempdir}/adapter_datamapper.sqlite3").close
8
+
9
+ describe "adapter_datamapper" do
10
+ before do
11
+ @store = Juno::Adapters::DataMapper.new(:setup => "sqlite3://#{make_tempdir}/adapter_datamapper.sqlite3")
12
+ @store.clear
13
+ end
14
+
15
+ after do
16
+ @store.close.should == nil if @store
17
+ end
18
+
19
+ it_should_behave_like 'null_stringkey_stringvalue'
20
+ it_should_behave_like 'store_stringkey_stringvalue'
21
+ it_should_behave_like 'returndifferent_stringkey_stringvalue'
22
+ it_should_behave_like 'returndifferent_stringkey_objectvalue'
23
+ it_should_behave_like 'null_stringkey_objectvalue'
24
+ it_should_behave_like 'store_stringkey_objectvalue'
25
+
26
+ it 'does not cross contaminate when storing' do
27
+ first = Juno::Adapters::DataMapper.new(:setup => "sqlite3://#{make_tempdir}/datamapper-first.sqlite3")
28
+ first.clear
29
+
30
+ second = Juno::Adapters::DataMapper.new(:repository => :sample, :setup => "sqlite3://#{make_tempdir}/datamapper-second.sqlite3")
31
+ second.clear
32
+
33
+ first['key'] = 'value'
34
+ second['key'] = 'value2'
35
+
36
+ first['key'].should == 'value'
37
+ second['key'].should == 'value2'
38
+ end
39
+
40
+ it 'does not cross contaminate when deleting' do
41
+ first = Juno::Adapters::DataMapper.new(:setup => "sqlite3://#{make_tempdir}/datamapper-first.sqlite3")
42
+ first.clear
43
+
44
+ second = Juno::Adapters::DataMapper.new(:repository => :sample, :setup => "sqlite3://#{make_tempdir}/datamapper-second.sqlite3")
45
+ second.clear
46
+
47
+ first['key'] = 'value'
48
+ second['key'] = 'value2'
49
+
50
+ first.delete('key').should == 'value'
51
+ first.key?('key').should == false
52
+ second['key'].should == 'value2'
53
+ end
54
+
55
+ end
56
+ rescue LoadError => ex
57
+ puts "Test adapter_datamapper not executed: #{ex.message}"
58
+ rescue Exception => ex
59
+ puts "Test adapter_datamapper not executed: #{ex.message}"
60
+ #puts "#{ex.backtrace.join("\n")}"
61
+ end
@@ -0,0 +1,27 @@
1
+ # Generated file
2
+ require 'helper'
3
+
4
+ begin
5
+ Juno::Adapters::DBM.new(:file => File.join(make_tempdir, "adapter_dbm")).close
6
+
7
+ describe "adapter_dbm" do
8
+ before do
9
+ @store = Juno::Adapters::DBM.new(:file => File.join(make_tempdir, "adapter_dbm"))
10
+ @store.clear
11
+ end
12
+
13
+ after do
14
+ @store.close.should == nil if @store
15
+ end
16
+
17
+ it_should_behave_like 'null_stringkey_stringvalue'
18
+ it_should_behave_like 'store_stringkey_stringvalue'
19
+ it_should_behave_like 'returndifferent_stringkey_stringvalue'
20
+
21
+ end
22
+ rescue LoadError => ex
23
+ puts "Test adapter_dbm not executed: #{ex.message}"
24
+ rescue Exception => ex
25
+ puts "Test adapter_dbm not executed: #{ex.message}"
26
+ #puts "#{ex.backtrace.join("\n")}"
27
+ end