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.
@@ -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
- Rake.application.define_play(self, *args, &block)
119
+ Abid.application.define_play(self, *args, &block)
134
120
  end
135
121
  end
136
122
  end
data/lib/abid/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Abid
2
- VERSION = '0.3.0-alpha.2'
2
+ VERSION = '0.3.0-alpha.3'
3
3
  end
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.2
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: 2016-12-02 00:00:00.000000000 Z
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:
@@ -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