module Agis

Public Instance Methods

_agis_cleanup_when_empty(redis) click to toggle source
# File lib/agis.rb, line 230
def _agis_cleanup_when_empty(redis)
  redis.del(self.agis_mailbox)
  redis.srem("AGIS_MAILBOX_GLOBAL_LIST", self.agis_mailbox)
  redis.srem("AGIS_MAILBOX_CLASS:" + self.class.to_s, self.agis_id_prelim)
  if(redis.scard("AGIS_MAILBOX_CLASS:" + self.class.to_s) == 0)
    redis.del("AGIS_MAILBOX_CLASS:" + self.class.to_s)
    redis.srem("AGIS_MAILBOX_CLASSES", self.class.to_s)
  end
end
_agis_crunch(redis, usig) click to toggle source
# File lib/agis.rb, line 240
def _agis_crunch(redis, usig)
  loop do
    redis.lock(self.agis_boxlock, life: 10) do |lock|
      a = agis_chew(redis, lock)
      next if lock.stale_key?
      u = agis_try_usig(redis, usig)
      if a == :empty
        _agis_cleanup_when_empty(redis)
        raise Agis::MessageBoxEmpty unless u
      end
      return agis_fconv(u) if u
    end
  end
end
_agis_find_global_mailboxes(redis) click to toggle source

Find all mailboxes total

# File lib/agis.rb, line 256
def _agis_find_global_mailboxes(redis)
  redis.smembers("AGIS_MAILBOX_GLOBAL_LIST")
end
acall(redis, name=nil, arg1=nil, arg2=nil, arg3=nil) click to toggle source

Alias for agis_call

# File lib/agis.rb, line 315
def acall(redis, name=nil, arg1=nil, arg2=nil, arg3=nil)
  agis_call(redis, name, arg1, arg2, arg3)
end
agis_aconv(v) click to toggle source
# File lib/agis.rb, line 43
def agis_aconv(v)
  a = ""
  case v
  when String
    a = "s:" + v
  when Symbol
    a = "s:" + v.to_s
  when Integer
    a = "i:" + v.to_s
  when Hash
    a = "h:" + v.to_json.to_s
  when Array
    a = "a:" + v.to_json.to_s
  when Float
    a = "d:" + v.to_s
  when TrueClass
    a = "t:"
  when FalseClass
    a = "f:"
  when NilClass
    a = "n:"
  else
    a = "h:" + v.to_json.to_s
  end
  return a
end
agis_boxlock() click to toggle source
# File lib/agis.rb, line 142
def agis_boxlock
  self.agis_mailbox + ".LOCK"
end
agis_call(redis, name=nil, arg1=nil, arg2=nil, arg3=nil) click to toggle source

Push a call and ncrunch immediately this returns the last return value from the queue

# File lib/agis.rb, line 293
def agis_call(redis, name=nil, arg1=nil, arg2=nil, arg3=nil)
  name ||= "AGIS_NOOP"
  until_sig = Time.now.to_s + ":" + Process.pid.to_s + Random.new.rand(4000000000).to_s + Random.new.rand(4000000000).to_s
  loop do
    begin
      redis.sadd("AGIS_MAILBOX_CLASSES", self.class.to_s)
      redis.sadd("AGIS_MAILBOX_CLASS:" + self.class.to_s, self.agis_id_prelim)
      redis.sadd("AGIS_MAILBOX_GLOBAL_LIST", self.agis_mailbox)
      redis.multi do
        redis.rpush self.agis_mailbox, "m:" + name.to_s
        redis.rpush self.agis_mailbox, agis_aconv(arg1)
        redis.rpush self.agis_mailbox, agis_aconv(arg2)
        redis.rpush self.agis_mailbox, agis_aconv(arg3)
        redis.rpush self.agis_mailbox, "r:" + until_sig
      end
      return _agis_crunch(redis, until_sig)
    rescue Agis::MessageBoxEmpty
    end
  end
