redis_object 1.0 → 1.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.
- data/.coveralls.yml +1 -0
 - data/.gitignore +2 -0
 - data/.travis.yml +5 -0
 - data/Gemfile +4 -0
 - data/README.markdown +24 -15
 - data/Rakefile +8 -0
 - data/lib/redis_object.rb +11 -1
 - data/lib/redis_object/base.rb +210 -60
 - data/lib/redis_object/collection.rb +130 -100
 - data/lib/redis_object/defaults.rb +21 -8
 - data/lib/redis_object/{history.rb → experimental/history.rb} +0 -0
 - data/lib/redis_object/ext/filters.rb +34 -16
 - data/lib/redis_object/ext/script_cache.rb +92 -0
 - data/lib/redis_object/ext/shardable.rb +18 -0
 - data/lib/redis_object/ext/triggers.rb +75 -13
 - data/lib/redis_object/ext/view_caching.rb +258 -0
 - data/lib/redis_object/ext/views.rb +102 -0
 - data/lib/redis_object/indices.rb +44 -39
 - data/lib/redis_object/inheritance_tracking.rb +23 -0
 - data/lib/redis_object/keys.rb +4 -4
 - data/lib/redis_object/storage.rb +30 -1
 - data/lib/redis_object/storage/adapter.rb +6 -3
 - data/lib/redis_object/storage/redis.rb +98 -3
 - data/lib/redis_object/timestamps.rb +42 -21
 - data/lib/redis_object/types.rb +172 -30
 - data/lib/redis_object/version.rb +1 -1
 - data/redis_object.gemspec +1 -0
 - data/spec/adapter_spec.rb +43 -0
 - data/spec/base_spec.rb +41 -6
 - data/spec/benchmark_spec.rb +46 -0
 - data/spec/collections_spec.rb +144 -0
 - data/spec/defaults_spec.rb +56 -0
 - data/spec/filters_spec.rb +29 -0
 - data/spec/indices_spec.rb +45 -0
 - data/spec/rename_class_spec.rb +96 -0
 - data/spec/spec_helper.rb +32 -1
 - data/spec/timestamp_spec.rb +28 -0
 - data/spec/trigger_spec.rb +51 -0
 - data/spec/types_spec.rb +103 -0
 - data/spec/view_caching_spec.rb +130 -0
 - data/spec/views_spec.rb +72 -0
 - metadata +111 -116
 - data/doc/Object.html +0 -185
 - data/doc/Seabright.html +0 -181
 - data/doc/Seabright/Adapter.html +0 -442
 - data/doc/Seabright/Collection.html +0 -797
 - data/doc/Seabright/Collections.html +0 -635
 - data/doc/Seabright/Collections/ClassMethods.html +0 -212
 - data/doc/Seabright/ExternalIndex.html +0 -217
 - data/doc/Seabright/History.html +0 -382
 - data/doc/Seabright/History/ClassMethods.html +0 -276
 - data/doc/Seabright/Indices.html +0 -324
 - data/doc/Seabright/Indices/ClassMethods.html +0 -348
 - data/doc/Seabright/Keys.html +0 -314
 - data/doc/Seabright/Keys/ClassMethods.html +0 -276
 - data/doc/Seabright/ObjectBase.html +0 -852
 - data/doc/Seabright/ObjectBase/ClassMethods.html +0 -677
 - data/doc/Seabright/RedisObject.html +0 -230
 - data/doc/Seabright/References.html +0 -280
 - data/doc/Seabright/Storage.html +0 -252
 - data/doc/Seabright/Storage/ClassMethods.html +0 -276
 - data/doc/Seabright/Storage/MySQL.html +0 -442
 - data/doc/Seabright/Storage/Redis.html +0 -218
 - data/doc/Seabright/Template.html +0 -212
 - data/doc/Seabright/Template/ClassMethods.html +0 -166
 - data/doc/Seabright/Timestamps.html +0 -292
 - data/doc/Seabright/Timestamps/ClassMethods.html +0 -214
 - data/doc/Seabright/Types.html +0 -410
 - data/doc/Seabright/Types/ClassMethods.html +0 -308
 - data/doc/created.rid +0 -17
 - data/doc/images/add.png +0 -0
 - data/doc/images/brick.png +0 -0
 - data/doc/images/brick_link.png +0 -0
 - data/doc/images/bug.png +0 -0
 - data/doc/images/bullet_black.png +0 -0
 - data/doc/images/bullet_toggle_minus.png +0 -0
 - data/doc/images/bullet_toggle_plus.png +0 -0
 - data/doc/images/date.png +0 -0
 - data/doc/images/delete.png +0 -0
 - data/doc/images/find.png +0 -0
 - data/doc/images/loadingAnimation.gif +0 -0
 - data/doc/images/macFFBgHack.png +0 -0
 - data/doc/images/package.png +0 -0
 - data/doc/images/page_green.png +0 -0
 - data/doc/images/page_white_text.png +0 -0
 - data/doc/images/page_white_width.png +0 -0
 - data/doc/images/plugin.png +0 -0
 - data/doc/images/ruby.png +0 -0
 - data/doc/images/tag_blue.png +0 -0
 - data/doc/images/tag_green.png +0 -0
 - data/doc/images/transparent.png +0 -0
 - data/doc/images/wrench.png +0 -0
 - data/doc/images/wrench_orange.png +0 -0
 - data/doc/images/zoom.png +0 -0
 - data/doc/index.html +0 -125
 - data/doc/js/darkfish.js +0 -153
 - data/doc/js/jquery.js +0 -18
 - data/doc/js/navigation.js +0 -142
 - data/doc/js/search.js +0 -94
 - data/doc/js/search_index.js +0 -1
 - data/doc/js/searcher.js +0 -228
 - data/doc/rdoc.css +0 -543
 - data/doc/table_of_contents.html +0 -394
 
| 
         @@ -0,0 +1,102 @@ 
     | 
|
| 
      
 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
         
     | 
    
        data/lib/redis_object/indices.rb
    CHANGED
    
    | 
         @@ -1,45 +1,50 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module Seabright
         
     | 
| 
       2 
2 
     | 
    
         
             
            	module Indices
         
     | 
| 
       3 
3 
     | 
    
         | 
| 
       4 
     | 
    
         
            -
            		# def save_indices
         
     | 
| 
       5 
     | 
    
         
            -
            		# 	# self.class.indices.each do |indx|
         
     | 
| 
       6 
     | 
    
         
            -
            		# 	# 	indx.each do |key,idx|
         
     | 
| 
       7 
     | 
    
         
            -
            		# 	# 		
         
     | 
| 
       8 
     | 
    
         
            -
            		# 	# 	end
         
     | 
| 
       9 
     | 
    
         
            -
            		# 	# end
         
     | 
| 
       10 
     | 
    
         
            -
            		# 	self.class.sort_indices.each do |idx|
         
     | 
| 
       11 
     | 
    
         
            -
            		# 		store.zadd(index_key(idx), send(idx).to_i, hkey)
         
     | 
| 
       12 
     | 
    
         
            -
            		# 	end
         
     | 
| 
       13 
     | 
    
         
            -
            		# end
         
     | 
| 
       14 
     | 
    
         
            -
            		
         
     | 
| 
       15 
4 
     | 
    
         
             
            		def index_key(idx)
         
     | 
| 
       16 
5 
     | 
    
         
             
            			self.class.index_key(idx)
         
     | 
| 
       17 
6 
     | 
    
         
             
            		end
         
     | 
| 
       18 
7 
     | 
    
         | 
| 
       19 
     | 
    
         
            -
            		# def save
         
     | 
| 
       20 
     | 
    
         
            -
            		# 	super
         
     | 
| 
       21 
     | 
    
         
            -
            		# 	save_indices
         
     | 
| 
       22 
     | 
    
         
            -
            		# end
         
     | 
| 
       23 
     | 
    
         
            -
            		
         
     | 
| 
       24 
     | 
    
         
            -
            		def mset(dat)
         
     | 
| 
       25 
     | 
    
         
            -
            			super(dat)
         
     | 
| 
       26 
     | 
    
         
            -
            			dat.select {|k,v| self.class.has_sort_index?(k) }.each do |k,v|
         
     | 
| 
       27 
     | 
    
         
            -
            				store.zadd(index_key(k), score_format(k,v), hkey)
         
     | 
| 
       28 
     | 
    
         
            -
            			end
         
     | 
| 
       29 
     | 
    
         
            -
            		end
         
     | 
| 
       30 
     | 
    
         
            -
            		
         
     | 
| 
       31 
     | 
    
         
            -
            		def set(k,v)
         
     | 
| 
       32 
     | 
    
         
            -
            			super(k,v)
         
     | 
| 
       33 
     | 
    
         
            -
            			if self.class.has_sort_index?(k)
         
     | 
| 
       34 
     | 
    
         
            -
            				store.zadd(index_key(k), score_format(k,v), hkey)
         
     | 
| 
       35 
     | 
    
         
            -
            			end
         
     | 
| 
       36 
     | 
    
         
            -
            		end
         
     | 
| 
       37 
     | 
    
         
            -
            		
         
     | 
| 
       38 
8 
     | 
    
         
             
            		module ClassMethods
         
     | 
| 
       39 
9 
     | 
    
         | 
| 
      
 10 
     | 
    
         
            +
            			def intercept_sets_for_indices!
         
     | 
| 
      
 11 
     | 
    
         
            +
            				return if @intercepted_sets_for_indices
         
     | 
| 
      
 12 
     | 
    
         
            +
            				self.class_eval do
         
     | 
| 
      
 13 
     | 
    
         
            +
            					alias_method :unindexed_set, :set unless method_defined?(:unindexed_set)
         
     | 
| 
      
 14 
     | 
    
         
            +
            					def set(k,v)
         
     | 
| 
      
 15 
     | 
    
         
            +
            						ret = unindexed_set(k,v)
         
     | 
| 
      
 16 
     | 
    
         
            +
            						if self.class.has_sort_index?(k)
         
     | 
| 
      
 17 
     | 
    
         
            +
            							store.zrem(index_key(k), hkey)
         
     | 
| 
      
 18 
     | 
    
         
            +
            							store.zadd(index_key(k), score_format(k,v), hkey)
         
     | 
| 
      
 19 
     | 
    
         
            +
            						end
         
     | 
| 
      
 20 
     | 
    
         
            +
            						ret
         
     | 
| 
      
 21 
     | 
    
         
            +
            					end
         
     | 
| 
      
 22 
     | 
    
         
            +
            					alias_method :unindexed_mset, :mset unless method_defined?(:unindexed_mset)
         
     | 
| 
      
 23 
     | 
    
         
            +
            					def mset(dat)
         
     | 
| 
      
 24 
     | 
    
         
            +
            						ret = unindexed_mset(dat)
         
     | 
| 
      
 25 
     | 
    
         
            +
            						dat.select {|k,v| self.class.has_sort_index?(k) }.each do |k,v|
         
     | 
| 
      
 26 
     | 
    
         
            +
            							store.zrem(index_key(k), hkey)
         
     | 
| 
      
 27 
     | 
    
         
            +
            							store.zadd(index_key(k), score_format(k,v), hkey)
         
     | 
| 
      
 28 
     | 
    
         
            +
            						end
         
     | 
| 
      
 29 
     | 
    
         
            +
            						ret
         
     | 
| 
      
 30 
     | 
    
         
            +
            					end
         
     | 
| 
      
 31 
     | 
    
         
            +
            					alias_method :unindexed_setnx, :setnx unless method_defined?(:unindexed_setnx)
         
     | 
| 
      
 32 
     | 
    
         
            +
            					def setnx(k,v)
         
     | 
| 
      
 33 
     | 
    
         
            +
            						ret = unindexed_setnx(k,v)
         
     | 
| 
      
 34 
     | 
    
         
            +
            						if self.class.has_sort_index?(k)
         
     | 
| 
      
 35 
     | 
    
         
            +
            							store.zrem(index_key(k), hkey)
         
     | 
| 
      
 36 
     | 
    
         
            +
            							store.zadd(index_key(k), score_format(k,v), hkey)
         
     | 
| 
      
 37 
     | 
    
         
            +
            						end
         
     | 
| 
      
 38 
     | 
    
         
            +
            						ret
         
     | 
| 
      
 39 
     | 
    
         
            +
            					end
         
     | 
| 
      
 40 
     | 
    
         
            +
            					
         
     | 
| 
      
 41 
     | 
    
         
            +
            				end
         
     | 
| 
      
 42 
     | 
    
         
            +
            				@intercepted_sets_for_indices = true
         
     | 
| 
      
 43 
     | 
    
         
            +
            			end
         
     | 
| 
      
 44 
     | 
    
         
            +
            			
         
     | 
| 
       40 
45 
     | 
    
         
             
            			def indexed(idx,num=-1,reverse=false)
         
     | 
| 
       41 
46 
     | 
    
         
             
            				out = Enumerator.new do |yielder|
         
     | 
| 
       42 
     | 
    
         
            -
            					store.send(reverse ? :zrevrange : :zrange, index_key(idx), 0, num).each do |member|
         
     | 
| 
      
 47 
     | 
    
         
            +
            					store.send(reverse ? :zrevrange : :zrange, index_key(idx), 0, num-1).each do |member|
         
     | 
| 
       43 
48 
     | 
    
         
             
            						if a = self.find_by_key(member)
         
     | 
| 
       44 
49 
     | 
    
         
             
            							yielder << a
         
     | 
| 
       45 
50 
     | 
    
         
             
            						end
         
     | 
| 
         @@ -58,20 +63,20 @@ module Seabright 
     | 
|
| 
       58 
63 
     | 
    
         
             
            				"#{self.plname}::#{idx}"
         
     | 
| 
       59 
