class Taskinator::Persistence::RedisDeserializationVisitor

Public Class Methods

new(key, instance_cache={}) click to toggle source

initialize with the store key for the instance to deserialize

optionally, pass in a hash which is used to cache the deserialized instances for the given key

# File lib/taskinator/persistence.rb, line 464
def initialize(key, instance_cache={})
  @key = key
  @instance_cache = instance_cache

  # pre-load all the attributes to reduce redis hits
  Taskinator.redis do |conn|
    keys, values = conn.multi do
      conn.hkeys(@key)
      conn.hvals(@key)
    end
    @attribute_values = Hash[keys.collect(&:to_sym).zip(values)]
  end
end

Public Instance Methods

visit() click to toggle source

the starting point for deserializing the instance

# File lib/taskinator/persistence.rb, line 479
def visit
  return unless @attribute_values.key?(:type)

  type = @attribute_values[:type]
  klass = Kernel.const_get(type)

  #
  # NOTE:
  #  using Class#allocate here so that the
  #  instance is created without the need to
  #  call the Class#new method which has constructor
  #  arguments which are unknown at this stage
  #
  @instance = klass.allocate
  @instance.accept(self)
  @instance
end
visit_args(attribute) click to toggle source

deserializes the arguments using YAML#load method

# File lib/taskinator/persistence.rb, line 557
def visit_args(attribute)
  yaml = @attribute_values[attribute]
  if yaml
    values = Taskinator::Persistence.deserialize(yaml)
    @instance.instance_variable_set("@#{attribute}", values)
  end
end
visit_attribute(attribute) { |value| ... } click to toggle source
# File lib/taskinator/persistence.rb, line 520
def visit_attribute(attribute)
  value = @attribute_values[attribute]
  if value
    # converted block given?
    if block_given?
      @instance.instance_variable_set("@#{attribute}", yield(value))
    else
      @instance.instance_variable_set("@#{attribute}", value)
    end
  end
end
visit_attribute_enum(attribute, type) click to toggle source

NB: assumes the enum type's members have integer values!

# File lib/taskinator/persistence.rb, line 539
def visit_attribute_enum(attribute, type)
  visit_attribute(attribute) do |value|
    const_value = type.constants.select {|c| type.const_get(c) == value.to_i }.first
    const_value ?
      type.const_get(const_value) :
      (defined?(type::Default) ? type::Default : nil)
  end
end
visit_attribute_time(attribute) click to toggle source
# File lib/taskinator/persistence.rb, line 532
def visit_attribute_time(attribute)
  visit_attribute(attribute) do |value|
    Time.parse(value)
  end
end
visit_process(attribute) click to toggle source
# File lib/taskinator/persistence.rb, line 497
def visit_process(attribute)
  uuid = @attribute_values[attribute]
  @instance.instance_variable_set("@#{attribute}", lazy_instance_for(Process, uuid)) if uuid
end
visit_process_reference(attribute) click to toggle source
# File lib/taskinator/persistence.rb, line 510
def visit_process_reference(attribute)
  uuid = @attribute_values[attribute]
  @instance.instance_variable_set("@#{attribute}", lazy_instance_for(Process, uuid)) if uuid
end
visit_task_reference(attribute) click to toggle source
# File lib/taskinator/persistence.rb, line 515
def visit_task_reference(attribute)
  uuid = @attribute_values[attribute]
  @instance.instance_variable_set("@#{attribute}", lazy_instance_for(Task, uuid)) if uuid
end
visit_tasks(tasks) click to toggle source
# File lib/taskinator/persistence.rb, line 502
def visit_tasks(tasks)
  # tasks are a linked list, so just get the first one
  Taskinator.redis do |conn|
    uuid = conn.lindex("#{@key}:tasks", 0)
    tasks.attach(lazy_instance_for(Task, uuid), conn.get("#{@key}.count").to_i) if uuid
  end
end
visit_type(attribute) click to toggle source
# File lib/taskinator/persistence.rb, line 548
def visit_type(attribute)
  value = @attribute_values[attribute]
  if value
    type = Kernel.const_get(value)
    @instance.instance_variable_set("@#{attribute}", type)
  end
end

Private Instance Methods

lazy_instance_for(base, uuid) click to toggle source

creates a proxy for the instance which will only fetch the instance when used this offers not only an optimization at load time, but also prevents need to load the entire object graph everytime a worker fetches an arbitrary instance to perform it's work

# File lib/taskinator/persistence.rb, line 575
def lazy_instance_for(base, uuid)
  type = Taskinator.redis do |conn|
    conn.hget(base.key_for(uuid), :type)
  end
  klass = Kernel.const_get(type)
  LazyLoader.new(klass, uuid, @instance_cache)
end