end
agis_chew(redis, lock) click to toggle source
# File lib/agis.rb, line 150
def agis_chew(redis, lock)
  args = redis.lrange(self.agis_mailbox, 0, 4)
  mni  = args[0]
  if(mni and mni[0..1] == "m:")
    # don't do any signatures twice ever
    lusig = args[4][2..-1]
    #puts lusig
    if redis.hget self.agis_returnbox, lusig
      popfive redis
      return nil
    end
    mn        = mni[2..-1]
    mns       = mn.to_sym
    if mn == "AGIS_NOOP" # NOOP
      redis.hset self.agis_returnbox, lusig, "done"
      popfive(redis)
      return :next
    else
      mc        = @agis_methods[mns][:arity]
      mrm       = @agis_methods[mns][:mode]
      meti      = @agis_methods[mns][:method]
      case meti
      when Proc
        met = meti
      when Symbol
        met = self.method(meti)
      when NilClass
        met = self.method(mn.to_sym) # when proc is Nil, call the class methods all the same
      end
    end
    
    begin
      #raise Agis::RedisLockExpired if lock.stale_key?
      #begin
      #  lock.extend_life (@agis_methods[mn.to_sym][2] or 5)
      #rescue Redis::Lock::LockNotAcquired
      #  raise Agis::RedisLockExpired
      #end
      popfive(redis) if mrm == :once
      case mc
      when 0
        ret = agis_aconv(met.call())
      when 1
        ret = agis_aconv(met.call(agis_fconv(args[1])))
      when 2
        ret = agis_aconv(met.call(agis_fconv(args[1]), agis_fconv(args[2])))
      when 3
        ret = agis_aconv(met.call(agis_fconv(args[1]), agis_fconv(args[2]), agis_fconv(args[3])))
      end
      redis.multi do
        redis.hset self.agis_returnbox, lusig, ret
        popfive(redis) if mrm == :retry
      end
      return :next
    rescue Agis::RedisLockExpired => e
      puts "Agis lock expired for " + args.to_s if (@agis_debugmode == true)
      # popfive redis
      return :relock
    rescue => e
      #puts "feck"
      lock.unlock
      raise e
    end
  elsif not mni
    return :empty
  else
    puts "AGIS error: Unrecognized line!" + mni.to_s
  end
end
agis_crunch_all_records(redis) click to toggle source

Crunch all agis calls on a single model found using the find method with the agis_id or id. Must be numeric

# File lib/agis.rb, line 268
def agis_crunch_all_records(redis)
  all = agis_find_all_mailboxes(redis)
  all.each do |id|
    self.class.find(id).agis_call(redis)
  end
end
agis_crunch_all_records_new(redis) click to toggle source

Crunch all agis calls on a single model found using the new method with id set to agis_id or id

# File lib/agis.rb, line 278
def agis_crunch_all_records_new(redis)
  all = agis_find_all_mailboxes(redis)
  all.each do |id|
    self.class.new(id).agis_call(redis)
  end
end
agis_def(name, mode=:retry, timeout=nil, &b) click to toggle source

alias for agis_defm3

# File lib/agis.rb, line 118
def agis_def(name, mode=:retry, timeout=nil, &b)
  agis_defm3(name, timeout, b)
end
agis_defm0(name, mode=:retry, timeout=nil, &b) click to toggle source

create a method with no parameters

# File lib/agis.rb, line 94
def agis_defm0(name, mode=:retry, timeout=nil, &b)
  @agis_methods ||= Hash.new
  @agis_methods[name] = {arity: 0, method: b, mode: mode, timeout: timeout}
end
agis_defm1(name, mode=:retry, timeout=nil, &b) click to toggle source

create a method with one parameter

# File lib/agis.rb, line 100
def agis_defm1(name, mode=:retry, timeout=nil, &b)
  @agis_methods ||= Hash.new
  @agis_methods[name] = {arity: 1, method: b, mode: mode, timeout: timeout}
end
agis_defm2(name, mode=:retry, timeout=nil, &b) click to toggle source

create a method with two parameters

# File lib/agis.rb, line 106
def agis_defm2(name, mode=:retry, timeout=nil, &b)
  @agis_methods ||= Hash.new
  @agis_methods[name] = {arity: 2, method: b, mode: mode, timeout: timeout}