64 
     | 
    
         
             
            			end
         
     | 
| 
       60 
65 
     | 
    
         | 
| 
       61 
     | 
    
         
            -
            			# def index(opts)
         
     | 
| 
       62 
     | 
    
         
            -
            			# 	indices << opts
         
     | 
| 
       63 
     | 
    
         
            -
            			# end
         
     | 
| 
       64 
     | 
    
         
            -
            			# 
         
     | 
| 
       65 
     | 
    
         
            -
            			# def indices
         
     | 
| 
       66 
     | 
    
         
            -
            			# 	@@indices ||= []
         
     | 
| 
       67 
     | 
    
         
            -
            			# end
         
     | 
| 
       68 
     | 
    
         
            -
            			
         
     | 
| 
       69 
66 
     | 
    
         
             
            			def sort_indices
         
     | 
| 
       70 
67 
     | 
    
         
             
            				@@sort_indices ||= []
         
     | 
| 
       71 
68 
     | 
    
         
             
            			end
         
     | 
| 
       72 
69 
     | 
    
         | 
| 
       73 
70 
     | 
    
         
             
            			def sort_by(k)
         
     | 
| 
       74 
71 
     | 
    
         
             
            				sort_indices << k.to_sym
         
     | 
| 
      
 72 
     | 
    
         
            +
            				intercept_sets_for_indices!
         
     | 
| 
      
 73 
     | 
    
         
            +
            			end
         
     | 
| 
      
 74 
     | 
    
         
            +
            			
         
     | 
| 
      
 75 
     | 
    
         
            +
            			def reindex(k)
         
     | 
| 
      
 76 
     | 
    
         
            +
            				store.del index_key(k)
         
     | 
| 
      
 77 
     | 
    
         
            +
            				all.each do |obj|
         
     | 
| 
      
 78 
     | 
    
         
            +
            					obj.set(k,obj.get(k))
         
     | 
| 
      
 79 
     | 
    
         
            +
            				end
         
     | 
| 
       75 
80 
     | 
    
         
             
            			end
         
     | 
| 
       76 
81 
     | 
    
         | 
| 
       77 
82 
     | 
    
         
             
            			def has_sort_index?(k)
         
     | 
| 
         @@ -0,0 +1,23 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Seabright
         
     | 
| 
      
 2 
     | 
    
         
            +
            	module InheritanceTracking
         
     | 
| 
      
 3 
     | 
    
         
            +
            		
         
     | 
| 
      
 4 
     | 
    
         
            +
            		module ClassMethods
         
     | 
| 
      
 5 
     | 
    
         
            +
            			def inherited(child_class)
         
     | 
| 
      
 6 
     | 
    
         
            +
            				child_classes_set.add(child_class)
         
     | 
| 
      
 7 
     | 
    
         
            +
            			end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            			def child_classes_set
         
     | 
| 
      
 10 
     | 
    
         
            +
            				@child_classes_set ||= Set.new
         
     | 
| 
      
 11 
     | 
    
         
            +
            			end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            			def child_classes
         
     | 
| 
      
 14 
     | 
    
         
            +
            				child_classes_set.to_a
         
     | 
| 
      
 15 
     | 
    
         
            +
            			end
         
     | 
| 
      
 16 
     | 
    
         
            +
            		end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
            		def self.included(base)
         
     | 
| 
      
 19 
     | 
    
         
            +
            			base.extend(ClassMethods)
         
     | 
| 
      
 20 
     | 
    
         
            +
            		end
         
     | 
| 
      
 21 
     | 
    
         
            +
            		
         
     | 
| 
      
 22 
     | 
    
         
            +
            	end
         
     | 
| 
      
 23 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/redis_object/keys.rb
    CHANGED
    
    | 
         @@ -15,15 +15,15 @@ module Seabright 
     | 
|
| 
       15 
15 
     | 
    
         | 
| 
       16 
16 
     | 
    
         
             
            		module ClassMethods
         
     | 
| 
       17 
17 
     | 
    
         | 
| 
       18 
     | 
    
         
            -
            			def key(ident)
         
     | 
| 
       19 
     | 
    
         
            -
            				"#{cname}:#{ident.gsub(/^.*:/,'')}"
         
     | 
| 
      
 18 
     | 
    
         
            +
            			def key(ident=nil)
         
     | 
| 
      
 19 
     | 
    
         
            +
            				"#{cname}#{ident ? ":#{ident.gsub(/^.*:/,'')}" : ""}"
         
     | 
| 
       20 
20 
     | 
    
         
             
            			end
         
     | 
| 
       21 
21 
     | 
    
         | 
| 
       22 
     | 
    
         
            -
            			def reserve_key(ident)
         
     | 
