operationable 0.2.7 → 0.2.8

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8b18274511419a5544c45629e90002fa62e716ef
4
- data.tar.gz: 00835b124deae21aa613dc9afb568d40fab14a85
3
+ metadata.gz: 2acea623e67938b58cb568d705062a86d5005ce2
4
+ data.tar.gz: 6145faa763a9fe92e19852bf5bb91c2d95c4bb11
5
5
  SHA512:
6
- metadata.gz: ba9e5eecb9fefe67536e074b2dacdbe2dcf2b55f9013571670a74ebc1654f503e759658ea0adce124e026cab4a5e55bc415c1fe4eb89e4a6e628c4a29f2d0bb7
7
- data.tar.gz: aa36fdabae4857d160e744be4198429f0e0b9ace7c8447c79934d0ae3a7a782aec9a12a0b2e0337381685036ebd7753d5d0849e4220ad95fec3266fb649dbc47
6
+ metadata.gz: ef5a0e1e38e6978caa2f72d63ec45305ae6d39721957d841d20921459ca310d9018ea8de5a03e472f6dd8fdd7833d15e87c3ddeeb693850513da264e520cce72
7
+ data.tar.gz: e2bbd17615a9a4285b9be47939d6d73a4386f311f29387e50db200bfa0490724062193c411c5ecec6d65f8c25e442532136acde3bc307ff74e0b1aadd103a8ea
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  class OperationJob < ActiveJob::Base
3
- include Operationable::Status
3
+ include Operationable::Persisters::Memory
4
4
  # include Operationable::Persister
5
5
 
6
6
  queue_as do
@@ -12,8 +12,10 @@ require 'operationable/callback'
12
12
  require 'operationable/operation'
13
13
  require 'operationable/serializer'
14
14
  require 'operationable/specification'
15
- require 'operationable/persister'
16
- require 'operationable/status'
15
+
16
+ require 'operationable/persisters/base'
17
+ require 'operationable/persisters/database'
18
+ require 'operationable/persisters/memory'
17
19
 
18
20
  require 'operationable/runners/base'
19
21
  require 'operationable/runners/serial'
