acidic_job 1.0.0.rc2 → 1.0.0.rc3
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.lock +1 -1
- data/app/models/acidic_job/entry.rb +7 -7
- data/app/models/acidic_job/execution.rb +22 -1
- data/lib/acidic_job/builder.rb +22 -6
- data/lib/acidic_job/errors.rb +22 -0
- data/lib/acidic_job/log_subscriber.rb +8 -8
- data/lib/acidic_job/plugin_context.rb +51 -0
- data/lib/acidic_job/plugins/transactional_step.rb +38 -0
- data/lib/acidic_job/version.rb +1 -1
- data/lib/acidic_job/workflow.rb +76 -36
- data/lib/acidic_job.rb +4 -2
- data/lib/generators/acidic_job/templates/create_acidic_job_tables_migration.rb.erb +8 -7
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8af9b244cf2343978f26322753e80c779c224ab6942c85de5a8fe05cf0ba55f2
|
4
|
+
data.tar.gz: 5f609ee36139400937e2a8b3cae42f721eb72f1abf6633ddbd275aa18c1b2242
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6becc8ed3a1c1c58e24d52753e53edb206854cec472ffb4438e4711ea2a8abcd5adae080c621ab7b8bd30eb386118a51012a4f446e997277da3e9b12e460c696
|
7
|
+
data.tar.gz: fe04f817a6c2cab6b2284f7ce0a79b44f452e1c490abac18e6385b801a7ca00860e0910286886da6d70270b508ca54fa3ae4c13369d539e47c3ea4d12e9316d8
|
data/Gemfile.lock
CHANGED
@@ -4,16 +4,16 @@ module AcidicJob
|
|
4
4
|
class Entry < Record
|
5
5
|
belongs_to :execution, class_name: "AcidicJob::Execution"
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
scope :for_step, ->(step) { where(step: step) }
|
8
|
+
scope :for_action, ->(action) { where(action: action) }
|
9
|
+
scope :ordered, -> { order(timestamp: :asc) }
|
10
10
|
|
11
|
-
def
|
12
|
-
|
11
|
+
def self.most_recent
|
12
|
+
order(created_at: :desc).first
|
13
13
|
end
|
14
14
|
|
15
|
-
def
|
16
|
-
action ==
|
15
|
+
def action?(check)
|
16
|
+
action == check
|
17
17
|
end
|
18
18
|
end
|
19
19
|
end
|
@@ -29,7 +29,28 @@ module AcidicJob
|
|
29
29
|
end
|
30
30
|
|
31
31
|
def finished?
|
32
|
-
|
32
|
+
# rubocop:disable Style/MultipleComparison
|
33
|
+
recover_to.to_s == FINISHED_RECOVERY_POINT ||
|
34
|
+
recover_to.to_s == "FINISHED" # old value pre-1.0, remove at v1.0
|
35
|
+
# rubocop:enable Style/MultipleComparison
|
36
|
+
end
|
37
|
+
|
38
|
+
def defined?(step)
|
39
|
+
if definition.key?("steps")
|
40
|
+
definition["steps"].key?(step)
|
41
|
+
else
|
42
|
+
# TODO: add deprecation warning
|
43
|
+
definition.key?(step)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def definition_for(step)
|
48
|
+
if definition.key?("steps")
|
49
|
+
definition["steps"].fetch(step)
|
50
|
+
else
|
51
|
+
# TODO: add deprecation warning
|
52
|
+
definition.fetch(step)
|
53
|
+
end
|
33
54
|
end
|
34
55
|
|
35
56
|
def deserialized_job
|
data/lib/acidic_job/builder.rb
CHANGED
@@ -4,12 +4,21 @@ module AcidicJob
|
|
4
4
|
class Builder
|
5
5
|
attr_reader :steps
|
6
6
|
|
7
|
-
def initialize
|
7
|
+
def initialize(plugins)
|
8
|
+
@plugins = plugins
|
8
9
|
@steps = []
|
9
10
|
end
|
10
11
|
|
11
|
-
def step(method_name,
|
12
|
-
|
12
|
+
def step(method_name, **kwargs)
|
13
|
+
step = { "does" => method_name.to_s }
|
14
|
+
|
15
|
+
@plugins.each do |plugin|
|
16
|
+
next unless kwargs.key?(plugin.keyword)
|
17
|
+
|
18
|
+
step[plugin.keyword.to_s] = plugin.validate(kwargs[plugin.keyword])
|
19
|
+
end
|
20
|
+
|
21
|
+
@steps << step
|
13
22
|
@steps
|
14
23
|
end
|
15
24
|
|
@@ -17,13 +26,20 @@ module AcidicJob
|
|
17
26
|
# [ { does: "step 1", transactional: true }, { does: "step 2", transactional: false }, ... ]
|
18
27
|
@steps << { "does" => FINISHED_RECOVERY_POINT }
|
19
28
|
|
20
|
-
|
29
|
+
definition = {
|
30
|
+
"meta" => {
|
31
|
+
"version" => VERSION
|
32
|
+
},
|
33
|
+
"steps" => {}
|
34
|
+
}
|
35
|
+
|
36
|
+
definition.tap do |workflow|
|
21
37
|
@steps.each_cons(2).map do |enter_step, exit_step|
|
22
38
|
enter_name = enter_step["does"]
|
23
|
-
workflow[enter_name] = enter_step.merge("then" => exit_step["does"])
|
39
|
+
workflow["steps"][enter_name] = enter_step.merge("then" => exit_step["does"])
|
24
40
|
end
|
25
41
|
end
|
26
|
-
# { "step 1": { does: "step 1", transactional: true, then: "step 2" }, ... }
|
42
|
+
# { meta: { ... }, steps: { "step 1": { does: "step 1", transactional: true, then: "step 2" }, ... } }
|
27
43
|
end
|
28
44
|
end
|
29
45
|
end
|
data/lib/acidic_job/errors.rb
CHANGED
@@ -98,5 +98,27 @@ module AcidicJob
|
|
98
98
|
"step method cannot expect arguments: #{@step.inspect}"
|
99
99
|
end
|
100
100
|
end
|
101
|
+
|
102
|
+
class DoublePluginCallError < Error
|
103
|
+
def initialize(plugin, step)
|
104
|
+
@plugin_name = Module === plugin ? plugin.name : plugin.class.name # rubocop:disable Style/CaseEquality
|
105
|
+
@step = step
|
106
|
+
end
|
107
|
+
|
108
|
+
def message
|
109
|
+
"plugin `#{@plugin_name}` attempted to call step multiple times: #{@step.inspect}"
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
class MissingPluginCallError < Error
|
114
|
+
def initialize(plugin, step)
|
115
|
+
@plugin_name = Module === plugin ? plugin.name : plugin.class.name # rubocop:disable Style/CaseEquality
|
116
|
+
@step = step
|
117
|
+
end
|
118
|
+
|
119
|
+
def message
|
120
|
+
"plugin `#{@plugin_name}` failed to call step: #{@step.inspect}"
|
121
|
+
end
|
122
|
+
end
|
101
123
|
# rubocop:enable Lint/MissingSuper
|
102
124
|
end
|
@@ -5,33 +5,33 @@ require "active_support/log_subscriber"
|
|
5
5
|
module AcidicJob
|
6
6
|
class LogSubscriber < ActiveSupport::LogSubscriber
|
7
7
|
def define_workflow(event)
|
8
|
-
debug formatted_event(event,
|
8
|
+
debug formatted_event(event, title: "Define workflow", **event.payload.slice(:job_class, :job_id))
|
9
9
|
end
|
10
10
|
|
11
11
|
def initialize_workflow(event)
|
12
|
-
debug formatted_event(event,
|
12
|
+
debug formatted_event(event, title: "Initialize workflow", **event.payload.slice(:steps))
|
13
13
|
end
|
14
14
|
|
15
15
|
def process_workflow(event)
|
16
|
-
debug formatted_event(event,
|
16
|
+
debug formatted_event(event, title: "Process workflow", **event.payload[:execution].slice(:id, :recover_to))
|
17
17
|
end
|
18
18
|
|
19
19
|
def process_step(event)
|
20
|
-
debug formatted_event(event,
|
20
|
+
debug formatted_event(event, title: "Process step", **event.payload)
|
21
21
|
end
|
22
22
|
|
23
23
|
def perform_step(event)
|
24
|
-
debug formatted_event(event,
|
24
|
+
debug formatted_event(event, title: "Perform step", **event.payload)
|
25
25
|
end
|
26
26
|
|
27
27
|
def record_entry(event)
|
28
|
-
debug formatted_event(event,
|
28
|
+
debug formatted_event(event, title: "Record entry", **event.payload.slice(:step, :action, :timestamp))
|
29
29
|
end
|
30
30
|
|
31
31
|
private
|
32
32
|
|
33
|
-
def formatted_event(event,
|
34
|
-
"AcidicJob-#{AcidicJob::VERSION} #{
|
33
|
+
def formatted_event(event, title:, **attributes)
|
34
|
+
"AcidicJob-#{AcidicJob::VERSION} #{title} (#{event.duration.round(1)}ms) #{formatted_attributes(**attributes)}"
|
35
35
|
end
|
36
36
|
|
37
37
|
def formatted_attributes(**attributes)
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AcidicJob
|
4
|
+
class PluginContext
|
5
|
+
PLUGIN_INACTIVE = :__ACIDIC_JOB_PLUGIN_INACTIVE__
|
6
|
+
|
7
|
+
def initialize(plugin, job, execution, step_definition)
|
8
|
+
@plugin = plugin
|
9
|
+
@job = job
|
10
|
+
@execution = execution
|
11
|
+
@step_definition = step_definition
|
12
|
+
end
|
13
|
+
|
14
|
+
def definition
|
15
|
+
@step_definition.fetch(@plugin.keyword.to_s, PLUGIN_INACTIVE)
|
16
|
+
end
|
17
|
+
|
18
|
+
def current_step
|
19
|
+
@step_definition["does"]
|
20
|
+
end
|
21
|
+
|
22
|
+
def inactive?
|
23
|
+
definition == PLUGIN_INACTIVE
|
24
|
+
end
|
25
|
+
|
26
|
+
def entries_for_action(action)
|
27
|
+
@execution.entries.for_action(plugin_action(action))
|
28
|
+
end
|
29
|
+
|
30
|
+
def record!(step:, action:, timestamp:, **kwargs)
|
31
|
+
@execution.record!(
|
32
|
+
step: step,
|
33
|
+
action: plugin_action(action),
|
34
|
+
timestamp: timestamp,
|
35
|
+
**kwargs
|
36
|
+
)
|
37
|
+
end
|
38
|
+
|
39
|
+
def enqueue_job(...)
|
40
|
+
@job.enqueue(...)
|
41
|
+
end
|
42
|
+
|
43
|
+
def halt_step!
|
44
|
+
@job.halt_step!
|
45
|
+
end
|
46
|
+
|
47
|
+
def plugin_action(action)
|
48
|
+
"#{@plugin.keyword}/#{action}"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AcidicJob
|
4
|
+
module Plugins
|
5
|
+
module TransactionalStep
|
6
|
+
extend self
|
7
|
+
|
8
|
+
def keyword
|
9
|
+
:transactional
|
10
|
+
end
|
11
|
+
|
12
|
+
# transactional: true
|
13
|
+
# transactional: false
|
14
|
+
# transactional: { on: Model }
|
15
|
+
def validate(input)
|
16
|
+
return input if input in true | false
|
17
|
+
|
18
|
+
raise ArgumentError.new("argument must be boolean or hash") unless input in Hash
|
19
|
+
raise ArgumentError.new("argument hash must have `on` key") unless input in Hash[on:]
|
20
|
+
raise ArgumentError.new("`on` key must have module value") unless input in Hash[on: Module]
|
21
|
+
|
22
|
+
input
|
23
|
+
end
|
24
|
+
|
25
|
+
def around_step(context, &block)
|
26
|
+
return yield if context.definition == false
|
27
|
+
|
28
|
+
model = if context.definition == true
|
29
|
+
AcidicJob::Execution
|
30
|
+
else
|
31
|
+
context.definition["on"].constantize
|
32
|
+
end
|
33
|
+
|
34
|
+
model.transaction(&block)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/acidic_job/version.rb
CHANGED
data/lib/acidic_job/workflow.rb
CHANGED
@@ -4,33 +4,31 @@ require "active_job"
|
|
4
4
|
|
5
5
|
module AcidicJob
|
6
6
|
module Workflow
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
private_constant :NO_OP_WRAPPER, :REPEAT_STEP, :HALT_STEP
|
7
|
+
REPEAT_STEP = :__ACIDIC_JOB_REPEAT_STEP_SIGNAL__
|
8
|
+
HALT_STEP = :__ACIDIC_JOB_HALT_STEP_SIGNAL__
|
9
|
+
private_constant :REPEAT_STEP, :HALT_STEP
|
11
10
|
|
12
|
-
|
13
|
-
|
14
|
-
def execute_workflow(unique_by:, &block)
|
11
|
+
def execute_workflow(unique_by:, with: [Plugins::TransactionalStep], &block)
|
12
|
+
@__acidic_job_plugins__ = with
|
15
13
|
serialized_job = serialize
|
16
14
|
|
17
15
|
workflow_definition = AcidicJob.instrument(:define_workflow, **serialized_job) do
|
18
|
-
raise RedefiningWorkflowError if defined? @
|
16
|
+
raise RedefiningWorkflowError if defined? @__acidic_job_builder__
|
19
17
|
|
20
|
-
@
|
18
|
+
@__acidic_job_builder__ = Builder.new(@__acidic_job_plugins__)
|
21
19
|
|
22
20
|
raise UndefinedWorkflowBlockError unless block_given?
|
23
21
|
raise InvalidWorkflowBlockError if block.arity != 1
|
24
22
|
|
25
|
-
block.call @
|
23
|
+
block.call @__acidic_job_builder__
|
26
24
|
|
27
|
-
raise MissingStepsError if @
|
25
|
+
raise MissingStepsError if @__acidic_job_builder__.steps.empty?
|
28
26
|
|
29
27
|
# convert the array of steps into a hash of recovery_points and next steps
|
30
|
-
@
|
28
|
+
@__acidic_job_builder__.define_workflow
|
31
29
|
end
|
32
30
|
|
33
|
-
AcidicJob.instrument(:initialize_workflow,
|
31
|
+
AcidicJob.instrument(:initialize_workflow, definition: workflow_definition) do
|
34
32
|
transaction_args = case ::ActiveRecord::Base.connection.adapter_name.downcase.to_sym
|
35
33
|
# SQLite doesn't support `serializable` transactions
|
36
34
|
when :sqlite
|
@@ -40,7 +38,7 @@ module AcidicJob
|
|
40
38
|
end
|
41
39
|
idempotency_key = Digest::SHA256.hexdigest(JSON.fast_generate([self.class.name, unique_by], strict: true))
|
42
40
|
|
43
|
-
@
|
41
|
+
@__acidic_job_execution__ = ::ActiveRecord::Base.transaction(**transaction_args) do
|
44
42
|
record = Execution.find_by(idempotency_key: idempotency_key)
|
45
43
|
|
46
44
|
if record.present?
|
@@ -62,41 +60,52 @@ module AcidicJob
|
|
62
60
|
last_run_at: Time.current
|
63
61
|
)
|
64
62
|
else
|
63
|
+
starting_point = if workflow_definition.key?("steps")
|
64
|
+
workflow_definition["steps"].keys.first
|
65
|
+
else
|
66
|
+
# TODO: add deprecation warning
|
67
|
+
workflow_definition.keys.first
|
68
|
+
end
|
69
|
+
|
65
70
|
record = Execution.create!(
|
66
71
|
idempotency_key: idempotency_key,
|
67
72
|
serialized_job: serialized_job,
|
68
73
|
definition: workflow_definition,
|
69
|
-
recover_to:
|
74
|
+
recover_to: starting_point
|
70
75
|
)
|
71
76
|
end
|
72
77
|
|
73
78
|
record
|
74
79
|
end
|
75
80
|
end
|
76
|
-
@
|
81
|
+
@__acidic_job_context__ ||= Context.new(@__acidic_job_execution__)
|
77
82
|
|
78
|
-
AcidicJob.instrument(:process_workflow, execution: @
|
83
|
+
AcidicJob.instrument(:process_workflow, execution: @__acidic_job_execution__.attributes) do
|
79
84
|
# if the workflow record is already marked as finished, immediately return its result
|
80
|
-
return true if @
|
85
|
+
return true if @__acidic_job_execution__.finished?
|
81
86
|
|
82
87
|
loop do
|
83
|
-
break if @
|
88
|
+
break if @__acidic_job_execution__.finished?
|
84
89
|
|
85
|
-
current_step = @
|
90
|
+
current_step = @__acidic_job_execution__.recover_to
|
86
91
|
|
87
|
-
if not @
|
92
|
+
if not @__acidic_job_execution__.defined?(current_step) # rubocop:disable Style/Not
|
88
93
|
raise UndefinedStepError.new(current_step)
|
89
94
|
end
|
90
95
|
|
91
|
-
step_definition = @
|
96
|
+
step_definition = @__acidic_job_execution__.definition_for(current_step)
|
92
97
|
AcidicJob.instrument(:process_step, **step_definition) do
|
93
98
|
recover_to = catch(:halt) { take_step(step_definition) }
|
94
99
|
case recover_to
|
95
100
|
when HALT_STEP
|
96
|
-
@
|
101
|
+
@__acidic_job_execution__.record!(
|
102
|
+
step: step_definition.fetch("does"),
|
103
|
+
action: :halted,
|
104
|
+
timestamp: Time.now
|
105
|
+
)
|
97
106
|
return true
|
98
107
|
else
|
99
|
-
@
|
108
|
+
@__acidic_job_execution__.update!(recover_to: recover_to)
|
100
109
|
end
|
101
110
|
end
|
102
111
|
end
|
@@ -114,11 +123,19 @@ module AcidicJob
|
|
114
123
|
def step_retrying?
|
115
124
|
step_name = caller_locations.first.label
|
116
125
|
|
117
|
-
if not @
|
126
|
+
if not @__acidic_job_execution__.defined?(step_name) # rubocop:disable Style/IfUnlessModifier, Style/Not
|
118
127
|
raise UndefinedStepError.new(step_name)
|
119
128
|
end
|
120
129
|
|
121
|
-
@
|
130
|
+
@__acidic_job_execution__.entries.where(step: step_name, action: "started").count > 1
|
131
|
+
end
|
132
|
+
|
133
|
+
def execution
|
134
|
+
@__acidic_job_execution__
|
135
|
+
end
|
136
|
+
|
137
|
+
def ctx
|
138
|
+
@__acidic_job_context__
|
122
139
|
end
|
123
140
|
|
124
141
|
private
|
@@ -127,11 +144,11 @@ module AcidicJob
|
|
127
144
|
curr_step = step_definition.fetch("does")
|
128
145
|
next_step = step_definition.fetch("then")
|
129
146
|
|
130
|
-
return next_step if @
|
147
|
+
return next_step if @__acidic_job_execution__.entries.exists?(step: curr_step, action: :succeeded)
|
131
148
|
|
132
149
|
rescued_error = nil
|
133
150
|
begin
|
134
|
-
@
|
151
|
+
@__acidic_job_execution__.record!(step: curr_step, action: :started, timestamp: Time.now)
|
135
152
|
result = AcidicJob.instrument(:perform_step, **step_definition) do
|
136
153
|
perform_step_for(step_definition)
|
137
154
|
end
|
@@ -139,7 +156,7 @@ module AcidicJob
|
|
139
156
|
when REPEAT_STEP
|
140
157
|
curr_step
|
141
158
|
else
|
142
|
-
@
|
159
|
+
@__acidic_job_execution__.record!(step: curr_step, action: :succeeded, timestamp: Time.now, result: result)
|
143
160
|
next_step
|
144
161
|
end
|
145
162
|
rescue StandardError => e
|
@@ -148,7 +165,7 @@ module AcidicJob
|
|
148
165
|
ensure
|
149
166
|
if rescued_error
|
150
167
|
begin
|
151
|
-
@
|
168
|
+
@__acidic_job_execution__.record!(
|
152
169
|
step: curr_step,
|
153
170
|
action: :errored,
|
154
171
|
timestamp: Time.now,
|
@@ -159,7 +176,7 @@ module AcidicJob
|
|
159
176
|
# We're already inside an error condition, so swallow any additional
|
160
177
|
# errors from here and just send them to logs.
|
161
178
|
logger.error(
|
162
|
-
"Failed to store exception at step #{curr_step} for execution ##{@
|
179
|
+
"Failed to store exception at step #{curr_step} for execution ##{@__acidic_job_execution__.id}: #{e}."
|
163
180
|
)
|
164
181
|
end
|
165
182
|
end
|
@@ -168,15 +185,38 @@ module AcidicJob
|
|
168
185
|
|
169
186
|
def perform_step_for(step_definition)
|
170
187
|
step_name = step_definition.fetch("does")
|
171
|
-
|
188
|
+
begin
|
189
|
+
step_method = method(step_name)
|
190
|
+
rescue NameError
|
191
|
+
raise UndefinedMethodError.new(step_name)
|
192
|
+
end
|
172
193
|
|
173
194
|
raise InvalidMethodError.new(step_name) unless step_method.arity.zero?
|
174
195
|
|
175
|
-
|
196
|
+
plugin_pipeline_callable = @__acidic_job_plugins__.reverse.reduce(step_method) do |callable, plugin|
|
197
|
+
context = PluginContext.new(plugin, self, @__acidic_job_execution__, step_definition)
|
198
|
+
|
199
|
+
if context.inactive?
|
200
|
+
callable
|
201
|
+
else
|
202
|
+
proc do
|
203
|
+
called = false
|
204
|
+
|
205
|
+
result = plugin.around_step(context) do
|
206
|
+
raise DoublePluginCallError.new(plugin, step_name) if called
|
207
|
+
|
208
|
+
called = true
|
209
|
+
callable.call
|
210
|
+
end
|
211
|
+
|
212
|
+
raise MissingPluginCallError.new(plugin, step_name) unless called
|
213
|
+
|
214
|
+
result
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
176
218
|
|
177
|
-
catch(:repeat) {
|
178
|
-
rescue NameError
|
179
|
-
raise UndefinedMethodError.new(step_name)
|
219
|
+
catch(:repeat) { plugin_pipeline_callable.call }
|
180
220
|
end
|
181
221
|
end
|
182
222
|
end
|
data/lib/acidic_job.rb
CHANGED
@@ -6,6 +6,8 @@ require_relative "acidic_job/errors"
|
|
6
6
|
require_relative "acidic_job/builder"
|
7
7
|
require_relative "acidic_job/context"
|
8
8
|
require_relative "acidic_job/arguments"
|
9
|
+
require_relative "acidic_job/plugin_context"
|
10
|
+
require_relative "acidic_job/plugins/transactional_step"
|
9
11
|
require_relative "acidic_job/log_subscriber"
|
10
12
|
require_relative "acidic_job/workflow"
|
11
13
|
|
@@ -15,13 +17,13 @@ module AcidicJob
|
|
15
17
|
extend self
|
16
18
|
|
17
19
|
DEFAULT_LOGGER = ActiveSupport::Logger.new($stdout)
|
18
|
-
FINISHED_RECOVERY_POINT = "
|
20
|
+
FINISHED_RECOVERY_POINT = "__ACIDIC_JOB_WORKFLOW_FINISHED__"
|
19
21
|
|
20
22
|
mattr_accessor :logger, default: DEFAULT_LOGGER
|
21
23
|
mattr_accessor :connects_to
|
22
24
|
|
23
25
|
def instrument(channel, **options, &block)
|
24
|
-
ActiveSupport::Notifications.instrument("#{channel}.acidic_job", **options, &block)
|
26
|
+
ActiveSupport::Notifications.instrument("#{channel}.acidic_job", **options.deep_symbolize_keys, &block)
|
25
27
|
end
|
26
28
|
|
27
29
|
ActiveSupport.run_load_hooks(:acidic_job, self)
|
@@ -7,24 +7,25 @@ class <%= migration_class_name %> < ActiveRecord::Migration<%= migration_version
|
|
7
7
|
t.datetime :locked_at, null: true
|
8
8
|
t.string :recover_to, null: true
|
9
9
|
t.json :definition, null: true, default: "{}"
|
10
|
+
|
10
11
|
t.timestamps
|
11
12
|
end
|
12
13
|
|
13
14
|
create_table :acidic_job_entries do |t|
|
14
15
|
t.references :execution, null: false, foreign_key: { to_table: :acidic_job_executions }
|
15
|
-
t.string
|
16
|
-
t.string
|
17
|
-
t.datetime
|
18
|
-
t.json :
|
16
|
+
t.string :step, null: false
|
17
|
+
t.string :action, null: false
|
18
|
+
t.datetime :timestamp, null: false
|
19
|
+
t.json :data, null: true, default: "{}"
|
19
20
|
|
20
21
|
t.timestamps
|
21
22
|
end
|
22
|
-
add_index :acidic_job_entries, [:execution_id, :step]
|
23
|
+
add_index :acidic_job_entries, [:execution_id, :step, :action]
|
23
24
|
|
24
25
|
create_table :acidic_job_values do |t|
|
25
26
|
t.references :execution, null: false, foreign_key: { to_table: :acidic_job_executions }
|
26
|
-
t.string
|
27
|
-
t.json
|
27
|
+
t.string :key, null: false
|
28
|
+
t.json :value, null: false, default: "{}"
|
28
29
|
|
29
30
|
t.timestamps
|
30
31
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: acidic_job
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0.
|
4
|
+
version: 1.0.0.rc3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- fractaledmind
|
8
8
|
bindir: exe
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-05-
|
10
|
+
date: 2025-05-16 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: json
|
@@ -260,6 +260,8 @@ files:
|
|
260
260
|
- lib/acidic_job/engine.rb
|
261
261
|
- lib/acidic_job/errors.rb
|
262
262
|
- lib/acidic_job/log_subscriber.rb
|
263
|
+
- lib/acidic_job/plugin_context.rb
|
264
|
+
- lib/acidic_job/plugins/transactional_step.rb
|
263
265
|
- lib/acidic_job/serializers/exception_serializer.rb
|
264
266
|
- lib/acidic_job/serializers/job_serializer.rb
|
265
267
|
- lib/acidic_job/serializers/new_record_serializer.rb
|