Class: Vash

Inherits:
Hash
  • Object
show all
Defined in:
lib/vash.rb

Overview

Class: Vash (Ruby Volatile Hash) Hash that returns values only for a short time. This is useful as a cache where I/O is involved. The primary goal of this object is to reduce I/O access and due to the nature of I/O being slower then memory, you should also see a gain in quicker response times.

For example, if Person.first found the first person from the database & cache was an instance of Vash then the following would only contact the database for the first iteration:

> cache = Vash.new > 1000.times ||= Person.first

However if you did the following immediately following that command it would hit the database again:

> sleep 43201 > cache ||= Person.first

The reason is that there is a default Time-To-Live of 43200 seconds. You can also set a custom TTL of 10 seconds like so:

> cache[:person, 10] = Person.first

The Vash object will forget any answer that is requested after the specified TTL. It is a good idea to manually clean things up from time to time because it is possible that you’ll cache data but never again access it and therefor it will stay in memory after the TTL has expired. To clean up the Vash object, call the method: cleanup!

> sleep 11 # At this point the prior person ttl will be expired

#  but the person key and value will still exist.

> cache # This will still show the the entire set of keys

#  regardless of the TTL, the :person will still exist

> cache.cleanup! # All of the TTL’s will be inspected and the expired

#  :person key will be deleted.

The cleanup must be manually called because the purpose of the Vash is to lessen needless I/O calls and gain speed not to slow it down with regular maintenance.

Instance Method Summary collapse

Constructor Details

#initialize(constructor = {}) ⇒ Vash

Returns a new instance of Vash.



43
44
45
46
47
48
49
50
51
# File 'lib/vash.rb', line 43

def initialize(constructor = {})
  @register ||= {} # remembers expiration time of every key
  if constructor.is_a?(Hash)
    super()
    merge(constructor)
  else
    super(constructor)
  end
end

Instance Method Details

#[](key) ⇒ Object



56
57
58
59
60
# File 'lib/vash.rb', line 56

def [](key)
  sterilize(key)
  clear(key) if expired?(key)
  regular_reader(key)
end

#[]=(key, *args) ⇒ Object



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/vash.rb', line 62

def []=(key, *args)
  # a little bit o variable hacking to support (h[key, ttl] = value), which will come 
  # accross as (key, [ttl, value]) whereas (h[key]=value) comes accross as (key, [value])
  if args.length == 2
    value, ttl = args[1], args[0]
  elsif args.length == 1
    value, ttl = args[0], 43200
  else
    raise ArgumentError, "Wrong number of arguments, expected 2 or 3, received: #{args.length+1}\n"+
                         "Example Usage:  volatile_hash[:key]=value OR volatile_hash[:key, ttl]=value"
  end
  sterilize(key)
  ttl(key, ttl)
  regular_writer(key, value)
end

#cleanup!Object



83
84
85
86
# File 'lib/vash.rb', line 83

def cleanup!
  now = Time.now.to_i
  @register.map {|k,v| clear(k) if v < now}
end

#clear(key) ⇒ Object



88
89
90
91
92
# File 'lib/vash.rb', line 88

def clear(key)
  sterilize(key)
  @register.delete key
  self.delete key
end

#merge(hsh) ⇒ Object



78
79
80
81
# File 'lib/vash.rb', line 78

def merge(hsh)
  hsh.map {|key,value| self[sterile(key)] = hsh[key]}
  self
end

#regular_readerObject



54
# File 'lib/vash.rb', line 54

alias_method :regular_reader, :[]

#regular_writerObject



53
# File 'lib/vash.rb', line 53

alias_method :regular_writer, :[]=