tisket 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5053145f8a0113cf49a5cb198a72c4507dd52389
4
+ data.tar.gz: f6e8f4a81cf9899cc0dc15138a293d67253f0080
5
+ SHA512:
6
+ metadata.gz: 472ed82c0f3d12596fdbcd5a1bff733c34466f8439e9c09cb049069c2f0b8ad346bd788d80740fb19d578bcf7841f319e608141e12cb74b9160fdb42d7fa5d43
7
+ data.tar.gz: aac6a2637a35fe86701c94f9a3f761455ce2354bc7bba9be7ba9e30056c1eb971dbc5e0cdf0b2c42113c3fa188b1a71fa2a45ddd90e7e330ba22dfd9221f8ee0
@@ -0,0 +1,78 @@
1
+ require 'set'
2
+
3
+ class Tisket::Manager
4
+
5
+ attr_accessor *%i[ backward_deps forward_deps initial_set specs threads ]
6
+
7
+ def initialize(specs)
8
+ specs = convert_specs(specs)
9
+
10
+ self.backward_deps = {}
11
+ self.forward_deps = Hash.new{|h,k| h[k] = Set.new }
12
+ self.initial_set = Set.new
13
+
14
+ specs.each do |id,spec|
15
+ if (deps = spec.delete(:_requires)) && !deps.empty?
16
+ deps.each{|d| forward_deps[d] << id }
17
+ backward_deps[id] = deps
18
+ else
19
+ initial_set << id
20
+ end
21
+ end
22
+
23
+ self.specs = specs
24
+ end
25
+
26
+ def complete(id)
27
+ puts "completing #{id}"
28
+ next_tasks = Set.new
29
+ forward_deps[id].each do |dep|
30
+ bw = backward_deps[dep]
31
+ bw.delete(id)
32
+ next_tasks << dep if bw.empty?
33
+ end
34
+ enqueue(next_tasks)
35
+ end
36
+
37
+ def enqueue(ids)
38
+ ids.map{|id| run_one(id) }.map(&:join)
39
+ end
40
+
41
+ def run_one(id)
42
+ puts "running #{id}"
43
+ spec = specs[id].dup
44
+ task = Object.const_get(
45
+ spec.delete(:_class) || camelize(id)
46
+ ).new(self, id: id, **spec)
47
+ th = Thread.new{ task.run }
48
+ th.run
49
+ th
50
+ end
51
+
52
+ def run
53
+ enqueue(initial_set)
54
+ end
55
+
56
+ protected
57
+
58
+ def convert_specs(node)
59
+ case node
60
+ when Hash
61
+ # Some YAML parsers - including Psych 2 - don't have builtin support for
62
+ # sets :(
63
+ if !node.empty? && node.values.all?(&:nil?)
64
+ Set.new(node.keys.map(&:to_sym))
65
+ else
66
+ node.inject({}){|h,(k,v)| h.update(k.to_sym => convert_specs(v)) }
67
+ end
68
+ when Array
69
+ node.map{|a| convert_specs(a) }
70
+ else
71
+ node
72
+ end
73
+ end
74
+
75
+ def camelize(snake_case)
76
+ snake_case.scan(/[^_]+_?/).map{|s| s.chomp('_') }.map(&:capitalize).join
77
+ end
78
+ end
@@ -0,0 +1,33 @@
1
+ class Tisket::Task::Polling < Tisket::Task
2
+
3
+ def self.attr_names
4
+ super + %i[ max_retries poll_interval ]
5
+ end
6
+
7
+ def self.defaults
8
+ super.merge(
9
+ max_retries: 10,
10
+ poll_interval: 30 ) # seconds
11
+ end
12
+
13
+ def done?
14
+ raise 'Abstract method'
15
+ end
16
+
17
+ def poll
18
+ @max_retries.times do
19
+ done? ? break : sleep(@poll_interval)
20
+ end
21
+ end
22
+
23
+ def run
24
+ super do
25
+ start
26
+ poll
27
+ end
28
+ end
29
+
30
+ def start
31
+ raise 'Abstract method'
32
+ end
33
+ end
@@ -0,0 +1,22 @@
1
+ class Tisket::Task
2
+
3
+ def self.attr_names
4
+ %i[ id manager ]
5
+ end
6
+
7
+ def self.defaults
8
+ { }
9
+ end
10
+
11
+ def initialize(manager = nil, **kwargs)
12
+ self.class.attr_names.each do |a|
13
+ instance_variable_set("@#{a}", kwargs[a] || self.class.defaults[a])
14
+ end
15
+ @manager = manager
16
+ end
17
+
18
+ def run
19
+ yield
20
+ @manager.complete(@id) if @manager
21
+ end
22
+ end
data/lib/tisket.rb ADDED
@@ -0,0 +1,13 @@
1
+ require 'yaml'
2
+
3
+ module Tisket
4
+ def self.run_spec(name)
5
+ Manager.new(YAML.load_file(name)).run
6
+ end
7
+ end
8
+
9
+ $LOAD_PATH << File.dirname(__FILE__)
10
+
11
+ require 'tisket/task'
12
+ require 'tisket/manager'
13
+ require 'tisket/polling'
metadata ADDED
@@ -0,0 +1,48 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tisket
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Michael
8
+ - Pabst
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2016-12-30 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Simple Ruby workflow executor
15
+ email: michael.k.pabst@gmail.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - lib/tisket.rb
21
+ - lib/tisket/manager.rb
22
+ - lib/tisket/polling.rb
23
+ - lib/tisket/task.rb
24
+ homepage: https://github.com/mpabst/tisket
25
+ licenses:
26
+ - CC-BY-NC-SA-4.0
27
+ metadata: {}
28
+ post_install_message:
29
+ rdoc_options: []
30
+ require_paths:
31
+ - lib
32
+ required_ruby_version: !ruby/object:Gem::Requirement
33
+ requirements:
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: '0'
37
+ required_rubygems_version: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ requirements: []
43
+ rubyforge_project:
44
+ rubygems_version: 2.5.1
45
+ signing_key:
46
+ specification_version: 4
47
+ summary: Tisket
48
+ test_files: []