@@ -0,0 +1,20 @@
1
+ module Operationable
2
+ module Persisters
3
+ module Base
4
+ STATUS_INIT = 'init'
5
+ STATUS_QUEUED = 'queued'
6
+ STATUS_WORKING = 'working'
7
+ STATUS_COMPLETED = 'completed'
8
+ STATUS_FAILED = 'failed'
9
+ STATUS_KILLED = 'killed'
10
+ STATUSES = [
11
+ STATUS_INIT,
12
+ STATUS_QUEUED,
13
+ STATUS_WORKING,
14
+ STATUS_COMPLETED,
15
+ STATUS_FAILED,
16
+ STATUS_KILLED
17
+ ].freeze
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+ module Operationable
3
+ module Persisters
4
+ module Database
5
+ class << self
6
+ def persist(callbacks, initiator_id, params, name)
7
+ ::Operation.create(
8
+ callbacks: callbacks.map { |callback|
9
+ {
10
+ status: Operationable::Persisters::Base::STATUS_INIT,
11
+ name: callback[:callback_method_name],
12
+ queue: callback[:queue]
13
+ }
14
+ },
15
+ initiator_id: initiator_id,
16
+ params: params,
17
+ name: name
18
+ )
19
+ end
20
+
21
+ def working(id, name)
22
+ update(id, name, Operationable::Persisters::Base::STATUS_WORKING)
23
+ end
24
+
25
+ def completed(id, name)
26
+ update(id, name, Operationable::Persisters::Base::STATUS_COMPLETED)
27
+ end
28
+
29
+ def around_call(id, name, block)
30
+ working(id, name)
31
+ block.call
32
+ completed(id, name)
33
+ end
34
+
35
+ private
36
+
37
+ def update(id, name, status)
38
+ op = ::Operation.find(id)
39
+ callbacks = op.callbacks.map do |cb|
40
+ cb['status'] = status if cb['name'] === name
41
+ cb
42
+ end
43
+
44
+ op.callbacks = callbacks
45
+ op.save
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,134 @@
1
+ # frozen_string_literal: true
2
+ # codebase has been taken from abandoned resque-status gem, that not compatible with ActiveJob and Rails now
3
+ module Operationable
4
+ module Persisters
5
+ module Memory
6
+ extend Forwardable
7
+ extend ActiveSupport::Concern
8
+
9
+ autoload :Hash, 'resque/plugins/status/hash'
10
+
11
+ # The error class raised when a job is killed
12
+ class Killed < RuntimeError; end
13
+ class NotANumber < RuntimeError; end
14
+
15
+ attr_reader :uuid, :options
16
+
17
+ def create_status_hash(job)
18
+ Resque::Plugins::Status::Hash.create(self.job_id, arguments.first)
19
+ end
20
+
21
+ def uuid
22
+ self.job_id
23
+ end
24
+
25
+ def options
26
+ arguments.first
27
+ end
28
+
29
+ # Run by the Resque::Worker when processing this job. It wraps the <tt>perform</tt>
30
+ # method ensuring that the final status of the job is set regardless of error.
31
+ # If an error occurs within the job's work, it will set the status as failed and
32
+ # re-raise the error.
33
+ def safe_perform(job, block)
34
+ working
35
+
36
+ block.call
37
+
38
+ if status && status.failed?
39
+ on_failure(status.message) if respond_to?(:on_failure)
40
+ return
41
+ elsif status && !status.completed?
42
+ completed
43
+ end
44
+ on_success if respond_to?(:on_success)
45
+ rescue Killed
46
+ Resque::Plugins::Status::Hash.killed(uuid)
47
+ on_killed if respond_to?(:on_killed)
48
+ rescue => e
49
+ failed("The task failed because of an error: #{e}")
50
+ if respond_to?(:on_failure)
51
+ on_failure(e)
52
+ else
53
+ raise e
54
+ end
55
+ end
56
+
57
+ # Set the jobs status. Can take an array of strings or hashes that are merged
58
+ # (in order) into a final status hash.
59
+ def status=(new_status)
60
+ Resque::Plugins::Status::Hash.set(uuid, *new_status)
61
+ end
62
+
63
+ # get the Resque::Plugins::Status::Hash object for the current uuid
64
+ def status
65
+ Resque::Plugins::Status::Hash.get(uuid)
66
+ end
67
+
68
+ def name
69
+ "#{self.class.name}(#{options.inspect unless options.empty?})"
70
+ end
71
+
72
+ # Checks against the kill list if this specific job instance should be killed
73
+ # on the next iteration
74
+ def should_kill?
75
+ Resque::Plugins::Status::Hash.should_kill?(uuid)
76
+ end
77
+
78
+ # set the status of the job for the current itteration. <tt>num</tt> and
79
+ # <tt>total</tt> are passed to the status as well as any messages.
80
+ # This will kill the job if it has been added to the kill list with
81
+ # <tt>Resque::Plugins::Status::Hash.kill()</tt>
82
+ def at(num, total, *messages)
83
+ if total.to_f <= 0.0
84
+ raise(NotANumber, "Called at() with total=#{total} which is not a number")
85
+ end
86
+ tick({
87
+ 'num' => num,
88
+ 'total' => total
89
+ }, *messages)
90
+ end
91
+
92
+ def working
93
+ set_status({'status' => Operationable::Persisters::Base::STATUS_WORKING})
94
+ end
95
+
96
+ # sets the status of the job for the current itteration. You should use
97
+ # the <tt>at</tt> method if you have actual numbers to track the iteration count.
98
+ # This will kill the job if it has been added to the kill list with
99
+ # <tt>Resque::Plugins::Status::Hash.kill()</tt>
100
+ def tick(*messages)
101
+ kill! if should_kill?
102
+ set_status({'status' => Operationable::Persisters::Base::STATUS_WORKING}, *messages)
103
+ end
104
+
105
+ # set the status to 'failed' passing along any additional messages
106
+ def failed(*messages)
107
+ set_status({'status' => Operationable::Persisters::Base::STATUS_FAILED}, *messages)
108
+ end
109
+
110
+ # set the status to 'completed' passing along any addional messages
111
+ def completed(*messages)
112
+ set_status({
113
+ 'status' => Operationable::Persisters::Base::STATUS_COMPLETED,
114
+ 'message' => "Completed at #{Time.now}"
115
+ }, *messages)
116
+ end
117
+
118
+ # kill the current job, setting the status to 'killed' and raising <tt>Killed</tt>
119
+ def kill!
120
+ set_status({
121
+ 'status' => Operationable::Persisters::Base::STATUS_KILLED,
122
+ 'message' => "Killed at #{Time.now}"
123
+ })
124
+ raise Killed
125
+ end
126
+
127
+ private
128
+
129
+ def set_status(*args)
130
+ self.status = [status, {'name' => self.name}, args].flatten
131
+ end
132
+ end
133
+ end
134
+ end
@@ -14,6 +14,10 @@ module Operationable
14
14
  initialize_callbacks
