abid 0.3.0.pre.alpha.2 → 0.3.0.pre.alpha.3

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.
@@ -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