burstflow 0.2.0 → 0.2.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 +4 -4
- data/Gemfile +1 -1
- data/Gemfile.lock +1 -1
- data/README.md +29 -21
- data/burstflow.gemspec +4 -4
- data/db/schema.rb +11 -13
- data/lib/burstflow/job.rb +23 -26
- data/lib/burstflow/job/callbacks.rb +4 -9
- data/lib/burstflow/job/exception.rb +3 -1
- data/lib/burstflow/job/initialization.rb +3 -6
- data/lib/burstflow/job/state.rb +17 -13
- data/lib/burstflow/manager.rb +85 -86
- data/lib/burstflow/railtie.rb +5 -2
- data/lib/burstflow/version.rb +3 -1
- data/lib/burstflow/worker.rb +21 -21
- data/lib/burstflow/workflow.rb +164 -156
- data/lib/burstflow/workflow/builder.rb +67 -64
- data/lib/burstflow/workflow/callbacks.rb +10 -16
- data/lib/burstflow/workflow/configuration.rb +37 -36
- data/lib/burstflow/workflow/exception.rb +3 -1
- data/lib/generators/burstflow/install/install_generator.rb +11 -5
- data/spec/builder_spec.rb +26 -27
- data/spec/generators/install_generator_spec.rb +11 -7
- data/spec/job_spec.rb +1 -1
- data/spec/spec_helper.rb +1 -1
- data/spec/workflow_spec.rb +128 -101
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4d68ef2fa6c3af3c066b65ae6213d3ac96216ea1eb66b849bb979759ed25c67b
|
4
|
+
data.tar.gz: b7868f4aeca3863996bba8f256fa72b79f244375bc6c82c301386ca88b7f66f8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 59e06e384d30bec993c880bce050f41dbc017cf1b0814855dca2d538ea270a79d9a9cb6a8f4601b47848f810cc768508e4a0c7aa5eade69717c194dc52b07526
|
7
|
+
data.tar.gz: dfba34ed82a10b598dfac4539be6f0b8d6880061eb61ac85780c9fcd84f5f498e72ce9228c3bb088d83bba32bcda75d4238b03e070ea64eb3b9d334a88718636
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -2,25 +2,33 @@
|
|
2
2
|
|
3
3
|
<!-- ## [](https://chaps.io) proudly made by [Chaps](https://chaps.io) -->
|
4
4
|
|
5
|
-
|
5
|
+
[](https://travis-ci.com/RnD-Soft/burstflow) [](https://badge.fury.io/rb/burstflow)
|
6
6
|
|
7
|
-
|
7
|
+
Burstflow is a parallel workflow runner using [ActiveRecord] and [ActiveJob](https://guides.rubyonrails.org/v4.2/active_job_basics.html) for scheduling and executing jobs.
|
8
8
|
|
9
|
-
|
9
|
+
This gem is higly inspired by [Gush](https://github.com/chaps-io/gush). But not tied to Reddis or Sidekiq like Gush.
|
10
|
+
|
11
|
+
ActiveRecord used as persisted store during workflow execution.
|
12
|
+
|
13
|
+
Additional features:
|
14
|
+
|
15
|
+
* **susped** and **resume** job(and whole workflow). For example if your job makes asynchronous request and will receive a response some time later. In this case, the job can send request and suspend until some external event resumes it eventually.
|
16
|
+
* before/after callbacks on jobs level
|
17
|
+
* before/after callbacks on workflow level
|
18
|
+
* **Dynamic workflows**. Any job can produce another jobs while executing. This jobs has its parent as incomming jobs, and all parents outgoing jobs as own outgoings.
|
10
19
|
|
11
|
-
Another difference from Gush is **Dynamic workflows**. Any job can produce another jobs while executing. This jobs has its parent as incomming jobs, and all parents outgoing jobs as own outgoings.
|
12
20
|
|
13
21
|
## Installation
|
14
22
|
|
15
23
|
### 1. Add `burst` to Gemfile
|
16
24
|
|
17
25
|
```ruby
|
18
|
-
gem '
|
26
|
+
gem 'burstflow', '~> 0.2.0'
|
19
27
|
```
|
20
28
|
|
21
29
|
### 2. Run migrations
|
22
30
|
|
23
|
-
|
31
|
+
```rake burstflow:install:migrations```
|
24
32
|
|
25
33
|
## Example
|
26
34
|
|
@@ -29,7 +37,7 @@ Here is a complete example of a workflow you can create:
|
|
29
37
|
|
30
38
|
```ruby
|
31
39
|
# app/workflows/sample_workflow.rb
|
32
|
-
class SampleWorkflow <
|
40
|
+
class SampleWorkflow < Burstflow::Workflow
|
33
41
|
configure do |url_to_fetch_from|
|
34
42
|
run FetchJob1, params: { url: url_to_fetch_from }
|
35
43
|
run FetchJob2, params: { some_flag: true, url: 'http://url.com' }
|
@@ -56,7 +64,7 @@ and this is how the graph will look like:
|
|
56
64
|
Let's start with the simplest workflow possible, consisting of a single job:
|
57
65
|
|
58
66
|
```ruby
|
59
|
-
class SimpleWorkflow <
|
67
|
+
class SimpleWorkflow < Burstflow::Workflow
|
60
68
|
configure do
|
61
69
|
run DownloadJob
|
62
70
|
end
|
@@ -74,12 +82,12 @@ class SimpleWorkflow < Burst::Workflow
|
|
74
82
|
end
|
75
83
|
```
|
76
84
|
|
77
|
-
We just told
|
85
|
+
We just told Burstflow to execute `SaveJob` right after `DownloadJob` finishes **successfully**.
|
78
86
|
|
79
87
|
But what if your job must have multiple dependencies? That's easy, just provide an array to the `after` attribute:
|
80
88
|
|
81
89
|
```ruby
|
82
|
-
class SimpleWorkflow <
|
90
|
+
class SimpleWorkflow < Burstflow::Workflow
|
83
91
|
configure do
|
84
92
|
run FirstDownloadJob
|
85
93
|
run SecondDownloadJob
|
@@ -98,7 +106,7 @@ With this simple syntax you can build any complex workflows you can imagine!
|
|
98
106
|
`run` method also accepts `before:` attribute to define the opposite association. So we can write the same workflow as above, but like this:
|
99
107
|
|
100
108
|
```ruby
|
101
|
-
class SimpleWorkflow <
|
109
|
+
class SimpleWorkflow < Burstflow::Workflow
|
102
110
|
configure do
|
103
111
|
run FirstDownloadJob, before: SaveJob
|
104
112
|
run SecondDownloadJob, before: SaveJob
|
@@ -118,7 +126,7 @@ Workflows can accept any primitive arguments in their constructor, which then wi
|
|
118
126
|
Let's assume we are writing a book publishing workflow which needs to know where the PDF of the book is and under what ISBN it will be released:
|
119
127
|
|
120
128
|
```ruby
|
121
|
-
class PublishBookWorkflow <
|
129
|
+
class PublishBookWorkflow < Burstflow::Workflow
|
122
130
|
configure do |url, isbn|
|
123
131
|
run FetchBook, params: { url: url }
|
124
132
|
run PublishBook, params: { book_isbn: isbn }, after: FetchBook
|
@@ -136,7 +144,7 @@ and that's basically it for defining workflows, see below on how to define jobs:
|
|
136
144
|
|
137
145
|
## Defining jobs
|
138
146
|
|
139
|
-
The simplest job is a class inheriting from `
|
147
|
+
The simplest job is a class inheriting from `Burstflow::Job` and responding to `perform` and `resume` method. Much like any other ActiveJob class.
|
140
148
|
|
141
149
|
```ruby
|
142
150
|
class FetchBook < Burst::Job
|
@@ -189,14 +197,14 @@ flow = PublishBookWorkflow.build("http://url.com/book.pdf", "978-0470081204")
|
|
189
197
|
flow.start!
|
190
198
|
```
|
191
199
|
|
192
|
-
Now
|
200
|
+
Now Burstflow will start processing jobs in the background using ActiveJob and your chosen backend.
|
193
201
|
|
194
202
|
### 3. Monitor its progress:
|
195
203
|
|
196
204
|
```ruby
|
197
205
|
flow.reload
|
198
206
|
flow.status
|
199
|
-
#=> :running|:finished|:failed
|
207
|
+
#=> :running|:finished|:failed|:suspended
|
200
208
|
```
|
201
209
|
|
202
210
|
`reload` is needed to see the latest status, since workflows are updated asynchronously.
|
@@ -205,7 +213,7 @@ flow.status
|
|
205
213
|
|
206
214
|
### Pipelining
|
207
215
|
|
208
|
-
|
216
|
+
Burstflow offers a useful tool to pass results of a job to its dependencies, so they can act differently.
|
209
217
|
|
210
218
|
**Example:**
|
211
219
|
|
@@ -228,9 +236,9 @@ end
|
|
228
236
|
Now, since `DownloadVideo` finished and its dependant job `EncodeVideo` started, we can access that payload inside it:
|
229
237
|
|
230
238
|
```ruby
|
231
|
-
class EncodeVideo <
|
239
|
+
class EncodeVideo < Burstflow::Job
|
232
240
|
def perform
|
233
|
-
video_path = payloads.first[:
|
241
|
+
video_path = payloads.first[:value]
|
234
242
|
end
|
235
243
|
end
|
236
244
|
```
|
@@ -243,7 +251,7 @@ end
|
|
243
251
|
{
|
244
252
|
id: "DownloadVideo-41bfb730-b49f-42ac-a808-156327989294" # unique id of the ancestor job
|
245
253
|
class: "DownloadVideo",
|
246
|
-
|
254
|
+
value: "https://s3.amazonaws.com/somebucket/downloaded-file.mp4" #the payload returned by DownloadVideo job using `output()` method
|
247
255
|
}
|
248
256
|
]
|
249
257
|
```
|
@@ -259,7 +267,7 @@ As an example, let's write a workflow which accepts an array of users and has to
|
|
259
267
|
|
260
268
|
```ruby
|
261
269
|
|
262
|
-
class ParentJob <
|
270
|
+
class ParentJob < Burstflow::Job
|
263
271
|
def perform
|
264
272
|
configure do
|
265
273
|
params[:user_ids].map do |user_id|
|
@@ -286,7 +294,7 @@ https://github.com/chaps-io/gush#contributors
|
|
286
294
|
|
287
295
|
## Contributing
|
288
296
|
|
289
|
-
1. Fork it ( https://github.com/RnD-Soft/
|
297
|
+
1. Fork it ( https://github.com/RnD-Soft/burstflow/fork )
|
290
298
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
291
299
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
292
300
|
4. Push to the branch (`git push origin my-new-feature`)
|
data/burstflow.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
$:.push File.expand_path(
|
1
|
+
$:.push File.expand_path('lib', __dir__)
|
2
2
|
|
3
3
|
# Maintain your gem's version:
|
4
|
-
require
|
4
|
+
require 'burstflow/version'
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = 'burstflow'
|
@@ -19,9 +19,9 @@ Gem::Specification.new do |spec|
|
|
19
19
|
|
20
20
|
spec.add_dependency 'activejob'
|
21
21
|
spec.add_dependency 'activerecord'
|
22
|
-
|
22
|
+
|
23
23
|
spec.add_development_dependency 'bundler'
|
24
|
+
spec.add_development_dependency 'generator_spec'
|
24
25
|
spec.add_development_dependency 'rake'
|
25
26
|
spec.add_development_dependency 'rspec'
|
26
|
-
spec.add_development_dependency 'generator_spec'
|
27
27
|
end
|
data/db/schema.rb
CHANGED
@@ -10,20 +10,18 @@
|
|
10
10
|
#
|
11
11
|
# It's strongly recommended that you check this file into your version control system.
|
12
12
|
|
13
|
-
ActiveRecord::Schema.define(version:
|
14
|
-
|
13
|
+
ActiveRecord::Schema.define(version: 20_180_101_000_001) do
|
15
14
|
# These are extensions that must be enabled in order to support this database
|
16
|
-
enable_extension
|
17
|
-
enable_extension
|
15
|
+
enable_extension 'pgcrypto'
|
16
|
+
enable_extension 'plpgsql'
|
18
17
|
|
19
|
-
create_table
|
20
|
-
t.string
|
21
|
-
t.string
|
22
|
-
t.jsonb
|
23
|
-
t.datetime
|
24
|
-
t.datetime
|
25
|
-
t.index [
|
26
|
-
t.index [
|
18
|
+
create_table 'burstflow_workflows', id: :uuid, default: -> { 'gen_random_uuid()' }, force: :cascade do |t|
|
19
|
+
t.string 'type'
|
20
|
+
t.string 'status'
|
21
|
+
t.jsonb 'flow', default: {}, null: false
|
22
|
+
t.datetime 'created_at', null: false
|
23
|
+
t.datetime 'updated_at', null: false
|
24
|
+
t.index ['status'], name: 'index_burstflow_workflows_on_status'
|
25
|
+
t.index ['type'], name: 'index_burstflow_workflows_on_type'
|
27
26
|
end
|
28
|
-
|
29
27
|
end
|
data/lib/burstflow/job.rb
CHANGED
@@ -1,12 +1,13 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require 'active_support/rescuable'
|
2
|
+
require 'active_job/callbacks'
|
3
3
|
|
4
4
|
class Burstflow::Job
|
5
|
-
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
5
|
+
|
6
|
+
require 'burstflow/job/exception'
|
7
|
+
require 'burstflow/job/model'
|
8
|
+
require 'burstflow/job/initialization'
|
9
|
+
require 'burstflow/job/state'
|
10
|
+
require 'burstflow/job/callbacks'
|
10
11
|
|
11
12
|
include Burstflow::Job::Model
|
12
13
|
include Burstflow::Job::Initialization
|
@@ -30,28 +31,28 @@ class Burstflow::Job
|
|
30
31
|
end
|
31
32
|
|
32
33
|
# execute this code by ActiveJob. You may return Burstflow::Job::SUSPEND to suspend job, or call suspend method
|
33
|
-
def perform
|
34
|
-
end
|
34
|
+
def perform; end
|
35
35
|
|
36
36
|
def perform_now
|
37
37
|
run_callbacks :perform do
|
38
38
|
perform
|
39
39
|
end
|
40
|
-
rescue => exception
|
40
|
+
rescue StandardError => exception
|
41
41
|
rescue_with_handler(exception) || raise
|
42
42
|
end
|
43
43
|
|
44
44
|
# execute this code when resumes after suspending
|
45
45
|
def resume(data)
|
46
|
-
raise InternalError.new(self, "Can't perform resume: not resumed")
|
46
|
+
raise InternalError.new(self, "Can't perform resume: not resumed") unless resumed?
|
47
|
+
|
47
48
|
set_output(data)
|
48
49
|
end
|
49
50
|
|
50
|
-
def resume_now
|
51
|
+
def resume_now(data)
|
51
52
|
run_callbacks :resume do
|
52
53
|
resume(data)
|
53
54
|
end
|
54
|
-
rescue => exception
|
55
|
+
rescue StandardError => exception
|
55
56
|
rescue_with_handler(exception) || raise
|
56
57
|
end
|
57
58
|
|
@@ -62,13 +63,13 @@ class Burstflow::Job
|
|
62
63
|
|
63
64
|
# mark execution as suspended
|
64
65
|
def suspend
|
65
|
-
raise InternalError.new(self, "Can't suspend: not running")
|
66
|
+
raise InternalError.new(self, "Can't suspend: not running") unless running?
|
67
|
+
|
66
68
|
set_output(SUSPEND)
|
67
69
|
end
|
68
70
|
|
69
|
-
def configure
|
71
|
+
def configure(*args, &block)
|
70
72
|
workflow.with_lock do
|
71
|
-
|
72
73
|
builder = Burstflow::Workflow::Builder.new(workflow, *args, &block)
|
73
74
|
workflow.flow['jobs_config'] = builder.as_json
|
74
75
|
workflow.save!
|
@@ -78,12 +79,12 @@ class Burstflow::Job
|
|
78
79
|
|
79
80
|
def attributes
|
80
81
|
{
|
81
|
-
workflow_id:
|
82
|
-
id:
|
83
|
-
klass:
|
82
|
+
workflow_id: workflow_id,
|
83
|
+
id: id,
|
84
|
+
klass: klass,
|
84
85
|
params: params,
|
85
|
-
incoming:
|
86
|
-
outgoing:
|
86
|
+
incoming: incoming,
|
87
|
+
outgoing: outgoing,
|
87
88
|
output: output,
|
88
89
|
started_at: started_at,
|
89
90
|
enqueued_at: enqueued_at,
|
@@ -91,12 +92,8 @@ class Burstflow::Job
|
|
91
92
|
failed_at: failed_at,
|
92
93
|
suspended_at: suspended_at,
|
93
94
|
resumed_at: resumed_at,
|
94
|
-
failure:
|
95
|
+
failure: failure
|
95
96
|
}
|
96
97
|
end
|
97
98
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
99
|
end
|
@@ -1,17 +1,15 @@
|
|
1
1
|
module Burstflow::Job::Callbacks
|
2
|
+
|
2
3
|
extend ActiveSupport::Concern
|
3
4
|
include ActiveJob::Callbacks
|
4
5
|
|
5
6
|
included do
|
6
|
-
|
7
7
|
define_callbacks :suspend
|
8
8
|
define_callbacks :resume
|
9
9
|
define_callbacks :failure
|
10
|
-
|
11
10
|
end
|
12
11
|
|
13
12
|
class_methods do
|
14
|
-
|
15
13
|
def before_suspend(*filters, &blk)
|
16
14
|
set_callback(:suspend, :before, *filters, &blk)
|
17
15
|
end
|
@@ -24,7 +22,6 @@ module Burstflow::Job::Callbacks
|
|
24
22
|
set_callback(:suspend, :around, *filters, &blk)
|
25
23
|
end
|
26
24
|
|
27
|
-
|
28
25
|
def before_resume(*filters, &blk)
|
29
26
|
set_callback(:resume, :before, *filters, &blk)
|
30
27
|
end
|
@@ -37,19 +34,17 @@ module Burstflow::Job::Callbacks
|
|
37
34
|
set_callback(:resume, :around, *filters, &blk)
|
38
35
|
end
|
39
36
|
|
40
|
-
|
41
37
|
def before_failure(*filters, &blk)
|
42
38
|
set_callback(:failure, :before, *filters, &blk)
|
43
39
|
end
|
44
|
-
|
40
|
+
|
45
41
|
def after_failure(*filters, &blk)
|
46
42
|
set_callback(:failure, :after, *filters, &blk)
|
47
43
|
end
|
48
|
-
|
44
|
+
|
49
45
|
def around_failure(*filters, &blk)
|
50
46
|
set_callback(:failure, :around, *filters, &blk)
|
51
47
|
end
|
52
|
-
|
53
48
|
end
|
54
49
|
|
55
|
-
end
|
50
|
+
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
module Burstflow::Job::Initialization
|
2
|
-
extend ActiveSupport::Concern
|
3
2
|
|
4
|
-
|
3
|
+
extend ActiveSupport::Concern
|
5
4
|
|
5
|
+
included do
|
6
6
|
def initialize(workflow, job_config = {})
|
7
7
|
@workflow = workflow
|
8
8
|
assign_default_values(job_config)
|
@@ -21,15 +21,12 @@ module Burstflow::Job::Initialization
|
|
21
21
|
def reload
|
22
22
|
assign_default_values(@workflow.job_hash(self.id))
|
23
23
|
end
|
24
|
-
|
25
24
|
end
|
26
25
|
|
27
26
|
class_methods do
|
28
|
-
|
29
27
|
def from_hash(workflow, job_config)
|
30
28
|
job_config[:klass].constantize.new(workflow, job_config)
|
31
29
|
end
|
32
|
-
|
33
30
|
end
|
34
31
|
|
35
|
-
end
|
32
|
+
end
|
data/lib/burstflow/job/state.rb
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
module Burstflow::Job::State
|
2
|
-
extend ActiveSupport::Concern
|
3
2
|
|
4
|
-
|
3
|
+
extend ActiveSupport::Concern
|
5
4
|
|
5
|
+
included do
|
6
6
|
# mark job as enqueued when it is scheduled to queue
|
7
7
|
def enqueue!
|
8
8
|
raise Burstflow::Job::InternalError.new(self, "Can't enqueue: already enqueued") if enqueued?
|
9
|
+
|
9
10
|
self.enqueued_at = current_timestamp
|
10
11
|
self.started_at = nil
|
11
12
|
self.finished_at = nil
|
@@ -17,22 +18,25 @@ module Burstflow::Job::State
|
|
17
18
|
# mark job as started when it is start performing
|
18
19
|
def start!
|
19
20
|
raise Burstflow::Job::InternalError.new(self, "Can't start: already started") if started?
|
20
|
-
raise Burstflow::Job::InternalError.new(self, "Can't start: not enqueued")
|
21
|
+
raise Burstflow::Job::InternalError.new(self, "Can't start: not enqueued") unless enqueued?
|
22
|
+
|
21
23
|
self.started_at = current_timestamp
|
22
24
|
end
|
23
25
|
|
24
26
|
# mark job as finished when it is finish performing
|
25
27
|
def finish!
|
26
28
|
raise Burstflow::Job::InternalError.new(self, "Can't finish: already finished") if finished?
|
27
|
-
raise Burstflow::Job::InternalError.new(self, "Can't finish: not started")
|
29
|
+
raise Burstflow::Job::InternalError.new(self, "Can't finish: not started") unless started?
|
30
|
+
|
28
31
|
self.finished_at = current_timestamp
|
29
32
|
end
|
30
33
|
|
31
34
|
# mark job as failed when it is failed
|
32
|
-
def fail!
|
33
|
-
#raise Burstflow::Job::InternalError.new(self, "Can't fail: already failed") if failed?
|
34
|
-
#raise Burstflow::Job::InternalError.new(self, Can't fail: already finished") if finished?
|
35
|
-
raise Burstflow::Job::InternalError.new(self, "Can't fail: not started")
|
35
|
+
def fail!(msg_or_exception)
|
36
|
+
# raise Burstflow::Job::InternalError.new(self, "Can't fail: already failed") if failed?
|
37
|
+
# raise Burstflow::Job::InternalError.new(self, Can't fail: already finished") if finished?
|
38
|
+
raise Burstflow::Job::InternalError.new(self, "Can't fail: not started") unless started?
|
39
|
+
|
36
40
|
self.finished_at = self.failed_at = current_timestamp
|
37
41
|
|
38
42
|
context = {}
|
@@ -51,14 +55,16 @@ module Burstflow::Job::State
|
|
51
55
|
# mark job as suspended
|
52
56
|
def suspend!
|
53
57
|
raise Burstflow::Job::InternalError.new(self, "Can't suspend: already suspended") if suspended?
|
54
|
-
raise Burstflow::Job::InternalError.new(self, "Can't suspend: not runnig")
|
58
|
+
raise Burstflow::Job::InternalError.new(self, "Can't suspend: not runnig") unless running?
|
59
|
+
|
55
60
|
self.suspended_at = current_timestamp
|
56
61
|
end
|
57
62
|
|
58
63
|
# mark job as resumed
|
59
64
|
def resume!
|
60
65
|
raise Burstflow::Job::InternalError.new(self, "Can't resume: already resumed") if resumed?
|
61
|
-
raise Burstflow::Job::InternalError.new(self, "Can't resume: not suspended")
|
66
|
+
raise Burstflow::Job::InternalError.new(self, "Can't resume: not suspended") unless suspended?
|
67
|
+
|
62
68
|
self.resumed_at = current_timestamp
|
63
69
|
end
|
64
70
|
|
@@ -115,11 +121,9 @@ module Burstflow::Job::State
|
|
115
121
|
def current_timestamp
|
116
122
|
Time.now.to_i
|
117
123
|
end
|
118
|
-
|
119
124
|
end
|
120
125
|
|
121
126
|
class_methods do
|
122
|
-
|
123
127
|
end
|
124
128
|
|
125
|
-
end
|
129
|
+
end
|