15
15
  end
16
16
 
17
+ def persist_operation
18
+ @persist_operation ||= ::Operationable::Persisters::Database.persist(check_callbacks, user.id, props, operation_class_name)
19
+ end
20
+
17
21
  def check_status?
18
22
  true
19
23
  end
@@ -1,3 +1,3 @@
1
1
  module Operationable
2
- VERSION = "0.2.7"
2
+ VERSION = "0.2.8"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: operationable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.7
4
+ version: 0.2.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kirill Suhodolov
@@ -119,13 +119,14 @@ files:
119
119
  - lib/operationable/builder.rb
120
120
  - lib/operationable/callback.rb
121
121
  - lib/operationable/operation.rb
122
- - lib/operationable/persister.rb
122
+ - lib/operationable/persisters/base.rb
123
+ - lib/operationable/persisters/database.rb
124
+ - lib/operationable/persisters/memory.rb
123
125
  - lib/operationable/runners/base.rb
124
126
  - lib/operationable/runners/separate.rb
125
127
  - lib/operationable/runners/serial.rb
126
128
  - lib/operationable/serializer.rb
127
129
  - lib/operationable/specification.rb
128
- - lib/operationable/status.rb
129
130
  - lib/operationable/version.rb
130
131
  - lib/operations/create.rb
131
132
  - lib/operations/destroy.rb
@@ -1,52 +0,0 @@
1
- # frozen_string_literal: true
2
- module Operationable
3
- module Persister
4
- def persist_operation
5
- @persist_operation ||= ::Operationable::Persister.persist(check_callbacks, user.id, props, operation_class_name)
6
- end
7
-
8
- class << self
9
- def persist(callbacks, initiator_id, params, name)
10
- ::Operation.create(
11
- callbacks: callbacks.map { |callback|
12
- {
13
- status: ::Operation::STATUS_INIT,
14
- name: callback[:callback_method_name],
15
- queue: callback[:queue]
16
- }
17
- },
18
- initiator_id: initiator_id,
19
- params: params,
20
- name: name
21
- )
22
- end
23
-
24
- def working(id, name)
25
- update(id, name, ::Operation::STATUS_WORKING)
26
- end
27
-
28
- def completed(id, name)
29
- update(id, name, ::Operation::STATUS_COMPLETED)
30
- end
31
-
32
- def around_call(id, name, block)
33
- working(id, name)
34
- block.call
35
- completed(id, name)
36
- end
37
-
38
- private
39
-
40
- def update(id, name, status)
41
- op = ::Operation.find(id)
42
- callbacks = op.callbacks.map do |cb|
43
- cb['status'] = status if cb['name'] === name
44
- cb
45
- end
46
-
47
- op.callbacks = callbacks
48
- op.save
49
- end
50
- end
51
- end
52
- end
@@ -1,145 +0,0 @@
1
- # frozen_string_literal: true
2
- # codebase has been taken from abandoned resque-status gem, that not compatible with ActiveJob and Rails now
3
- module Operationable
4
- module Status
5
- extend Forwardable
6
- extend ActiveSupport::Concern
7
-
8
- STATUS_QUEUED = 'queued'
9
- STATUS_WORKING = 'working'
10
- STATUS_COMPLETED = 'completed'
11
- STATUS_FAILED = 'failed'
12
- STATUS_KILLED = 'killed'
13
- STATUSES = [
14
- STATUS_QUEUED,
15
- STATUS_WORKING,
16
- STATUS_COMPLETED,
17
- STATUS_FAILED,
18
- STATUS_KILLED
19
- ].freeze
20
-
21
- autoload :Hash, 'resque/plugins/status/hash'
22
-
23
- # The error class raised when a job is killed
24
- class Killed < RuntimeError; end
25
- class NotANumber < RuntimeError; end
26
-
27
- attr_reader :uuid, :options
28
-
29
- def create_status_hash(job)
30
- Resque::Plugins::Status::Hash.create(self.job_id, arguments.first)
31
- end
32
-
33
- def uuid
34
- self.job_id
35
- end
36
-
37
- def options
38
- arguments.first
39
- end
40
-
41
- # Run by the Resque::Worker when processing this job. It wraps the <tt>perform</tt>
42
- # method ensuring that the final status of the job is set regardless of error.
43
- # If an error occurs within the job's work, it will set the status as failed and
44
- # re-raise the error.
45
- def safe_perform(job, block)
46
- working
47
-
48
- block.call
49
-
50
- if status && status.failed?
51
- on_failure(status.message) if respond_to?(:on_failure)
52
- return
53
- elsif status && !status.completed?
54
- completed
55
- end
56
- on_success if respond_to?(:on_success)
57
- rescue Killed
58
- Resque::Plugins::Status::Hash.killed(uuid)
59
- on_killed if respond_to?(:on_killed)
60
- rescue => e
61
- failed("The task failed because of an error: #{e}")
62
- if respond_to?(:on_failure)
63
- on_failure(e)
64
- else
65
- raise e
66
- end
67
- end
68
-
69
- # Set the jobs status. Can take an array of strings or hashes that are merged
70
- # (in order) into a final status hash.
71
- def status=(new_status)
72
- Resque::Plugins::Status::Hash.set(uuid, *new_status)
73
- end
74
-
75
- # get the Resque::Plugins::Status::Hash object for the current uuid
76
- def status
77
- Resque::Plugins::Status::Hash.get(uuid)
78
- end
79
-
80
- def name
81
- "#{self.class.name}(#{options.inspect unless options.empty?})"
82
- end
83
-
84
- # Checks against the kill list if this specific job instance should be killed
85
- # on the next iteration
86
- def should_kill?
87
- Resque::Plugins::Status::Hash.should_kill?(uuid)
88
- end
89
-
90
- # set the status of the job for the current itteration. <tt>num</tt> and
91
- # <tt>total</tt> are passed to the status as well as any messages.
92
- # This will kill the job if it has been added to the kill list with
93
- # <tt>Resque::Plugins::Status::Hash.kill()</tt>
94
- def at(num, total, *messages)
95
- if total.to_f <= 0.0
96
- raise(NotANumber, "Called at() with total=#{total} which is not a number")
97
- end
98
- tick({
99
- 'num' => num,
100
- 'total' => total
101
- }, *messages)
102
- end
103
-
104
- def working
105
- set_status({'status' => STATUS_WORKING})
106
- end
107
-
108
- # sets the status of the job for the current itteration. You should use
109
- # the <tt>at</tt> method if you have actual numbers to track the iteration count.
110
- # This will kill the job if it has been added to the kill list with
111
- # <tt>Resque::Plugins::Status::Hash.kill()</tt>
112
- def tick(*messages)
113
- kill! if should_kill?
114
- set_status({'status' => STATUS_WORKING}, *messages)
115
- end
116
-
117
- # set the status to 'failed' passing along any additional messages
118
- def failed(*messages)
119
- set_status({'status' => STATUS_FAILED}, *messages)
120
- end
121
-
122
- # set the status to 'completed' passing along any addional messages
123
- def completed(*messages)
124
- set_status({
125
- 'status' => STATUS_COMPLETED,
126
- 'message' => "Completed at #{Time.now}"
127
- }, *messages)
128
- end
129
-
130
- # kill the current job, setting the status to 'killed' and raising <tt>Killed</tt>
131
- def kill!
132
- set_status({
133
- 'status' => STATUS_KILLED,
134
- 'message' => "Killed at #{Time.now}"
135
- })
136
- raise Killed
137
- end
138
-
139
- private
140
-
141
- def set_status(*args)
142
- self.status = [status, {'name' => self.name}, args].flatten
143
- end
144
- end
145
- end