| 
      
 22 
     | 
    
         
            +
            			def reserve_key(ident=nil)
         
     | 
| 
       23 
23 
     | 
    
         
             
            				"#{key(ident)}_reserve"
         
     | 
| 
       24 
24 
     | 
    
         
             
            			end
         
     | 
| 
       25 
25 
     | 
    
         | 
| 
       26 
     | 
    
         
            -
            			def hkey(ident =  
     | 
| 
      
 26 
     | 
    
         
            +
            			def hkey(ident = nil)
         
     | 
| 
       27 
27 
     | 
    
         
             
            				"#{key(ident)}_h"
         
     | 
| 
       28 
28 
     | 
    
         
             
            			end
         
     | 
| 
       29 
29 
     | 
    
         | 
    
        data/lib/redis_object/storage.rb
    CHANGED
    
    | 
         @@ -19,8 +19,12 @@ module Seabright 
     | 
|
| 
       19 
19 
     | 
    
         
             
            				adapters[id] ||= const_get(adapter).new(config(id))
         
     | 
| 
       20 
20 
     | 
    
         
             
            			end
         
     | 
| 
       21 
21 
     | 
    
         | 
| 
       22 
     | 
    
         
            -
            			def configure_store(conf,id=store_name)
         
     | 
| 
      
 22 
     | 
    
         
            +
            			def configure_store(conf,id=store_name,*ids)
         
     | 
| 
       23 
23 
     | 
    
         
             
            				configs[id] = conf
         
     | 
| 
      
 24 
     | 
    
         
            +
            				ids.each do |i|
         
     | 
| 
      
 25 
     | 
    
         
            +
            					configs[i] = conf
         
     | 
| 
      
 26 
     | 
    
         
            +
            				end
         
     | 
| 
      
 27 
     | 
    
         
            +
            				store(id)
         
     | 
| 
       24 
28 
     | 
    
         
             
            			end
         
     | 
| 
       25 
29 
     | 
    
         | 
| 
       26 
30 
     | 
    
         
             
            			def use_store(id)
         
     | 
| 
         @@ -54,6 +58,31 @@ module Seabright 
     | 
|
| 
       54 
58 
     | 
    
         
             
            				configs[id]
         
     | 
| 
       55 
59 
     | 
    
         
             
            			end
         
     | 
| 
       56 
60 
     | 
    
         | 
| 
      
 61 
     | 
    
         
            +
            			def stores
         
     | 
| 
      
 62 
     | 
    
         
            +
            				adapters
         
     | 
| 
      
 63 
     | 
    
         
            +
            			end
         
     | 
| 
      
 64 
     | 
    
         
            +
            			
         
     | 
| 
      
 65 
     | 
    
         
            +
            			def dump_stores_to_files(path)
         
     | 
| 
      
 66 
     | 
    
         
            +
            				raise "Directory does not exist!" unless Dir.exists?(File.dirname(path))
         
     | 
| 
      
 67 
     | 
    
         
            +
            				adapters.each do |name,adptr|
         
     | 
| 
      
 68 
     | 
    
         
            +
            					if adptr.respond_to? :dump_to_file
         
     | 
| 
      
 69 
     | 
    
         
            +
            						puts "Dumping #{name} into #{path}/#{name.to_s}.dump"
         
     | 
| 
      
 70 
     | 
    
         
            +
            						adptr.dump_to_file("#{path}/#{name.to_s}.dump")
         
     | 
| 
      
 71 
     | 
    
         
            +
            					end
         
     | 
| 
      
 72 
     | 
    
         
            +
            				end
         
     | 
| 
      
 73 
     | 
    
         
            +
            			end
         
     | 
| 
      
 74 
     | 
    
         
            +
            			
         
     | 
| 
      
 75 
     | 
    
         
            +
            			def restore_stores_from_files(path)
         
     | 
| 
      
 76 
     | 
    
         
            +
            				raise "Directory does not exist!" unless Dir.exists?(File.dirname(path))
         
     | 
| 
      
 77 
     | 
    
         
            +
            				Dir.glob(path + "/*.dump").each do |file|
         
     | 
| 
      
 78 
     | 
    
         
            +
            					name = file.gsub(/\.[^\.]+$/,'').gsub(/.*\//,'').to_sym
         
     | 
| 
      
 79 
     | 
    
         
            +
            					if (stor = store(name)) && stor.respond_to?(:restore_from_file)
         
     | 
| 
      
 80 
     | 
    
         
            +
            						puts "Restoring #{name} from #{file}"
         
     | 
| 
      
 81 
     | 
    
         
            +
            						stor.restore_from_file(file)
         
     | 
| 
      
 82 
     | 
    
         
            +
            					end
         
     | 
| 
      
 83 
     | 
    
         
            +
            				end
         
     | 
| 
      
 84 
     | 
    
         
            +
            			end
         
     | 
| 
      
 85 
     | 
    
         
            +
            			
         
     | 
| 
       57 
86 
     | 
    
         
             
            		end
         
     | 
| 
       58 
87 
     | 
    
         | 
| 
       59 
88 
     | 
    
         
             
            		def self.included(base)
         
     | 
| 
         @@ -23,15 +23,18 @@ module Seabright 
     | 
|
| 
       23 
23 
     | 
    
         
             
            			end
         
     | 
| 
       24 
24 
     | 
    
         | 
| 
       25 
25 
     | 
    
         
             
            			def reset
         
     | 
| 
       26 
     | 
    
         
            -
            				 
     | 
| 
       27 
     | 
    
         
            -
            					 
     | 
| 
      
 26 
     | 
    
         
            +
            				connections.each_index do |i|
         
     | 
| 
      
 27 
     | 
    
         
            +
            					connections[i] = nil
         
     | 
| 
       28 
28 
     | 
    
         
             
            				end
         
     | 
| 
       29 
29 
     | 
    
         
             
            			end
         
     | 
| 
       30 
30 
     | 
    
         
             
            			alias_method :reconnect!, :reset
         
     | 
| 
       31 
31 
     | 
    
         | 
| 
       32 
32 
     | 
    
         
             
            			def connection(num=0)
         
     | 
| 
      
 33 
     | 
    
         
            +
            				connections[num] ||= new_connection
         
     | 
| 
      
 34 
     | 
    
         
            +
            			end
         
     | 
| 
      
 35 
     | 
    
         
            +
            			
         
     | 
| 
      
 36 
     | 
    
         
            +
            			def connections
         
     | 
| 
       33 
37 
     | 
    
         
             
            				@connections ||= []
         
     | 
| 
       34 
     | 
    
         
            -
            				@connections[num] ||= new_connection
         
     | 
| 
       35 
38 
     | 
    
         
             
            			end
         
     | 
| 
       36 
39 
     | 
    
         | 
| 
       37 
40 
     | 
    
         
             
            			def new_connection
         
     | 
| 
         @@ -3,6 +3,7 @@ module Seabright 
     | 
|
| 
       3 
3 
     | 
    
         
             
            		class Redis < Adapter
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
       5 
5 
     | 
    
         
             
            			def method_missing(sym, *args, &block)
         
     | 
| 
      
 6 
     | 
    
         
            +
            				return super unless connection.respond_to?(sym)
         
     | 
| 
       6 
7 
     | 
    
         
             
            				puts "[Storage::Redis] #{sym}(#{args.inspect.gsub(/\[|\]/m,'')})" if Debug.verbose?
         
     | 
| 
       7 
8 
     | 
    
         
             
            				begin
         
     | 
| 
       8 
9 
     | 
    
         
             
            					connection.send(sym,*args, &block)
         
     | 
| 
         @@ -10,15 +11,109 @@ module Seabright 
     | 
|
| 
       10 
11 
     | 
    
         
             
            					puts "Rescued: #{err.inspect}" if DEBUG
         
     | 
| 
       11 
12 
     | 
    
         
             
            					reset
         
     | 
| 
       12 
13 
     | 
    
         
             
            					connection.send(sym,*args, &block)
         
     | 
| 
      
 14 
     | 
    
         
            +
            				rescue ::Redis::TimeoutError => err
         
     | 
| 
      
 15 
     | 
    
         
            +
            					puts "Rescued connection timeout: #{err.inspect}" if DEBUG
         
     | 
| 
      
 16 
     | 
    
         
            +
            					reset
         
     | 
| 
      
 17 
     | 
    
         
            +
            					connection.send(sym,*args, &block)
         
     | 
| 
       13 
18 
     | 
    
         
             
            				end
         
     | 
| 
       14 
19 
     | 
    
         
             
            			end
         
     | 
| 
       15 
20 
     | 
    
         | 
| 
       16 
21 
     | 
    
         
             
            			def new_connection
         
     | 
| 
       17 
22 
     | 
    
         
             
            				require 'redis'
         
     | 
| 
       18 
     | 
    
         
            -
            				 
     | 
| 
       19 
     | 
    
         
            -
            				::Redis.new(config_opts(:path, :db, :password))
         
     | 
| 
      
 23 
     | 
    
         
            +
            				puts "Connecting to Redis with: #{config_opts(:path, :db, :password, :host, :port, :timeout, :tcp_keepalive).inspect}" if DEBUG
         
     | 
| 
      
 24 
     | 
    
         
            +
            				::Redis.new(config_opts(:path, :db, :password, :host, :port, :timeout, :tcp_keepalive))
         
     | 
| 
      
 25 
     | 
    
         
            +
            			end
         
     | 
| 
      
 26 
     | 
    
         
            +
            			
         
     | 
| 
      
 27 
     | 
    
         
            +
            			DUMP_SEPARATOR = "---:::RedisObject::DUMP_SEPARATOR:::---"
         
     | 
| 
      
 28 
     | 
    
         
            +
            			REC_SEPARATOR = "---:::RedisObject::REC_SEPARATOR:::---"
         
     | 
| 
      
 29 
     | 
    
         
            +
            			
         
     | 
| 
      
 30 
     | 
    
         
            +
            			def dump_to_file(file)
         
     | 
| 
      
 31 
     | 
    
         
            +
            				File.open(file,'wb') do |f|
         
     | 
| 
      
 32 
     | 
    
         
            +
            					keys = connection.send(:keys,"*")
         
     | 
| 
      
 33 
     | 
    
         
            +
            					f.write keys.map {|k|
         
     | 
| 
      
 34 
     | 
    
         
            +
            						v = connection.dump(k)
         
     | 
| 
      
 35 
     | 
    
         
            +
            						v.force_encoding(Encoding::BINARY)
         
     | 
| 
      
 36 
     | 
    
         
            +
            						[k,v].join(DUMP_SEPARATOR)
         
     | 
| 
      
 37 
     | 
    
         
            +
            					}.join(REC_SEPARATOR)
         
     | 
| 
      
 38 
     | 
    
         
            +
            				end
         
     | 
| 
      
 39 
     | 
    
         
            +
            			end
         
     | 
| 
      
 40 
     | 
    
         
            +
            			
         
     | 
| 
      
 41 
     | 
    
         
            +
            			def restore_from_file(file)
         
     | 
| 
      
 42 
     | 
    
         
            +
            				str = File.read(file)
         
     | 
| 
      
 43 
     | 
    
         
            +
            				str.force_encoding(Encoding::BINARY)
         
     | 
| 
      
 44 
     | 
    
         
            +
            				str.split(REC_SEPARATOR).each do |line|
         
     | 
| 
      
 45 
     | 
    
         
            +
            					line.force_encoding(Encoding::BINARY)
         
     | 
| 
      
 46 
     | 
    
         
            +
            					key, val = line.split(DUMP_SEPARATOR)
         
     | 
| 
      
 47 
     | 
    
         
            +
            					connection.multi do
         
     | 
| 
      
 48 
     | 
    
         
            +
            						connection.del key
         
     | 
| 
      
 49 
     | 
    
         
            +
            						connection.restore key, 0, val
         
     | 
| 
      
 50 
     | 
    
         
            +
            					end
         
     | 
| 
      
 51 
     | 
    
         
            +
            				end
         
     | 
| 
      
 52 
     | 
    
         
            +
            			end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
            			def rename_class old_name, new_name
         
     | 
| 
      
 55 
     | 
    
         
            +
            				old_name = old_name.to_s#.split('::').last
         
     | 
| 
      
 56 
     | 
    
         
            +
            				new_name = new_name.to_s#.split('::').last
         
     | 
| 
      
 57 
     | 
    
         
            +
            				old_collection_name = old_name.split('::').last.underscore.pluralize
         
     | 
| 
      
 58 
     | 
    
         
            +
            				new_collection_name = new_name.split('::').last.underscore.pluralize
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
            				# references to type in collection data
         
     | 
| 
      
 61 
     | 
    
         
            +
            				keys("#{old_name}:*:backreferences").each do |backref_key|
         
     | 
| 
      
 62 
     | 
    
         
            +
            					smembers(backref_key).each do |hashref|
         
     | 
| 
      
 63 
     | 
    
         
            +
            						# there are two referenes we need to fix: individual references to items
         
     | 
| 
      
 64 
     | 
    
         
            +
            						# and lists of collection names.
         
     | 
| 
      
 65 
     | 
    
         
            +
            						#
         
     | 
| 
      
 66 
     | 
    
         
            +
            						# this updates the item references in collections
         
     | 
| 
      
 67 
     | 
    
         
            +
            						backref = hashref.sub(/_h$/,'');
         
     | 
| 
      
 68 
     | 
    
         
            +
            						old_collection = "#{backref}:COLLECTION:#{old_collection_name}"
         
     | 
| 
      
 69 
     | 
    
         
            +
            						new_collection = "#{backref}:COLLECTION:#{new_collection_name}"
         
     | 
| 
      
 70 
     | 
    
         
            +
            						zrange(old_collection, 0, 99999, withscores:true).each do |key, score|
         
     | 
| 
      
 71 
     | 
    
         
            +
            							zadd(new_collection, score, key.sub(/^#{old_name}/, new_name))
         
     | 
| 
      
 72 
     | 
    
         
            +
            						end
         
     | 
| 
      
 73 
     | 
    
         
            +
            						del(old_collection)
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
            						# this updates the lists of collection names
         
     | 
| 
      
 76 
     | 
    
         
            +
            						collection_names = "#{hashref}:collections"
         
     | 
| 
      
 77 
     | 
    
         
            +
            						smembers(collection_names).each do |collection_name|
         
     | 
| 
      
 78 
     | 
    
         
            +
            							if collection_name == old_collection_name
         
     | 
| 
      
 79 
     | 
    
         
            +
            								sadd(collection_names, new_collection_name)
         
     | 
| 
      
 80 
     | 
    
         
            +
            								srem(collection_names, old_collection_name)
         
     | 
| 
      
 81 
     | 
    
         
            +
            							end
         
     | 
| 
      
 82 
     | 
    
         
            +
            						end
         
     | 
| 
      
 83 
     | 
    
         
            +
            					end
         
     | 
| 
      
 84 
     | 
    
         
            +
            					rename(backref_key, backref_key.sub(/^#{old_name}/, new_name))
         
     | 
| 
      
 85 
     | 
    
         
            +
            				end
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
            				# type-wide id index
         
     | 
| 
      
 88 
     | 
    
         
            +
            				smembers(old_name.pluralize).each do |key|
         
     | 
| 
      
 89 
     | 
    
         
            +
            					sadd(new_name.pluralize, key.sub(/^#{old_name}/, new_name))
         
     | 
| 
      
 90 
     | 
    
         
            +
            					old_class = hget("#{key}_h", :class)
         
     | 
| 
      
 91 
     | 
    
         
            +
            					old_key = hget("#{key}_h", :key)
         
     | 
| 
      
 92 
     | 
    
         
            +
            					hset("#{key}_h", :class, old_class.sub(/#{old_name}$/, new_name))
         
     | 
| 
      
 93 
     | 
    
         
            +
            					hset("#{key}_h", :key, old_key.sub(/^#{old_name}/, new_name))
         
     | 
| 
      
 94 
     | 
    
         
            +
            					hset("#{key}_h", "#{new_name.downcase}_id", key.sub(/^#{old_name}:/,''))
         
     | 
| 
      
 95 
     | 
    
         
            +
            					hdel("#{key}_h", "#{old_name.downcase}_id")
         
     | 
| 
      
 96 
     | 
    
         
            +
            				end
         
     | 
| 
      
 97 
     | 
    
         
            +
            				del(old_name.pluralize)
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
            				# column indexes
         
     | 
| 
      
 100 
     | 
    
         
            +
            				keys("#{old_name.pluralize}::*").each do |old_index|
         
     | 
| 
      
 101 
     | 
    
         
            +
            					new_index = old_index.sub(/^#{old_name.pluralize}/, new_name.pluralize)
         
     | 
| 
      
 102 
     | 
    
         
            +
            					zrange(old_index, 0, 99999, withscores:true).each do |key, score|
         
     | 
| 
      
 103 
     | 
    
         
            +
            						zadd(new_index, score, key.sub(/^#{old_name}/, new_name))
         
     | 
| 
      
 104 
     | 
    
         
            +
            					end
         
     | 
| 
      
 105 
     | 
    
         
            +
            					del(old_index)
         
     | 
| 
      
 106 
     | 
    
         
            +
            				end
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
            				# top-level keys
         
     | 
| 
      
 109 
     | 
    
         
            +
            				keys("#{old_name}:*").each do |key|
         
     | 
| 
      
 110 
     | 
    
         
            +
            					rename(key, key.sub(/^#{old_name}/, new_name))
         
     | 
| 
      
 111 
     | 
    
         
            +
            				end
         
     | 
| 
      
 112 
     | 
    
         
            +
            				keys("#{old_name.pluralize}:*").each do |key|
         
     | 
| 
      
 113 
     | 
    
         
            +
            					rename(key, key.sub(/^#{old_name.pluralize}/, new_name.pluralize))
         
     | 
| 
      
 114 
     | 
    
         
            +
            				end
         
     | 
| 
       20 
115 
     | 
    
         
             
            			end
         
     | 
| 
       21 
116 
     | 
    
         | 
| 
       22 
117 
     | 
    
         
             
            		end
         
     | 
| 
       23 
118 
     | 
    
         
             
            	end
         
     | 
| 
       24 
     | 
    
         
            -
            end
         
     | 
| 
      
 119 
     | 
    
         
            +
            end
         
     |