記事は Qiita に書いています。
Created
December 28, 2015 23:05
-
-
Save hakobera/f1166b697e0e3f5f37f8 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'tsort' | |
class DAG | |
include TSort | |
def initialize | |
@tasks = {} | |
end | |
def tsort_each_node(&block) | |
@tasks.each_key(&block) | |
end | |
def tsort_each_child(node, &block) | |
@tasks.fetch(node).each(&block) | |
end | |
def add_task(task) | |
_add_task(nil, task) | |
end | |
private | |
def _add_task(parent, task) | |
unless @tasks[task] | |
@tasks[task] = task.requires | |
task.requires.each do |r| | |
_add_task(task, r) | |
end | |
end | |
task | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require_relative 'workflow' | |
require_relative 'task' | |
require_relative 'file_target' | |
class EchoTask < Task | |
def output | |
FileTarget.new("/tmp/#{self.class.name}.txt") | |
end | |
def run | |
puts "#{self.class.name}#run" | |
File.write(output.path, "done") | |
end | |
end | |
class TaskA < EchoTask | |
def requires | |
[ TaskB.new, TaskC.new ] | |
end | |
end | |
class TaskB < EchoTask | |
def requires | |
[ TaskD.new ] | |
end | |
end | |
class TaskC < EchoTask | |
def requires | |
[ TaskD.new ] | |
end | |
end | |
class TaskD < EchoTask | |
end | |
Workflow.new.run(TaskA.new) | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require_relative 'target' | |
class FileTarget < Target | |
attr_reader :path | |
def initialize(path) | |
@path = path | |
end | |
def exists? | |
File.exist?(path) | |
end | |
end | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Target | |
def exists? | |
raise NotImplementedError, "You must implement #{self.class}##{__method__}" | |
end | |
end | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Task | |
def output | |
raise NotImplementedError, "You must implement #{self.class}##{__method__}" | |
end | |
def run | |
raise NotImplementedError, "You must implement #{self.class}##{__method__}" | |
end | |
def requires | |
[] # If you need to define task dependencies, override in subclass | |
end | |
def eql?(other) | |
self.hash == other.hash | |
end | |
def hash | |
self.class.name.hash | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require_relative 'dag' | |
class Workflow | |
def run(task) | |
dag = DAG.new | |
dag.add_task(task) | |
dag.tsort.each do |t| | |
t.run unless t.output.exists? | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment