tisket 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []