Skip to content

Instantly share code, notes, and snippets.

@yrashk
Created July 12, 2012 15:09
Show Gist options
  • Save yrashk/3098723 to your computer and use it in GitHub Desktop.
Save yrashk/3098723 to your computer and use it in GitHub Desktop.
require 'tendita'
require 'uuid'
require "socket"
 
class Session
  attr_reader :key
  attr_accessor :expires
   
  def initialize(expires=nil)
    @uuid = UUID.new
    @key = @uuid.generate
    @data = {}
    @expires = expires
  end
 
  def [](k)
    @data[k]
  end
 
  def []=(k,v)
    @data[k]=v
  end
 
  def self.locate(client,key)
    data = client.coord([
                  Tendita::Coord::Plan.new(:service => SessionService.service_name,
                                           :key => key,
                                           :n => 3),
                  Tendita::Coord::Send.new(:data => SessionService.encode(nil)),
                  Tendita::Coord::Receive.new(:n => 2)
                  ])
    data.map{|loc| SessionService.decode(loc)}
  end
 
  def locate(client)
    self.class.locate(client, key)
  end
 
  def self.find(client,key)
    data = client.coord([
                  Tendita::Coord::Plan.new(:service => SessionService.service_name,
                                           :key => key,
                                           :n => 3),
                  Tendita::Coord::Send.new(:data => SessionService.encode(key)),
                  Tendita::Coord::Receive.new(:n => 1)
                  ])
    SessionService.decode(data.first)
  end
 
  def save(client)
    client.coord([
                  Tendita::Coord::Plan.new(:service => SessionService.service_name,
                                           :key => key,
                                           :n => 3),
                  Tendita::Coord::Send.new(:data => SessionService.encode(self)),
                  Tendita::Coord::Receive.new(:n => 2)
                  ])
    true
  end
end
 
class SessionService < Tendita::Service
  service_name "session"
  encoding :ruby
 
  def initialize(*args)
    super
    @sessions = {}
  end
 
  def handle(data, coordinator)
    case data
    when Session # store a session
      @sessions[data.key] = data
      reply :ok
    when String # retrieve a session
      key = data
      session = @sessions[key]
      if session.is_a?(Session) and (not session.expires.nil?) and session.expires <= Time.now # expired
        @sessions.delete(key)
        reply nil
      else
        reply session
      end
    when nil # location
      reply "Partition #{partition} on host #{Socket.gethostname}"
    end
  end
 
  def handoff ; @sessions ; end
  def takeover(k,v) ; @sessions[k] = v ; end
  def delete ; @sessions = {} ; end
  def size ; @sessions.size ; end
 
end
 
if ARGV == ["worker"]
  worker = Tendita::Worker.new([SessionService])
  worker.loop
else
  $client = Tendita::Client.new
  def client ; $client ; end
  require 'irb'
  IRB.start
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment