tisket 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/tisket/manager.rb +78 -0
- data/lib/tisket/polling.rb +33 -0
- data/lib/tisket/task.rb +22 -0
- data/lib/tisket.rb +13 -0
- metadata +48 -0
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
|
data/lib/tisket/task.rb
ADDED
@@ -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
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: []
|