redis_object 0.5.0 → 1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. data/.gitignore +0 -2
  2. data/Gemfile +0 -4
  3. data/README.markdown +15 -24
  4. data/Rakefile +0 -8
  5. data/doc/Object.html +185 -0
  6. data/doc/Seabright.html +181 -0
  7. data/doc/Seabright/Adapter.html +442 -0
  8. data/doc/Seabright/Collection.html +797 -0
  9. data/doc/Seabright/Collections.html +635 -0
  10. data/doc/Seabright/Collections/ClassMethods.html +212 -0
  11. data/doc/Seabright/ExternalIndex.html +217 -0
  12. data/doc/Seabright/History.html +382 -0
  13. data/doc/Seabright/History/ClassMethods.html +276 -0
  14. data/doc/Seabright/Indices.html +324 -0
  15. data/doc/Seabright/Indices/ClassMethods.html +348 -0
  16. data/doc/Seabright/Keys.html +314 -0
  17. data/doc/Seabright/Keys/ClassMethods.html +276 -0
  18. data/doc/Seabright/ObjectBase.html +852 -0
  19. data/doc/Seabright/ObjectBase/ClassMethods.html +677 -0
  20. data/doc/Seabright/RedisObject.html +230 -0
  21. data/doc/Seabright/References.html +280 -0
  22. data/doc/Seabright/Storage.html +252 -0
  23. data/doc/Seabright/Storage/ClassMethods.html +276 -0
  24. data/doc/Seabright/Storage/MySQL.html +442 -0
  25. data/doc/Seabright/Storage/Redis.html +218 -0
  26. data/doc/Seabright/Template.html +212 -0
  27. data/doc/Seabright/Template/ClassMethods.html +166 -0
  28. data/doc/Seabright/Timestamps.html +292 -0
  29. data/doc/Seabright/Timestamps/ClassMethods.html +214 -0
  30. data/doc/Seabright/Types.html +410 -0
  31. data/doc/Seabright/Types/ClassMethods.html +308 -0
  32. data/doc/created.rid +17 -0
  33. data/doc/images/add.png +0 -0
  34. data/doc/images/brick.png +0 -0
  35. data/doc/images/brick_link.png +0 -0
  36. data/doc/images/bug.png +0 -0
  37. data/doc/images/bullet_black.png +0 -0
  38. data/doc/images/bullet_toggle_minus.png +0 -0
  39. data/doc/images/bullet_toggle_plus.png +0 -0
  40. data/doc/images/date.png +0 -0
  41. data/doc/images/delete.png +0 -0
  42. data/doc/images/find.png +0 -0
  43. data/doc/images/loadingAnimation.gif +0 -0
  44. data/doc/images/macFFBgHack.png +0 -0
  45. data/doc/images/package.png +0 -0
  46. data/doc/images/page_green.png +0 -0
  47. data/doc/images/page_white_text.png +0 -0
  48. data/doc/images/page_white_width.png +0 -0
  49. data/doc/images/plugin.png +0 -0
  50. data/doc/images/ruby.png +0 -0
  51. data/doc/images/tag_blue.png +0 -0
  52. data/doc/images/tag_green.png +0 -0
  53. data/doc/images/transparent.png +0 -0
  54. data/doc/images/wrench.png +0 -0
  55. data/doc/images/wrench_orange.png +0 -0
  56. data/doc/images/zoom.png +0 -0
  57. data/doc/index.html +125 -0
  58. data/doc/js/darkfish.js +153 -0
  59. data/doc/js/jquery.js +18 -0
  60. data/doc/js/navigation.js +142 -0
  61. data/doc/js/search.js +94 -0
  62. data/doc/js/search_index.js +1 -0
  63. data/doc/js/searcher.js +228 -0
  64. data/doc/rdoc.css +543 -0
  65. data/doc/table_of_contents.html +394 -0
  66. data/lib/redis_object.rb +1 -11
  67. data/lib/redis_object/base.rb +60 -210
  68. data/lib/redis_object/collection.rb +100 -130
  69. data/lib/redis_object/defaults.rb +8 -21
  70. data/lib/redis_object/ext/filters.rb +16 -34
  71. data/lib/redis_object/ext/triggers.rb +13 -75
  72. data/lib/redis_object/{experimental/history.rb → history.rb} +0 -0
  73. data/lib/redis_object/indices.rb +39 -44
  74. data/lib/redis_object/keys.rb +4 -4
  75. data/lib/redis_object/storage.rb +1 -30
  76. data/lib/redis_object/storage/adapter.rb +3 -6
  77. data/lib/redis_object/storage/redis.rb +3 -98
  78. data/lib/redis_object/timestamps.rb +21 -42
  79. data/lib/redis_object/types.rb +30 -172
  80. data/lib/redis_object/version.rb +1 -1
  81. data/redis_object.gemspec +0 -1
  82. data/spec/base_spec.rb +6 -41
  83. data/spec/spec_helper.rb +1 -32
  84. metadata +116 -111
  85. data/.coveralls.yml +0 -1
  86. data/.travis.yml +0 -5
  87. data/lib/redis_object/ext/script_cache.rb +0 -92
  88. data/lib/redis_object/ext/shardable.rb +0 -18
  89. data/lib/redis_object/ext/view_caching.rb +0 -258
  90. data/lib/redis_object/ext/views.rb +0 -102
  91. data/lib/redis_object/inheritance_tracking.rb +0 -23
  92. data/spec/adapter_spec.rb +0 -43
  93. data/spec/benchmark_spec.rb +0 -46
  94. data/spec/collections_spec.rb +0 -144
  95. data/spec/defaults_spec.rb +0 -56
  96. data/spec/filters_spec.rb +0 -29
  97. data/spec/indices_spec.rb +0 -45
  98. data/spec/rename_class_spec.rb +0 -96
  99. data/spec/timestamp_spec.rb +0 -28
  100. data/spec/trigger_spec.rb +0 -51
  101. data/spec/types_spec.rb +0 -103
  102. data/spec/view_caching_spec.rb +0 -130
  103. data/spec/views_spec.rb +0 -72
@@ -1 +0,0 @@
1
- repo_token: 8vq1j1WGB56M8h1zI6TeuK7x3HVJ1K8l4
@@ -1,5 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - 1.9.3
4
- env:
5
- - "TEST_DB=14"
@@ -1,92 +0,0 @@
1
- $ScriptSHAMap = {}
2
-
3
- module Seabright
4
-
5
- class RedisObject
6
- module ScriptSources; end
7
- end
8
-
9
- module CachedScripts
10
-
11
- def run_script(name,keys=[],args=[],source=nil)
12
- self.class.run_script(name,keys,args,source,store)
13
- end
14
-
15
- module ClassMethods
16
-
17
- NoScriptError = "NOSCRIPT No matching script. Please use EVAL.".freeze
18
-
19
- def run_script(name,keys=[],args=[],source=nil,stor=nil)
20
- @tmp_store = stor if stor
21
- @rescue_recurse ||= 0
22
- begin
23
- out = (@tmp_store || store).evalsha(get_script_sha(name,source),keys,args)
24
- rescue Redis::CommandError => e
25
- if e.message == NoScriptError && @rescue_recurse < 3
26
- puts "Rescuing NOSCRIPT error for #{name} - running again..." if DEBUG
27
- untrack_script name
28
- @rescue_recurse += 1
29
- out = (@tmp_store || store).evalsha(get_script_sha(name,source),keys,args)
30
- else
31
- @rescue_recurse = 0
32
- raise e
33
- end
34
- end
35
- @rescue_recurse = 0
36
- remove_instance_variable(:@tmp_store) if @tmp_store
37
- out
38
- end
39
-
40
- def get_script_sha(name,source=nil)
41
- $ScriptSHAMap[name] ||= (script_sha_from_key(name) || store_script(name,source))
42
- end
43
-
44
- def script_sha_from_key(name)
45
- (@tmp_store || store).get(script_sha_key(name))
46
- end
47
-
48
- class SourceNotFoundError < RuntimeError
49
- def initialize
50
- super("Could not locate script source")
51
- end
52
- end
53
-
54
- def store_script(name,source=nil)
55
- source ||= script_source_from_const(name)
56
- raise SourceNotFoundError unless source
57
- sha = (@tmp_store || store).script(:load,source)
58
- (@tmp_store || store).set(script_sha_key(name),sha)
59
- sha
60
- end
61
-
62
- def untrack_script(name)
63
- ScriptSHAMap.delete name
64
- (@tmp_store || store).del(script_sha_key(name))
65
- end
66
-
67
- def script_source_from_const(name)
68
- (self.const_defined?(name.to_sym) && self.const_get(name.to_sym)) || (RedisObject::ScriptSources.const_defined?(name.to_sym) && RedisObject::ScriptSources.const_get(name.to_sym)) || nil
69
- end
70
-
71
- SCRIPT_KEY_PREFIX = "ScriptCache::SHA::".freeze
72
-
73
- def expire_all_script_shas(store_name=nil)
74
- store_obj = store_name.is_a?(String) || store_name.is_a?(Symbol) ? store(store_name.to_sym) : store_name
75
- store_obj.keys(script_sha_key("*")).each do |k|
76
- store_obj.del k
77
- end
78
- end
79
-
80
- def script_sha_key(name)
81
- "#{SCRIPT_KEY_PREFIX}#{name.to_s}"
82
- end
83
-
84
- end
85
-
86
- def self.included(base)
87
- base.extend(ClassMethods)
88
- end
89
-
90
- end
91
-
92
- end
@@ -1,18 +0,0 @@
1
- module Seabright
2
- module Shardable
3
-
4
- # Intention is to override any methods needed so that the underlying data can be safely sharded
5
-
6
- module ClassMethods
7
-
8
- # same here
9
-
10
- end
11
-
12
- def self.included(base)
13
- base.extend(ClassMethods)
14
- end
15
-
16
- end
17
- RedisObject.send(:include,Shardable)
18
- end
@@ -1,258 +0,0 @@
1
- # View Caching
2
- #
3
- # Cache a named view:
4
- # cache_named_view :admin_view
5
- #
6
- # Invalidate all cached views when the I receive notification that something I reference or have been referenced by has changed:
7
- # invalidate_caches_from_upstream_updates!
8
- #
9
- # Notify some objects that reference me when I am updated: (objects of these classes)
10
- # invalidate_upstream Property, Application, PaymentRequest, PaymentResponse
11
- #
12
- # Notify some objects in my collections when I am updated: (objects in these collections)
13
- # invalidate_downstream :properties, :applications, :payment_requests, :payment_responses
14
- #
15
- # You can also set up hooks for when this object is updated by certain types of objects by defining the following:
16
- # def invalidated_by(obj,chain)
17
- # invalidate_cached_view :blah
18
- # end
19
- #
20
- # def invalidated_by_user(obj,chain)
21
- # invalidate_cached_view :users
22
- # end
23
- #
24
-
25
- module Seabright
26
- module ViewCaching
27
-
28
- CachedViewInvalidator = "
29
- for i=1,#ARGV do
30
- redis.call('HDEL', KEYS[1], ARGV[i])
31
- end".gsub(/\t/,'').freeze
32
-
33
- module ClassMethods
34
-
35
- def cache_view(name,opts=true)
36
- cached_views[name.to_sym] = opts
37
- intercept_views_for_caching!
38
- set_up_invalidation!
39
- end
40
- alias_method :cache_named_view, :cache_view
41
-
42
- def intercept_views_for_caching!
43
- return if @cached_views_intercepted
44
- self.class_eval do
45
-
46
- alias_method :uncached_view_as_hash, :view_as_hash unless method_defined?(:uncached_view_as_hash)
47
- def view_as_hash(name)
48
- return uncached_view_as_hash(name) unless self.class.view_should_be_cached?(name)
49
- if v = view_from_cache(name)
50
- puts " Got view from cache: #{name}" if DEBUG
51
- Yajl::Parser.parse(v)
52
- else
53
- puts " View cache miss: #{name}" if DEBUG
54
- cache_view_content(name)[0]
55
- end
56
- end
57
-
58
- alias_method :uncached_view_as_json, :view_as_json unless method_defined?(:uncached_view_as_json)
59
- def view_as_json(name)
60
- return uncached_view_as_json(name) unless self.class.view_should_be_cached?(name)
61
- if v = view_from_cache(name)
62
- puts " Got view from cache: #{name}" if DEBUG
63
- v
64
- else
65
- puts " View cache miss: #{name}" if DEBUG
66
- cache_view_content(name)[1]
67
- end
68
- end
69
-
70
- def cache_view_content(name,content=nil)
71
- content ||= uncached_view_as_hash(name)
72
- json = Yajl::Encoder.encode(content)
73
- store.hset(cached_view_key,name,json)
74
- [content,json]
75
- end
76
-
77
- def view_from_cache(name)
78
- if v = store.hget(cached_view_key,name)
79
- v
80
- else
81
- nil
82
- end
83
- end
84
-
85
- def view_is_cached?(name)
86
- store.hexists(cached_view_key, name)
87
- end
88
-
89
- def cached_view_key
90
- "#{hkey}::ViewCache"
91
- end
92
-
93
- def regenerate_cached_views(*names)
94
- names.each do |name|
95
- cache_view_content name
96
- end
97
- end
98
-
99
- def regenerate_cached_views!
100
- regenerate_cached_views(*self.class.cached_views.map {|name,opts| name })
101
- end
102
-
103
- end
104
- @cached_views_intercepted = true
105
- end
106
-
107
- def set_up_invalidation!
108
- return if @invalidation_set_up
109
- self.class_eval do
110
-
111
- def invalidate_cached_views(*names)
112
- puts "Invalidating cached views: #{names.join(", ")}" if Debug.verbose?
113
- run_script(:CachedViewInvalidator, [cached_view_key], names, CachedViewInvalidator)
114
- self.class.cache_invalidation_hooks do |hook|
115
- hook.call(names)
116
- end
117
- end
118
- alias_method :invalidate_cached_view, :invalidate_cached_views
119
-
120
- def invalidate_cached_views!
121
- invalidate_cached_views(*self.class.cached_views.map {|name,opts| name })
122
- end
123
-
124
- def invalidate_downstream!
125
- return unless self.class.downstream_invalidations && (self.class.downstream_invalidations.size > 0)
126
- puts "Invalidating downstream: #{self.class.downstream_invalidations.inspect}" if Debug.verbose?
127
- self.class.downstream_invalidations.each do |col|
128
- if has_collection?(col) && (colctn = get_collection(col))
129
- colctn.each do |obj|
130
- obj.invalidated_by_other(self,invalidation_chain + [self.hkey])
131
- end
132
- end
133
- end
134
- end
135
-
136
- def invalidate_upstream!
137
- return unless self.class.upstream_invalidations && (self.class.upstream_invalidations.size > 0)
138
- puts "Invalidating upstream: #{self.class.upstream_invalidations.inspect}" if Debug.verbose?
139
- backreferences.each do |obj|
140
- next unless self.class.upstream_invalidations.include?(obj.class.name.split("::").last.to_sym) #|| self.class.invalidate_everything_upstream?
141
- obj.invalidated_by_other(self,invalidation_chain + [self.hkey]) if obj.respond_to?(:invalidated_by_other)
142
- end
143
- end
144
-
145
- def invalidated_by_update!(*args)
146
- Thread.new do
147
- invalidate_cached_views!
148
- invalidate_up_and_down!
149
- end
150
- end
151
-
152
- def invalidated_by_reference!(*args)
153
- invalidated_by_update!
154
- end
155
-
156
- def invalidation_chain
157
- @invalidation_chain ||= []
158
- end
159
-
160
- def invalidate_up_and_down!
161
- unless invalidation_chain.include?(self)
162
- invalidate_downstream!
163
- invalidate_upstream!
164
- end
165
- end
166
-
167
- def invalidated_by_other(obj,chain)
168
- unless chain.include?(self.hkey)
169
- puts "#{self.class.name}:#{self.id}'s view caches were invalidated by upstream object: #{obj.class.name}:#{obj.id} (chain:#{chain.inspect})" if Debug.verbose?
170
- @invalidation_chain = chain
171
- [:invalidated_by,"invalidated_by_#{obj.class.name.underscore}".to_sym].each do |meth_sym|
172
- send(meth_sym,obj,chain) if respond_to?(meth_sym)
173
- end
174
- invalidate_up_and_down!
175
- end
176
- end
177
-
178
- trigger_on_update :invalidated_by_update!
179
- trigger_on_reference :invalidated_by_reference!
180
-
181
- end
182
- @invalidation_set_up = true
183
- end
184
-
185
- def invalidate_caches_from_upstream_updates!
186
- self.class_eval do
187
-
188
- def invalidated_by(obj,chain)
189
- invalidate_cached_views!
190
- end
191
-
192
- end
193
- end
194
-
195
- def on_cache_invalidation(&block)
196
- cache_invalidation_hooks << block
197
- end
198
-
199
- def cache_invalidation_hooks
200
- @cache_invalidation_hooks ||= []
201
- end
202
-
203
- def invalidate_upstream(*args)
204
- @upstream_invalidations = (@upstream_invalidations || []) + args
205
- set_up_invalidation!
206
- end
207
-
208
- def upstream_invalidations
209
- @upstream_invalidations ||= []
210
- end
211
-
212
- # def invalidate_everything_upstream!
213
- # @invalidate_everything_upstream = true
214
- # end
215
- #
216
- # def invalidate_everything_upstream?
217
- # @invalidate_everything_upstream
218
- # end
219
-
220
- def invalidate_downstream(*args)
221
- @downstream_invalidations = (@downstream_invalidations || []) + args
222
- set_up_invalidation!
223
- end
224
-
225
- def downstream_invalidations
226
- @downstream_invalidations ||= []
227
- end
228
-
229
- # def invalidate_everything_downstream!
230
- # @invalidate_everything_downstream = true
231
- # end
232
- #
233
- # def invalidate_everything_downstream?
234
- # @invalidate_everything_downstream
235
- # end
236
-
237
- def view_should_be_cached?(name)
238
- !!cached_views[name.to_sym]
239
- end
240
-
241
- def cached_views
242
- @cached_view ||= {}
243
- end
244
-
245
- def cache_named_views!
246
- named_views.each do |name,view|
247
- cache_view name
248
- end
249
- end
250
-
251
- end
252
-
253
- def self.included(base)
254
- base.extend(ClassMethods)
255
- end
256
-
257
- end
258
- end
@@ -1,102 +0,0 @@
1
- module Seabright
2
- module Views
3
-
4
- ViewFieldGetter = "local out = {}
5
- local key
6
- local val
7
- for i=1,#ARGV do
8
- key = ARGV[i]
9
- val = redis.call('HGET',KEYS[1],key)
10
- if val then
11
- table.insert(out,key)
12
- table.insert(out,val)
13
- end
14
- end
15
- return out".gsub(/\t/,'').freeze
16
-
17
- def view_as_hash(name)
18
- out = {}
19
- if requested_set = self.class.named_views[name]
20
- if requested_set.is_a?(Symbol) and self.respond_to?(requested_set)
21
- out = send(requested_set)
22
- else
23
- methods = requested_set[:fields].select {|f| self.respond_to?(f.to_sym) }
24
- if methods.count > 0
25
- methods.each do |m|
26
- out[m.to_s] = send(m.to_sym)
27
- end
28
- end
29
- if requested_set[:fields] && (flds = requested_set[:fields].select {|f| !out.keys.include?(f.to_s) }.map {|f| f.to_s }) && flds.count > 0
30
- res = Hash[*store.eval(ViewFieldGetter, [hkey], flds)]
31
- out.merge!(res)
32
- end
33
- if requested_set[:procs]
34
- requested_set[:procs].each do |k,proc|
35
- out[k.to_s] = proc.call(self)
36
- end
37
- end
38
- if requested_set[:hashes]
39
- requested_set[:hashes].each do |k,v|
40
- case v
41
- when String, Symbol
42
- out[k.to_s] = get(v)
43
- end
44
- end
45
- end
46
- end
47
- end
48
- out
49
- end
50
-
51
- def view_as_json(name)
52
- Yajl::Encoder.encode(view_as_hash(name))
53
- end
54
-
55
- module ClassMethods
56
-
57
- def named_view(name,*fields)
58
- named_views[name] = normalize_field_options(fields)
59
- end
60
-
61
- def named_views
62
- @named_views ||= {}
63
- end
64
-
65
- def normalize_field_options(fields)
66
- fields.flatten!
67
- fields.uniq!
68
-
69
- options = {}
70
- if fields.last.is_a?(Hash) # assume an option hash
71
- options.merge!(fields.slice!(fields.size - 1, 1)[0])
72
- end
73
-
74
- # assign a the method as a symbol to be exclusively invoked on view
75
- # so instead of returning a hash on view, it will return only what was
76
- # produced by calling the method.
77
- if options.keys.size > 0 and options[:method]
78
- out = options[:method].to_sym
79
- else
80
- hash = fields.select {|f| f.is_a?(Hash) }.inject({},:merge)
81
- out = {}
82
- if (h = hash.select {|k,v| !v.is_a?(Proc) }) && h.count > 0
83
- out[:hashes] = h
84
- end
85
- if (h = hash.select {|k,v| v.is_a?(Proc) }) && h.count > 0
86
- out[:procs] = h
87
- end
88
- if (h = fields.select {|o| o.is_a?(String) || o.is_a?(Symbol) }) && h.count > 0
89
- out[:fields] = h
90
- end
91
- end
92
- out
93
- end
94
-
95
- end
96
-
97
- def self.included(base)
98
- base.extend(ClassMethods)
99
- end
100
-
101
- end
102
- end