abid 0.3.0.pre.alpha.2 → 0.3.0.pre.alpha.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/exe/abid +1 -1
- data/lib/abid.rb +21 -6
- data/lib/abid/application.rb +17 -40
- data/lib/abid/cli.rb +8 -7
- data/lib/abid/cli/assume.rb +4 -3
- data/lib/abid/cli/list.rb +5 -4
- data/lib/abid/cli/migrate.rb +4 -5
- data/lib/abid/cli/revoke.rb +5 -4
- data/lib/abid/config.rb +3 -3
- data/lib/abid/dsl_definition.rb +3 -3
- data/lib/abid/engine.rb +13 -0
- data/lib/abid/engine/executor.rb +126 -0
- data/lib/abid/engine/process.rb +137 -0
- data/lib/abid/engine/process_manager.rb +56 -0
- data/lib/abid/engine/scheduler.rb +96 -0
- data/lib/abid/engine/waiter.rb +83 -0
- data/lib/abid/engine/worker_manager.rb +123 -0
- data/lib/abid/environment.rb +48 -0
- data/lib/abid/job.rb +49 -7
- data/lib/abid/job_manager.rb +22 -0
- data/lib/abid/mixin_task.rb +2 -2
- data/lib/abid/rake_extensions.rb +12 -4
- data/lib/abid/rake_extensions/task.rb +4 -117
- data/lib/abid/state_manager/database.rb +21 -17
- data/lib/abid/state_manager/state.rb +65 -15
- data/lib/abid/state_manager/state_proxy.rb +65 -0
- data/lib/abid/task.rb +1 -15
- data/lib/abid/version.rb +1 -1
- metadata +12 -8
- data/lib/abid/abid_module.rb +0 -19
- data/lib/abid/session.rb +0 -92
- data/lib/abid/state.rb +0 -193
- data/lib/abid/state_manager.rb +0 -17
- data/lib/abid/waiter.rb +0 -110
- data/lib/abid/worker.rb +0 -56
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
module Abid
|
4
|
+
module StateManager
|
5
|
+
# StateProxy provides accessor methods to State for Job#state.
|
6
|
+
#
|
7
|
+
# StateProxy holds a reference to the job, and find corresponding state
|
8
|
+
# every time when needed.
|
9
|
+
#
|
10
|
+
# Use StateProxy#find if you have to access the undergrounding State object
|
11
|
+
# many times.
|
12
|
+
class StateProxy
|
13
|
+
def initialize(job)
|
14
|
+
@job = job
|
15
|
+
@states = job.env.db.states
|
16
|
+
end
|
17
|
+
|
18
|
+
# Find underlying State object
|
19
|
+
#
|
20
|
+
# @return [State] state corresponding the job.
|
21
|
+
def find
|
22
|
+
if @job.volatile?
|
23
|
+
@states.init_by_job(@job).tap(&:freeze)
|
24
|
+
else
|
25
|
+
@states.find_or_init_by_job(@job).tap(&:freeze)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
alias instance find
|
29
|
+
|
30
|
+
# Update the state to started unless volatile.
|
31
|
+
# @see State.start
|
32
|
+
def start
|
33
|
+
return if @job.dryrun? || @job.volatile?
|
34
|
+
@states.start(@job)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Try to update the state to started unless volatile.
|
38
|
+
# @see State.start
|
39
|
+
# @return [Boolean] false if already running
|
40
|
+
def try_start
|
41
|
+
start
|
42
|
+
true
|
43
|
+
rescue AlreadyRunningError
|
44
|
+
false
|
45
|
+
end
|
46
|
+
|
47
|
+
# Update the state to SUCCESSED / FAILED unless volatile.
|
48
|
+
# @see State.finish
|
49
|
+
def finish(error = nil)
|
50
|
+
return if @job.dryrun? || @job.volatile?
|
51
|
+
@states.finish(@job, error)
|
52
|
+
end
|
53
|
+
|
54
|
+
def assume(force: false)
|
55
|
+
@states.assume(@job, force: force)
|
56
|
+
end
|
57
|
+
|
58
|
+
# for testing
|
59
|
+
def mock_fail(error)
|
60
|
+
start
|
61
|
+
finish(error)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
data/lib/abid/task.rb
CHANGED
@@ -104,20 +104,6 @@ module Abid
|
|
104
104
|
play.run
|
105
105
|
end
|
106
106
|
|
107
|
-
def concerned?
|
108
|
-
state.reload
|
109
|
-
|
110
|
-
if !application.options.repair && state.failed? && !top_level?
|
111
|
-
fail "#{name} -- task has been failed"
|
112
|
-
end
|
113
|
-
|
114
|
-
application.options.repair || !state.successed?
|
115
|
-
end
|
116
|
-
|
117
|
-
def needed?
|
118
|
-
!state.successed? || prerequisite_tasks.any? { |t| t.session.successed? }
|
119
|
-
end
|
120
|
-
|
121
107
|
def bind_play_hooks(tag, to = nil)
|
122
108
|
to ||= tag
|
123
109
|
hooks[to] = [proc { |*args| call_play_hooks(tag, *args) }]
|
@@ -130,7 +116,7 @@ module Abid
|
|
130
116
|
|
131
117
|
class <<self
|
132
118
|
def define_play(*args, &block) # :nodoc:
|
133
|
-
|
119
|
+
Abid.application.define_play(self, *args, &block)
|
134
120
|
end
|
135
121
|
end
|
136
122
|
end
|
data/lib/abid/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: abid
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.0.pre.alpha.
|
4
|
+
version: 0.3.0.pre.alpha.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Hikaru Ojima
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-01-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -174,7 +174,6 @@ files:
|
|
174
174
|
- exe/abidsc
|
175
175
|
- lib/Abidfile.rb
|
176
176
|
- lib/abid.rb
|
177
|
-
- lib/abid/abid_module.rb
|
178
177
|
- lib/abid/application.rb
|
179
178
|
- lib/abid/cli.rb
|
180
179
|
- lib/abid/cli/assume.rb
|
@@ -184,8 +183,17 @@ files:
|
|
184
183
|
- lib/abid/cli/table_formatter.rb
|
185
184
|
- lib/abid/config.rb
|
186
185
|
- lib/abid/dsl_definition.rb
|
186
|
+
- lib/abid/engine.rb
|
187
|
+
- lib/abid/engine/executor.rb
|
188
|
+
- lib/abid/engine/process.rb
|
189
|
+
- lib/abid/engine/process_manager.rb
|
190
|
+
- lib/abid/engine/scheduler.rb
|
191
|
+
- lib/abid/engine/waiter.rb
|
192
|
+
- lib/abid/engine/worker_manager.rb
|
193
|
+
- lib/abid/environment.rb
|
187
194
|
- lib/abid/error.rb
|
188
195
|
- lib/abid/job.rb
|
196
|
+
- lib/abid/job_manager.rb
|
189
197
|
- lib/abid/mixin_task.rb
|
190
198
|
- lib/abid/params_format.rb
|
191
199
|
- lib/abid/params_parser.rb
|
@@ -193,16 +201,12 @@ files:
|
|
193
201
|
- lib/abid/play_core.rb
|
194
202
|
- lib/abid/rake_extensions.rb
|
195
203
|
- lib/abid/rake_extensions/task.rb
|
196
|
-
- lib/abid/session.rb
|
197
|
-
- lib/abid/state.rb
|
198
|
-
- lib/abid/state_manager.rb
|
199
204
|
- lib/abid/state_manager/database.rb
|
200
205
|
- lib/abid/state_manager/state.rb
|
206
|
+
- lib/abid/state_manager/state_proxy.rb
|
201
207
|
- lib/abid/task.rb
|
202
208
|
- lib/abid/task_manager.rb
|
203
209
|
- lib/abid/version.rb
|
204
|
-
- lib/abid/waiter.rb
|
205
|
-
- lib/abid/worker.rb
|
206
210
|
- migrations/01_create_state_table.rb
|
207
211
|
homepage: https://github.com/ojima-h/abid
|
208
212
|
licenses:
|
data/lib/abid/abid_module.rb
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
module Abid
|
2
|
-
extend Rake
|
3
|
-
|
4
|
-
class << self
|
5
|
-
def application
|
6
|
-
return @application if @application
|
7
|
-
self.application = Abid::Application.new
|
8
|
-
end
|
9
|
-
|
10
|
-
def application=(app)
|
11
|
-
@application = app
|
12
|
-
Rake.application = app
|
13
|
-
end
|
14
|
-
|
15
|
-
def config
|
16
|
-
@config ||= Config.new
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
data/lib/abid/session.rb
DELETED
@@ -1,92 +0,0 @@
|
|
1
|
-
module Abid
|
2
|
-
class Session
|
3
|
-
extend MonitorMixin
|
4
|
-
|
5
|
-
%w(successed skipped failed canceled).each do |result|
|
6
|
-
define_method(:"#{result}?") { @result == result.to_sym }
|
7
|
-
end
|
8
|
-
attr_reader :error
|
9
|
-
|
10
|
-
def initialize(task)
|
11
|
-
@task = task
|
12
|
-
@state = task.state
|
13
|
-
|
14
|
-
@entered = false
|
15
|
-
@locked = false
|
16
|
-
@result = nil
|
17
|
-
@error = nil
|
18
|
-
@ivar = Concurrent::IVar.new
|
19
|
-
|
20
|
-
@on_success = []
|
21
|
-
@on_fail = []
|
22
|
-
end
|
23
|
-
|
24
|
-
def synchronize(&block)
|
25
|
-
self.class.synchronize(&block)
|
26
|
-
end
|
27
|
-
|
28
|
-
def enter(&block)
|
29
|
-
synchronize do
|
30
|
-
return @ivar if @entered
|
31
|
-
@entered = true
|
32
|
-
end
|
33
|
-
block.call
|
34
|
-
@ivar
|
35
|
-
end
|
36
|
-
|
37
|
-
def capture_exception(&block)
|
38
|
-
block.call
|
39
|
-
rescue Exception => e
|
40
|
-
self.fail(e)
|
41
|
-
end
|
42
|
-
|
43
|
-
def add_observer(*args, &block)
|
44
|
-
@ivar.add_observer(*args, &block)
|
45
|
-
end
|
46
|
-
|
47
|
-
def lock
|
48
|
-
synchronize do
|
49
|
-
@state.start unless @locked
|
50
|
-
@locked = true
|
51
|
-
true
|
52
|
-
end
|
53
|
-
rescue AbidErrorTaskAlreadyRunning
|
54
|
-
false
|
55
|
-
end
|
56
|
-
|
57
|
-
def unlock(error = nil)
|
58
|
-
synchronize do
|
59
|
-
@state.finish(error) if @locked
|
60
|
-
@locked = false
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
def success
|
65
|
-
unlock
|
66
|
-
@result = :successed
|
67
|
-
@ivar.try_set(true)
|
68
|
-
end
|
69
|
-
|
70
|
-
def skip
|
71
|
-
unlock
|
72
|
-
@result = :skipped
|
73
|
-
@ivar.try_set(false)
|
74
|
-
end
|
75
|
-
|
76
|
-
def fail(error)
|
77
|
-
@result = :failed
|
78
|
-
@error = error
|
79
|
-
unlock(error)
|
80
|
-
@ivar.fail(error) rescue Concurrent::MultipleAssignmentError
|
81
|
-
rescue Exception => e
|
82
|
-
@ivar.fail(e) rescue Concurrent::MultipleAssignmentError
|
83
|
-
end
|
84
|
-
|
85
|
-
def cancel(error)
|
86
|
-
unlock(error)
|
87
|
-
@result = :canceled
|
88
|
-
@error = error
|
89
|
-
@ivar.fail(error) rescue Concurrent::MultipleAssignmentError
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
data/lib/abid/state.rb
DELETED
@@ -1,193 +0,0 @@
|
|
1
|
-
module Abid
|
2
|
-
class AbidErrorTaskAlreadyRunning < StandardError; end
|
3
|
-
|
4
|
-
class State
|
5
|
-
extend Forwardable
|
6
|
-
extend MonitorMixin
|
7
|
-
|
8
|
-
RUNNING = 1
|
9
|
-
SUCCESSED = 2
|
10
|
-
FAILED = 3
|
11
|
-
|
12
|
-
STATES = constants.map { |c| [const_get(c), c] }.to_h
|
13
|
-
|
14
|
-
@cache = {}
|
15
|
-
class <<self
|
16
|
-
def find(task)
|
17
|
-
synchronize { @cache[task.object_id] ||= new(task) }
|
18
|
-
end
|
19
|
-
|
20
|
-
def list(pattern: nil, started_before: nil, started_after: nil)
|
21
|
-
dataset = StateManager.database[:states]
|
22
|
-
|
23
|
-
dataset = dataset.where { start_time < started_before } if started_before
|
24
|
-
dataset = dataset.where { start_time > started_after } if started_after
|
25
|
-
dataset = dataset.order(:start_time)
|
26
|
-
|
27
|
-
dataset.map do |record|
|
28
|
-
next if pattern && record[:name] !~ pattern
|
29
|
-
{
|
30
|
-
id: record[:id],
|
31
|
-
name: record[:name],
|
32
|
-
params: deserialize(record[:params]),
|
33
|
-
state: STATES[record[:state]],
|
34
|
-
start_time: record[:start_time],
|
35
|
-
end_time: record[:end_time]
|
36
|
-
}
|
37
|
-
end.compact
|
38
|
-
end
|
39
|
-
|
40
|
-
def revoke(id)
|
41
|
-
db = StateManager.database
|
42
|
-
db.transaction do
|
43
|
-
running = db[:states].where(id: id, state: RUNNING).count > 0
|
44
|
-
fail 'task is now running' if running
|
45
|
-
db[:states].where(id: id).delete
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def serialize(params)
|
50
|
-
YAML.dump(params)
|
51
|
-
end
|
52
|
-
|
53
|
-
def deserialize(bytes)
|
54
|
-
YAML.load(bytes)
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
def_delegators 'self.class', :serialize, :deserialize
|
59
|
-
|
60
|
-
def initialize(task)
|
61
|
-
@task = task
|
62
|
-
@record = nil
|
63
|
-
@started = false
|
64
|
-
reload
|
65
|
-
end
|
66
|
-
|
67
|
-
def database
|
68
|
-
StateManager.database
|
69
|
-
end
|
70
|
-
|
71
|
-
def dataset
|
72
|
-
database[:states]
|
73
|
-
end
|
74
|
-
|
75
|
-
def disabled?
|
76
|
-
@task.volatile? || Rake.application.options.disable_state
|
77
|
-
end
|
78
|
-
|
79
|
-
def preview?
|
80
|
-
Rake.application.options.dryrun || Rake.application.options.preview
|
81
|
-
end
|
82
|
-
|
83
|
-
def reload
|
84
|
-
return if disabled?
|
85
|
-
|
86
|
-
if @record
|
87
|
-
id = @record[:id]
|
88
|
-
@record = dataset.where(id: id).first
|
89
|
-
else
|
90
|
-
@record = dataset.where(digest: digest).to_a.find do |r|
|
91
|
-
[@task.name, @task.params].eql? [r[:name], deserialize(r[:params])]
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
def id
|
97
|
-
@record[:id] if @record
|
98
|
-
end
|
99
|
-
|
100
|
-
def state
|
101
|
-
@record[:state] if @record
|
102
|
-
end
|
103
|
-
|
104
|
-
def running?
|
105
|
-
state == RUNNING
|
106
|
-
end
|
107
|
-
|
108
|
-
def successed?
|
109
|
-
state == SUCCESSED
|
110
|
-
end
|
111
|
-
|
112
|
-
def failed?
|
113
|
-
state == FAILED
|
114
|
-
end
|
115
|
-
|
116
|
-
def not_found?
|
117
|
-
!disabled? && @record.nil?
|
118
|
-
end
|
119
|
-
|
120
|
-
def assume
|
121
|
-
fail 'cannot revoke volatile task' if disabled?
|
122
|
-
|
123
|
-
database.transaction do
|
124
|
-
reload
|
125
|
-
fail 'task is now running' if running?
|
126
|
-
|
127
|
-
new_state = {
|
128
|
-
state: SUCCESSED,
|
129
|
-
start_time: Time.now,
|
130
|
-
end_time: Time.now
|
131
|
-
}
|
132
|
-
|
133
|
-
if @record
|
134
|
-
dataset.where(id: @record[:id]).update(new_state)
|
135
|
-
@record = @record.merge(new_state)
|
136
|
-
else
|
137
|
-
id = dataset.insert(
|
138
|
-
digest: digest,
|
139
|
-
name: @task.name,
|
140
|
-
params: serialize(@task.params),
|
141
|
-
**new_state
|
142
|
-
)
|
143
|
-
@record = { id: id, **new_state }
|
144
|
-
end
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
def start
|
149
|
-
return true if disabled? || preview?
|
150
|
-
|
151
|
-
database.transaction do
|
152
|
-
reload
|
153
|
-
|
154
|
-
fail AbidErrorTaskAlreadyRunning if running?
|
155
|
-
|
156
|
-
new_state = {
|
157
|
-
state: RUNNING,
|
158
|
-
start_time: Time.now,
|
159
|
-
end_time: nil
|
160
|
-
}
|
161
|
-
|
162
|
-
if @record
|
163
|
-
dataset.where(id: @record[:id]).update(new_state)
|
164
|
-
@record = @record.merge(new_state)
|
165
|
-
else
|
166
|
-
id = dataset.insert(
|
167
|
-
digest: digest,
|
168
|
-
name: @task.name,
|
169
|
-
params: serialize(@task.params),
|
170
|
-
**new_state
|
171
|
-
)
|
172
|
-
@record = { id: id, **new_state }
|
173
|
-
end
|
174
|
-
|
175
|
-
@started = true
|
176
|
-
true
|
177
|
-
end
|
178
|
-
end
|
179
|
-
|
180
|
-
def finish(error = nil)
|
181
|
-
return if disabled? || preview?
|
182
|
-
return unless @record
|
183
|
-
return unless @started
|
184
|
-
state = error ? FAILED : SUCCESSED
|
185
|
-
dataset.where(id: @record[:id]).update(state: state, end_time: Time.now)
|
186
|
-
reload
|
187
|
-
end
|
188
|
-
|
189
|
-
def digest
|
190
|
-
Digest::MD5.hexdigest(@task.name + "\n" + serialize(@task.params))
|
191
|
-
end
|
192
|
-
end
|
193
|
-
end
|