Marcin Raczkowski 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