Marcin R. wrote:
why don’t you try Gemstone or other object-oriented databases?
besides, memcache isn’t THAT much faster then database, it’s faster
becouse it can store objects in memory, but if you need queries it
looses all it’s advantages.
greets
here’s simple object oriented DB i wrote ages ago, just throw out state
machine stuff and have phun, searching is done in ruby and really easy.
it took me one day if i remember correctly so that should be indication
of time you’d need to make simple ODB
Module responsible for handling requests informations
Information status:
- :waiting (waiting for server response)
- :progress (server reported progress)
- :results (server returned results)
- :error (j.w)
- :timeout (request timed out)
- :collect - to be garbage collected (right now for debuging
purposes)
module Informations
default time to live of message (used when expire is set to :ttl)
attr_accessor :default_ttl
default timeout - time betwen ANY actions sent by server
attr_accessor :default_timeout
use garbage collecting?
attr_accessor :gc
def init(ttl=30, timeout=30, gc=true)
@gc = gc
@default_ttl = ttl
@default_timeout = timeout
@informations={}
end
creates new informations about request, id is request id,
hash should contain additional informations (the’ll be merged)
def new_info(id, hash)
#hash=hash.dup
#hash.delete(:data)
info={}
info[:id]=id
info[:status]=:waiting
info[:timeout]=@default_timeout
info[:last_action]=info[:start]=Time.now
info[:expire]=:new
info[:ttl]=@default_ttl
info.merge! hash
@informations[id] = info
end
information state machine
checks message status - and takes care of checking state
transitions
if transition is wrong it’s ignored (no exception is rised!!)
new info is returned
def change_status(info, state)
case info[:status]
when :waiting, :progress
if [:progress, :results, :error, :timeout].include? state
info[:status]=state
info[:stop]=Time.now unless state == :progress
info[:last_action]=Time.now
end
when :results, :error, :timeout
if state == :collect
info[:status]=state
info[:last_action]=Time.now
end
end
info
end
checks if message timed out
def timeout?(info)
change_status(info, :timeout) if ([:wait, :progress].include?
info[:status]) && (Time.now > info[:last_action] + info[:timeout])
end
finds information with id
takes care of marking msg, as timed out/ to be collected
returns info
def find(id)
self.timeout?(@informations[id])
begin
info = @informations[id].dup
#return nil if info[:state]==:collect # don't return expired
infos
if info[:expire]==:first
@gc ? change_status(@informations[id], :collect) :
@informations.delete(id)
end
if (info[:expire]==:ttl) && (Time.now < info[:last_action] +
info[:ttl])
@gc ? change_status(@informations[id], :collect) :
@informations.delete(id)
end
rescue Exception
info=nil
end
#info[:last_action]=Time.now preventing expire ?
info
end
finds all message matching criteria block
or checks if :server_id and :name provided in hash match
block should return true if information should be returned
Examples:
find_all({:name=>“actions”, :server_id=>“121516136171356151”})
find_all() {|i| i[:last_action] > Time.now-60 }
returns all informations that state changed minute or less ago
find_all() {|i| i[:status]==:error}
returns all messages that returned errors
gc! if find_all() {|i| i[:status]==:collect}.size > 1000
clears old messages when there’s more then 1000 of them
def find_all(hash={})
res = []
@informations.each_pair { |k,v|
if block_given?
res << self.find(k) if yield(v.dup)
else
catch(:no_match) {
# add more here!!
[:server_id, :name].each { |x|
throw(:no_match) if hash[x] && hash[x]!=v[x]
}
res << self.find(k)
}
end
}
res.empty? ? nil : res
end
clears all messages marked for collection
def gc!
@informations.each_pair { |k,v|
@informations.delete(k) if v[:status]==:collect
}
end
end