lib/taskinator/persistence.rb in taskinator-0.3.9 vs lib/taskinator/persistence.rb in taskinator-0.3.10
- old
+ new
@@ -66,10 +66,19 @@
true
end
end
end
+ def to_xml
+ builder = ::Builder::XmlMarkup.new
+ builder.instruct!
+ builder.tag!('process', :key => self.key) do |xml|
+ XmlSerializationVisitor.new(xml, self).visit
+ end
+ builder
+ end
+
# the persistence key
def key
@key ||= self.class.key_for(self.uuid)
end
@@ -260,11 +269,14 @@
def visit_tasks(tasks)
tasks.each do |task|
RedisSerializationVisitor.new(@conn, task, @base_visitor).visit
@conn.rpush "#{@key}:tasks", task.uuid
- @base_visitor.incr_task_count unless task.is_a?(Task::SubProcess)
+ unless task.is_a?(Task::SubProcess)
+ incr_task_count unless self == @base_visitor
+ @base_visitor.incr_task_count
+ end
end
end
def visit_attribute(attribute)
value = @instance.send(attribute)
@@ -302,9 +314,121 @@
if (yaml.bytesize / (1024.0**2)) > 2
Taskinator.logger.warn("Large argument data detected for '#{self.to_s}'. Consider using intrinsic types instead, or try to reduce the amount of data provided.")
end
@hmset += [attribute, yaml]
+ end
+
+ def task_count
+ @task_count
+ end
+
+ def incr_task_count
+ @task_count += 1
+ end
+ end
+
+ class XmlSerializationVisitor < Taskinator::Visitor::Base
+
+ #
+ # the redis connection is passed in since it is
+ # in the multi statement mode in order to produce
+ # one roundtrip to the redis server
+ #
+
+ attr_reader :builder
+ attr_reader :instance
+
+ def initialize(builder, instance, base_visitor=self)
+ @builder = builder
+ @instance = instance
+ @key = instance.key
+ @root = base_visitor.instance
+ @base_visitor = base_visitor
+ @task_count = 0
+ end
+
+ # the starting point for serializing the instance
+ def visit
+ @attributes = []
+ @attributes << [:type, @instance.class.name]
+ @attributes << [:process_uuid, @root.uuid]
+ @attributes << [:state, :initial]
+
+ @instance.accept(self)
+
+ @attributes << [:task_count, @task_count]
+
+ @attributes.each do |(name, value)|
+ builder.tag!('attribute', name => value)
+ end
+
+ self
+ end
+
+ def visit_process(attribute)
+ process = @instance.send(attribute)
+ if process
+ @attributes << [attribute, process.uuid]
+
+ builder.tag!('process', :key => process.key) do |xml|
+ XmlSerializationVisitor.new(xml, process, @base_visitor).visit
+ end
+ end
+ end
+
+ def visit_tasks(tasks)
+ builder.tag!('tasks') do |xml|
+ tasks.each do |task|
+ xml.tag!('task', :key => task.key) do |xml2|
+ XmlSerializationVisitor.new(xml2, task, @base_visitor).visit
+ unless task.is_a?(Task::SubProcess)
+ incr_task_count unless self == @base_visitor
+ @base_visitor.incr_task_count
+ end
+ end
+ end
+ end
+ end
+
+ def visit_attribute(attribute)
+ value = @instance.send(attribute)
+ @attributes << [attribute, value] if value
+ end
+
+ def visit_attribute_time(attribute)
+ visit_attribute(attribute)
+ end
+
+ def visit_attribute_enum(attribute, type)
+ visit_attribute(attribute)
+ end
+
+ def visit_process_reference(attribute)
+ process = @instance.send(attribute)
+ @attributes << [attribute, process.uuid] if process
+ end
+
+ def visit_task_reference(attribute)
+ task = @instance.send(attribute)
+ @attributes << [attribute, task.uuid] if task
+ end
+
+ def visit_type(attribute)
+ type = @instance.send(attribute)
+ @attributes << [attribute, type.name] if type
+ end
+
+ def visit_args(attribute)
+ values = @instance.send(attribute)
+ yaml = Taskinator::Persistence.serialize(values)
+
+ # greater than 2 MB?
+ if (yaml.bytesize / (1024.0**2)) > 2
+ Taskinator.logger.warn("Large argument data detected for '#{self.to_s}'. Consider using intrinsic types instead, or try to reduce the amount of data provided.")
+ end
+
+ @attributes << [attribute, yaml]
end
def task_count
@task_count
end