Class: Familia::RedisObject
- Inherits:
-
Object
- Object
- Familia::RedisObject
- Defined in:
- lib/familia/redisobject.rb
Class Attribute Summary collapse
- .classes ⇒ Object
- .db(v = nil) ⇒ Object
-
.parent ⇒ Object
Returns the value of attribute parent.
- .ttl(v = nil) ⇒ Object
- .uri(v = nil) ⇒ Object
Instance Attribute Summary collapse
-
#cache ⇒ Object
readonly
RedisObject instances are frozen.
-
#name ⇒ Object
readonly
Returns the value of attribute name.
-
#parent ⇒ Object
readonly
Returns the value of attribute parent.
- #redis ⇒ Object
Class Method Summary collapse
- .inherited(obj) ⇒ Object
-
.register(klass, meth) ⇒ Object
To be called inside every class that inherits RedisObject
meth
becomes the base for the class and instances methods that are created for the givenklass
(e.g. Obj.list). - .registration ⇒ Object
Instance Method Summary collapse
- #class? ⇒ Boolean
- #clear_cache ⇒ Object
-
#db ⇒ Object
Returns the most likely value for db, checking (in this order): * the value from :class if it’s a Familia object * the value from :parent * the value self.class.db * assumes the db is 0.
- #delete ⇒ Object (also: #clear, #del)
- #dump_method ⇒ Object
- #echo(meth, trace) ⇒ Object
-
#exists? ⇒ Boolean
def destroy! clear # TODO: delete redis objects for this instance end.
- #expire(sec) ⇒ Object
- #expireat(unixtime) ⇒ Object
- #from_redis(v) ⇒ Object
-
#initialize(name, opts = {}) ⇒ RedisObject
constructor
name
: If parent is set, this will be used as the suffix for rediskey. - #load_method ⇒ Object
- #move(db) ⇒ Object
- #multi_from_redis(*values) ⇒ Object
- #parent? ⇒ Boolean
- #persist ⇒ Object
- #qstamp(quantum = nil, pattern = nil, now = Familia.now) ⇒ Object
- #realttl ⇒ Object
-
#rediskey ⇒ Object
returns a redis key based on the parent object so it will include the proper index.
- #rename(newkey) ⇒ Object
- #renamenx(newkey) ⇒ Object
- #to_redis(v) ⇒ Object
- #ttl ⇒ Object
- #type ⇒ Object
- #update_expiration(ttl = nil) ⇒ Object
Constructor Details
#initialize(name, opts = {}) ⇒ RedisObject
name
: If parent is set, this will be used as the suffix for rediskey. Otherwise this becomes the value of the key. If this is an Array, the elements will be joined.
Options:
:class => A class that responds to Familia.load_method and Familia.dump_method. These will be used when loading and saving data from/to redis to unmarshal/marshal the class.
:reference => When true the index of the given value will be stored rather than the marshaled value. This assumes that the marshaled object is stored at a separate key. When read, from_redis looks for that separate key and returns the unmarshaled object. :class must be specified. Default: false.
:extend => Extend this instance with the functionality in an other module. Literally: “self.extend opts”.
:parent => The Familia object that this redis object belongs to. This can be a class that includes Familia or an instance.
:ttl => the time to live in seconds. When not nil, this will set the redis expire for this key whenever #save is called. You can also call it explicitly via #update_expiration.
:quantize => append a quantized timestamp to the rediskey. Takes one of the following:
Boolean: include the default stamp (now % 10 minutes)
Integer: the number of seconds to quantize to (e.g. 1.hour)
Array: All arguments for qstamp (quantum, pattern, Time.now)
:default => the default value (String-only)
:dump_method => the instance method to call to serialize the object before sending it to Redis (default: Familia.dump_method).
:load_method => the class method to call to deserialize the object after it’s read from Redis (default: Familia.load_method).
:db => the redis database to use (ignored if :redis is used).
:redis => an instance of Redis.
Uses the redis connection of the parent or the value of opts or Familia.redis (in that order).
104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/familia/redisobject.rb', line 104 def initialize name, opts={} @name, @opts = name, opts @name = @name.join(Familia.delim) if Array === @name #Familia.ld [name, opts, caller[0]].inspect self.extend @opts[:extend] if Module === @opts[:extend] @db = @opts.delete(:db) @parent = @opts.delete(:parent) @ttl ||= @opts.delete(:ttl) @redis ||= @opts.delete(:redis) @cache = {} init if respond_to? :init end |
Class Attribute Details
.classes ⇒ Object
19 20 21 |
# File 'lib/familia/redisobject.rb', line 19 def RedisObject.classes @classes end |
.db(v = nil) ⇒ Object
31 32 33 34 |
# File 'lib/familia/redisobject.rb', line 31 def db v=nil @db = v unless v.nil? @db || (parent ? parent.db : nil) end |
.parent ⇒ Object
Returns the value of attribute parent.
25 26 27 |
# File 'lib/familia/redisobject.rb', line 25 def parent @parent end |
.ttl(v = nil) ⇒ Object
27 28 29 30 |
# File 'lib/familia/redisobject.rb', line 27 def ttl v=nil @ttl = v unless v.nil? @ttl || (parent ? parent.ttl : nil) end |
Instance Attribute Details
#cache ⇒ Object (readonly)
RedisObject instances are frozen. ‘cache` is a hash for you to store values retreived from Redis. This is not used anywhere by default, but you’re encouraged to use it in your specific scenarios.
56 57 58 |
# File 'lib/familia/redisobject.rb', line 56 def cache @cache end |
#name ⇒ Object (readonly)
Returns the value of attribute name.
49 50 51 |
# File 'lib/familia/redisobject.rb', line 49 def name @name end |
#parent ⇒ Object (readonly)
Returns the value of attribute parent.
49 50 51 |
# File 'lib/familia/redisobject.rb', line 49 def parent @parent end |
Class Method Details
.inherited(obj) ⇒ Object
39 40 41 42 43 44 45 46 |
# File 'lib/familia/redisobject.rb', line 39 def inherited(obj) obj.db = self.db obj.ttl = self.ttl obj.uri = self.uri obj.parent = self RedisObject.classes << obj super(obj) end |
.register(klass, meth) ⇒ Object
To be called inside every class that inherits RedisObject meth
becomes the base for the class and instances methods that are created for the given klass
(e.g. Obj.list)
11 12 13 |
# File 'lib/familia/redisobject.rb', line 11 def RedisObject.register klass, meth registration[meth] = klass end |
.registration ⇒ Object
15 16 17 |
# File 'lib/familia/redisobject.rb', line 15 def RedisObject.registration @registration end |
Instance Method Details
#class? ⇒ Boolean
183 184 185 |
# File 'lib/familia/redisobject.rb', line 183 def class? !@opts[:class].to_s.empty? && @opts[:class].kind_of?(Familia) end |
#clear_cache ⇒ Object
117 118 119 |
# File 'lib/familia/redisobject.rb', line 117 def clear_cache @cache.clear end |
#db ⇒ Object
Returns the most likely value for db, checking (in this order):
* the value from :class if it's a Familia object
* the value from :parent
* the value self.class.db
* assumes the db is 0
After this is called once, this method will always return the same value.
138 139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/familia/redisobject.rb', line 138 def db # Note it's important that we select this value at the last # possible moment rather than in initialize b/c the value # could be modified after that but before this is called. if @opts[:class] && @opts[:class].ancestors.member?(Familia) @opts[:class].db elsif parent? parent.db else self.class.db || @db || 0 end end |
#delete ⇒ Object Also known as: clear, del
221 222 223 |
# File 'lib/familia/redisobject.rb', line 221 def delete redis.del rediskey end |
#dump_method ⇒ Object
252 253 254 |
# File 'lib/familia/redisobject.rb', line 252 def dump_method @opts[:dump_method] || Familia.dump_method end |
#echo(meth, trace) ⇒ Object
121 122 123 |
# File 'lib/familia/redisobject.rb', line 121 def echo meth, trace redis.echo "[#{self.class}\##{meth}] #{trace} (#{@opts[:class]}\#)" end |
#exists? ⇒ Boolean
def destroy!
clear
# TODO: delete redis objects for this instance
end
232 233 234 |
# File 'lib/familia/redisobject.rb', line 232 def exists? redis.exists(rediskey) && !size.zero? end |
#expire(sec) ⇒ Object
240 241 242 |
# File 'lib/familia/redisobject.rb', line 240 def expire sec redis.expire rediskey, sec.to_i end |
#expireat(unixtime) ⇒ Object
244 245 246 |
# File 'lib/familia/redisobject.rb', line 244 def expireat unixtime redis.expireat rediskey, unixtime end |
#from_redis(v) ⇒ Object
334 335 336 337 338 339 |
# File 'lib/familia/redisobject.rb', line 334 def from_redis v return @opts[:default] if v.nil? return v unless @opts[:class] ret = multi_from_redis v ret.first unless ret.nil? # return the object or nil end |
#load_method ⇒ Object
256 257 258 |
# File 'lib/familia/redisobject.rb', line 256 def load_method @opts[:load_method] || Familia.load_method end |
#move(db) ⇒ Object
205 206 207 |
# File 'lib/familia/redisobject.rb', line 205 def move db redis.move rediskey, db end |
#multi_from_redis(*values) ⇒ Object
293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 |
# File 'lib/familia/redisobject.rb', line 293 def multi_from_redis *values Familia.ld "multi_from_redis: (#{@opts}) #{values}" return [] if values.empty? return values.flatten unless @opts[:class] ret = case @opts[:class] when ::String v.to_s when ::Symbol v.to_s.to_sym when ::Integer, ::Float @opts[:class].induced_from v else objs = values if @opts[:reference] == true objs = @opts[:class].rawmultiget *values end objs.compact! if @opts[:class].respond_to? load_method objs.collect! { |obj| begin v = @opts[:class].send load_method, obj if v.nil? Familia.ld "[#{self.class}\#multi_from_redis] nil returned for #{@opts[:class]}\##{name}" end v rescue => ex Familia.info v Familia.info "Parse error for #{rediskey} (#{load_method}): #{ex.}" Familia.info ex.backtrace nil end } else raise Familia::Problem, "No such method: #{@opts[:class]}##{load_method}" end objs.compact # don't use compact! b/c the return value appears in ret end ret end |
#parent? ⇒ Boolean
187 188 189 |
# File 'lib/familia/redisobject.rb', line 187 def parent? Class === parent || Module === parent || parent.kind_of?(Familia) end |
#persist ⇒ Object
248 249 250 |
# File 'lib/familia/redisobject.rb', line 248 def persist redis.persist rediskey end |
#qstamp(quantum = nil, pattern = nil, now = Familia.now) ⇒ Object
191 192 193 194 195 196 |
# File 'lib/familia/redisobject.rb', line 191 def qstamp quantum=nil, pattern=nil, now=Familia.now quantum ||= ttl || 10.minutes pattern ||= '%H%M' rounded = now - (now % quantum) Time.at(rounded).utc.strftime(pattern) end |
#realttl ⇒ Object
236 237 238 |
# File 'lib/familia/redisobject.rb', line 236 def realttl redis.ttl rediskey end |
#rediskey ⇒ Object
returns a redis key based on the parent object so it will include the proper index.
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
# File 'lib/familia/redisobject.rb', line 160 def rediskey if parent? # We need to check if the parent has a specific suffix # for the case where we have specified one other than :object. suffix = parent.kind_of?(Familia) && parent.class.suffix != :object ? parent.class.suffix : name k = parent.rediskey(name, nil) else k = [name].flatten.compact.join(Familia.delim) end if @opts[:quantize] args = case @opts[:quantize] when Numeric [@opts[:quantize]] # :quantize => 1.minute when Array @opts[:quantize] # :quantize => [1.day, '%m%D'] else [] # :quantize => true end k = [k, qstamp(*args)].join(Familia.delim) end k end |
#rename(newkey) ⇒ Object
209 210 211 |
# File 'lib/familia/redisobject.rb', line 209 def rename newkey redis.rename rediskey, newkey end |
#renamenx(newkey) ⇒ Object
213 214 215 |
# File 'lib/familia/redisobject.rb', line 213 def renamenx newkey redis.renamenx rediskey, newkey end |
#to_redis(v) ⇒ Object
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 |
# File 'lib/familia/redisobject.rb', line 260 def to_redis v return v unless @opts[:class] ret = case @opts[:class] when ::Symbol, ::String, ::Integer, ::Float, Gibbler::Digest v when ::NilClass "" else if ::String === v v elsif @opts[:reference] == true unless v.respond_to? :index raise Familia::Problem, "#{v.class} does not have an index method" end unless v.kind_of?(Familia) raise Familia::Problem, "#{v.class} is not Familia (#{name})" end v.index elsif v.respond_to? dump_method v.send dump_method else raise Familia::Problem, "No such method: #{v.class}.#{dump_method}" end end if ret.nil? Familia.ld "[#{self.class}\#to_redis] nil returned for #{@opts[:class]}\##{name}" end ret end |
#ttl ⇒ Object
151 152 153 154 155 156 |
# File 'lib/familia/redisobject.rb', line 151 def ttl @ttl || (parent.ttl if parent?) || (@opts[:class].ttl if class?) || (self.class.ttl if self.class.respond_to?(:ttl)) end |
#type ⇒ Object
217 218 219 |
# File 'lib/familia/redisobject.rb', line 217 def type redis.type rediskey end |