end
agis_defm3(name, mode=:retry, timeout=nil, &b) click to toggle source

create a method with three parameters

# File lib/agis.rb, line 112
def agis_defm3(name, mode=:retry, timeout=nil, &b)
  @agis_methods ||= Hash.new
  @agis_methods[name] = {arity: 3, method: b, mode: mode, timeout: timeout}
end
agis_fconv(v) click to toggle source
# File lib/agis.rb, line 70
def agis_fconv(v)
  case v[0..1]
  when "s:"
    v[2..-1]
  when "i:"
    v[2..-1].to_i
  when "h:"
    JSON.parse!(v[2..-1], symbolize_names: false)
  when "a:"
    JSON.parse!(v[2..-1], symbolize_names: false)
  when "d:"
    v[2..-1].to_f
  when "t:"
    true
  when "f:"
    false
  when "n:"
    nil
  when "m:"
    raise MethodCallInParameters
  end
end
agis_find_all_mailboxes(redis) click to toggle source

Find all mailboxes for this class

# File lib/agis.rb, line 261
def agis_find_all_mailboxes(redis)
  redis.smembers("AGIS_MAILBOX_CLASS:" + self.class.to_s)
end
agis_id_prelim() click to toggle source
# File lib/agis.rb, line 23
def agis_id_prelim
  begin
    mid = self.agis_id
  rescue NoMethodError
  end
  begin
    mid ||= self.id
  rescue NoMethodError
  end
  return mid
end
agis_mailbox() click to toggle source

the name of the key used for the Agis message box in Redis the lock is this string followed by “.LOCK”

# File lib/agis.rb, line 37
def agis_mailbox
  mid = agis_id_prelim
  raise NoAgisIDAvailable unless mid
  a = "AGIS TERMINAL : " + self.class.to_s + " : " + mid.to_s
end
agis_method(name) click to toggle source

Get method in the format

arity, method body
# File lib/agis.rb, line 287
def agis_method(name)
  @agis_methods[name]
end
agis_recall(mn, arg1=nil, arg2=nil, arg3=nil) click to toggle source

Method for calling another Agis method, or retrying. this doesn’t touch the message box because it should only be called inside an Agis method, where the box is already guaranteed to be locked

# File lib/agis.rb, line 323
def agis_recall(mn, arg1=nil, arg2=nil, arg3=nil)
  meti = @agis_methods[mn.to_sym][:method]
  case meti
  when Proc
    met = meti
  when Symbol
    met = self.method(meti)
  when NilClass
    met = self.method(mn.to_sym) # when proc is Nil, call the class methods all the same
  end
  
  case @agis_methods[mn.to_sym][:arity]
  when 0
    return met.call()
  when 1
    return met.call(arg1)
  when 2
    return met.call(arg1, arg2)
  when 3
    return met.call(arg1, arg2, arg3)
  end
end
agis_returnbox() click to toggle source
# File lib/agis.rb, line 146
def agis_returnbox
  self.agis_mailbox + ".RETN"
end
agis_try_usig(redis, usig) click to toggle source
# File lib/agis.rb, line 220
def agis_try_usig(redis, usig)
  mayb = redis.hget self.agis_returnbox, usig
  if mayb
    redis.hdel self.agis_returnbox, usig
    return mayb
  else
    return nil
  end
end
popfive(redis) click to toggle source
# File lib/agis.rb, line 132
def popfive(redis)
  redis.multi do
    redis.lpop self.agis_mailbox
    redis.lpop self.agis_mailbox
    redis.lpop self.agis_mailbox
    redis.lpop self.agis_mailbox
    redis.lpop self.agis_mailbox
  end
end
pretty_exception(args, e) click to toggle source
# File lib/agis.rb, line 122
def pretty_exception(args, e)
  ret = []
  ret << "Agis method call failed: " + args.to_s
  ret << "  " + e.class.to_s
  e.backtrace.each do |v|
    ret << v.to_s
  end
  ret
end