easyop 0.1.2 → 0.1.4
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/CHANGELOG.md +196 -4
- data/README.md +390 -0
- data/lib/easyop/configuration.rb +8 -0
- data/lib/easyop/events/bus/active_support_notifications.rb +82 -0
- data/lib/easyop/events/bus/adapter.rb +119 -0
- data/lib/easyop/events/bus/custom.rb +51 -0
- data/lib/easyop/events/bus/memory.rb +64 -0
- data/lib/easyop/events/bus.rb +66 -0
- data/lib/easyop/events/event.rb +44 -0
- data/lib/easyop/events/registry.rb +128 -0
- data/lib/easyop/flow.rb +48 -0
- data/lib/easyop/plugins/event_handlers.rb +76 -0
- data/lib/easyop/plugins/events.rb +162 -0
- data/lib/easyop/plugins/recording.rb +112 -11
- data/lib/easyop/schema.rb +1 -1
- data/lib/easyop/version.rb +1 -1
- data/lib/easyop.rb +11 -0
- metadata +10 -1
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Easyop
|
|
4
|
+
module Plugins
|
|
5
|
+
# Subscribes an operation class to handle domain events.
|
|
6
|
+
#
|
|
7
|
+
# The handler operation receives the event payload merged into ctx, plus
|
|
8
|
+
# ctx.event (the Easyop::Events::Event object itself for sync dispatch).
|
|
9
|
+
#
|
|
10
|
+
# Basic usage:
|
|
11
|
+
#
|
|
12
|
+
# class SendOrderConfirmation < ApplicationOperation
|
|
13
|
+
# plugin Easyop::Plugins::EventHandlers
|
|
14
|
+
#
|
|
15
|
+
# on "order.placed"
|
|
16
|
+
#
|
|
17
|
+
# def call
|
|
18
|
+
# event = ctx.event # Easyop::Events::Event
|
|
19
|
+
# order_id = ctx.order_id # payload keys merged into ctx
|
|
20
|
+
# OrderMailer.confirm(order_id).deliver_later
|
|
21
|
+
# end
|
|
22
|
+
# end
|
|
23
|
+
#
|
|
24
|
+
# Async dispatch (requires Easyop::Plugins::Async also installed):
|
|
25
|
+
#
|
|
26
|
+
# class IndexOrder < ApplicationOperation
|
|
27
|
+
# plugin Easyop::Plugins::Async, queue: "indexing"
|
|
28
|
+
# plugin Easyop::Plugins::EventHandlers
|
|
29
|
+
#
|
|
30
|
+
# on "order.*", async: true
|
|
31
|
+
# on "inventory.**", async: true, queue: "low"
|
|
32
|
+
#
|
|
33
|
+
# def call
|
|
34
|
+
# # For async dispatch ctx.event_data is a Hash (serialized for ActiveJob).
|
|
35
|
+
# # Reconstruct if needed: Easyop::Events::Event.new(**ctx.event_data)
|
|
36
|
+
# SearchIndex.reindex(ctx.order_id)
|
|
37
|
+
# end
|
|
38
|
+
# end
|
|
39
|
+
#
|
|
40
|
+
# Wildcard patterns:
|
|
41
|
+
# "order.*" — matches order.placed, order.shipped (not order.payment.failed)
|
|
42
|
+
# "warehouse.**" — matches warehouse.stock.updated, warehouse.zone.moved, etc.
|
|
43
|
+
module EventHandlers
|
|
44
|
+
def self.install(base, **_options)
|
|
45
|
+
base.extend(ClassMethods)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
module ClassMethods
|
|
49
|
+
# Subscribe this operation to events matching +pattern+.
|
|
50
|
+
#
|
|
51
|
+
# Registration happens at class-load time and is bound to the bus that is
|
|
52
|
+
# active when the class is evaluated. Configure the bus before loading
|
|
53
|
+
# handler classes (e.g. in a Rails initializer that runs before autoloading).
|
|
54
|
+
#
|
|
55
|
+
# @param pattern [String, Regexp] event name or glob
|
|
56
|
+
# @param async [Boolean] enqueue via call_async (requires Async plugin)
|
|
57
|
+
# @param options [Hash] e.g. queue: "low" (overrides Async default)
|
|
58
|
+
def on(pattern, async: false, **options)
|
|
59
|
+
_event_handler_registrations << { pattern: pattern, async: async, options: options }
|
|
60
|
+
|
|
61
|
+
Easyop::Events::Registry.register_handler(
|
|
62
|
+
pattern: pattern,
|
|
63
|
+
handler_class: self,
|
|
64
|
+
async: async,
|
|
65
|
+
**options
|
|
66
|
+
)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# @api private — list of registrations declared on this class
|
|
70
|
+
def _event_handler_registrations
|
|
71
|
+
@_event_handler_registrations ||= []
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Easyop
|
|
4
|
+
module Plugins
|
|
5
|
+
# Emits domain events after an operation completes.
|
|
6
|
+
#
|
|
7
|
+
# Install on a base operation class to inherit into all subclasses:
|
|
8
|
+
#
|
|
9
|
+
# class ApplicationOperation
|
|
10
|
+
# include Easyop::Operation
|
|
11
|
+
# plugin Easyop::Plugins::Events
|
|
12
|
+
# end
|
|
13
|
+
#
|
|
14
|
+
# Then declare events on individual operations:
|
|
15
|
+
#
|
|
16
|
+
# class PlaceOrder < ApplicationOperation
|
|
17
|
+
# emits "order.placed", on: :success, payload: [:order_id, :total]
|
|
18
|
+
# emits "order.failed", on: :failure, payload: ->(ctx) { { error: ctx.error } }
|
|
19
|
+
# emits "order.attempted", on: :always
|
|
20
|
+
#
|
|
21
|
+
# def call
|
|
22
|
+
# ctx.order_id = Order.create!(ctx.to_h).id
|
|
23
|
+
# end
|
|
24
|
+
# end
|
|
25
|
+
#
|
|
26
|
+
# Plugin options:
|
|
27
|
+
# bus: [Bus::Base, nil] per-class bus override (default: global registry bus)
|
|
28
|
+
# metadata: [Hash, Proc, nil] extra metadata merged into every event from this class
|
|
29
|
+
#
|
|
30
|
+
# `emits` DSL options:
|
|
31
|
+
# on: [:success (default), :failure, :always]
|
|
32
|
+
# payload: [Proc, Array, nil] Proc receives ctx; Array slices ctx keys; nil = full ctx.to_h
|
|
33
|
+
# guard: [Proc, nil] extra condition — event only fires if truthy
|
|
34
|
+
module Events
|
|
35
|
+
def self.install(base, bus: nil, metadata: nil, **_options)
|
|
36
|
+
base.extend(ClassMethods)
|
|
37
|
+
base.prepend(RunWrapper)
|
|
38
|
+
base.instance_variable_set(:@_events_bus, bus)
|
|
39
|
+
base.instance_variable_set(:@_events_metadata, metadata)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
module ClassMethods
|
|
43
|
+
# Declare an event this operation emits after execution.
|
|
44
|
+
#
|
|
45
|
+
# @example
|
|
46
|
+
# emits "order.placed", on: :success, payload: [:order_id]
|
|
47
|
+
# emits "order.failed", on: :failure, payload: ->(ctx) { { error: ctx.error } }
|
|
48
|
+
#
|
|
49
|
+
# @param name [String]
|
|
50
|
+
# @param on [Symbol] :success (default), :failure, or :always
|
|
51
|
+
# @param payload [Proc, Array, nil]
|
|
52
|
+
# @param guard [Proc, nil] optional condition — fires only when truthy
|
|
53
|
+
def emits(name, on: :success, payload: nil, guard: nil)
|
|
54
|
+
_emitted_events << { name: name.to_s, on: on, payload: payload, guard: guard }
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# @api private — inheritable list of emits declarations
|
|
58
|
+
def _emitted_events
|
|
59
|
+
@_emitted_events ||= _inherited_emitted_events
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# @api private — bus for this class (falls back to superclass, then global registry)
|
|
63
|
+
def _events_bus
|
|
64
|
+
if instance_variable_defined?(:@_events_bus)
|
|
65
|
+
@_events_bus
|
|
66
|
+
elsif superclass.respond_to?(:_events_bus)
|
|
67
|
+
superclass._events_bus
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# @api private — metadata for this class (falls back to superclass)
|
|
72
|
+
def _events_metadata
|
|
73
|
+
if instance_variable_defined?(:@_events_metadata)
|
|
74
|
+
@_events_metadata
|
|
75
|
+
elsif superclass.respond_to?(:_events_metadata)
|
|
76
|
+
superclass._events_metadata
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
private
|
|
81
|
+
|
|
82
|
+
def _inherited_emitted_events
|
|
83
|
+
superclass.respond_to?(:_emitted_events) ? superclass._emitted_events.dup : []
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
module RunWrapper
|
|
88
|
+
# Wraps _easyop_run to publish declared events in an ensure block.
|
|
89
|
+
# Events fire AFTER the operation completes — success, failure, or exception.
|
|
90
|
+
def _easyop_run(ctx, raise_on_failure:)
|
|
91
|
+
super
|
|
92
|
+
ensure
|
|
93
|
+
_events_publish_all(ctx)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
private
|
|
97
|
+
|
|
98
|
+
def _events_publish_all(ctx)
|
|
99
|
+
declarations = self.class._emitted_events
|
|
100
|
+
return if declarations.empty?
|
|
101
|
+
|
|
102
|
+
bus = self.class._events_bus || Easyop::Events::Registry.bus
|
|
103
|
+
|
|
104
|
+
declarations.each do |decl|
|
|
105
|
+
next unless _events_should_fire?(decl, ctx)
|
|
106
|
+
|
|
107
|
+
event = _events_build_event(decl, ctx)
|
|
108
|
+
bus.publish(event)
|
|
109
|
+
rescue StandardError
|
|
110
|
+
# Individual publish failures must never crash the operation.
|
|
111
|
+
# Log if Rails is available.
|
|
112
|
+
_events_log_warning($ERROR_INFO)
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def _events_should_fire?(decl, ctx)
|
|
117
|
+
case decl[:on]
|
|
118
|
+
when :success then return false unless ctx.success?
|
|
119
|
+
when :failure then return false unless ctx.failure?
|
|
120
|
+
when :always then nil # always fire
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
guard = decl[:guard]
|
|
124
|
+
guard ? guard.call(ctx) : true
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def _events_build_event(decl, ctx)
|
|
128
|
+
Easyop::Events::Event.new(
|
|
129
|
+
name: decl[:name],
|
|
130
|
+
payload: _events_extract_payload(decl[:payload], ctx),
|
|
131
|
+
metadata: _events_build_metadata(ctx),
|
|
132
|
+
source: self.class.name
|
|
133
|
+
)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def _events_extract_payload(payload_spec, ctx)
|
|
137
|
+
case payload_spec
|
|
138
|
+
when Proc then payload_spec.call(ctx)
|
|
139
|
+
when Array then ctx.slice(*payload_spec)
|
|
140
|
+
when nil then ctx.to_h
|
|
141
|
+
else payload_spec
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def _events_build_metadata(ctx)
|
|
146
|
+
meta = self.class._events_metadata
|
|
147
|
+
case meta
|
|
148
|
+
when Proc then meta.call(ctx)
|
|
149
|
+
when Hash then meta.dup
|
|
150
|
+
else {}
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def _events_log_warning(err)
|
|
155
|
+
return unless defined?(Rails) && Rails.respond_to?(:logger) && Rails.logger
|
|
156
|
+
|
|
157
|
+
Rails.logger.warn "[EasyOp::Events] Failed to publish event: #{err.message}"
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'securerandom'
|
|
4
|
+
|
|
3
5
|
module Easyop
|
|
4
6
|
module Plugins
|
|
5
7
|
# Records operation executions to a database model.
|
|
@@ -18,6 +20,15 @@ module Easyop
|
|
|
18
20
|
# duration_ms :float
|
|
19
21
|
# performed_at :datetime, null: false
|
|
20
22
|
#
|
|
23
|
+
# Optional flow-tracing columns:
|
|
24
|
+
# root_reference_id :string # shared across entire execution tree
|
|
25
|
+
# reference_id :string # unique to this operation execution
|
|
26
|
+
# parent_operation_name :string # class name of the direct parent
|
|
27
|
+
# parent_reference_id :string # reference_id of the direct parent
|
|
28
|
+
#
|
|
29
|
+
# Optional result column:
|
|
30
|
+
# result_data :text # stored as JSON — selected ctx keys after call
|
|
31
|
+
#
|
|
21
32
|
# Opt out per operation class:
|
|
22
33
|
# class MyOp < ApplicationOperation
|
|
23
34
|
# recording false
|
|
@@ -26,15 +37,24 @@ module Easyop
|
|
|
26
37
|
# Options:
|
|
27
38
|
# model: (required) ActiveRecord class
|
|
28
39
|
# record_params: true pass false to skip params serialization
|
|
40
|
+
# record_result: nil configure result capture at plugin level (Hash/Proc/Symbol)
|
|
29
41
|
module Recording
|
|
30
42
|
# Sensitive keys scrubbed from params_data before persisting.
|
|
31
43
|
SCRUBBED_KEYS = %i[password password_confirmation token secret api_key].freeze
|
|
32
44
|
|
|
33
|
-
|
|
45
|
+
# Internal ctx keys used for flow tracing — excluded from params_data.
|
|
46
|
+
INTERNAL_CTX_KEYS = %i[
|
|
47
|
+
__recording_root_reference_id
|
|
48
|
+
__recording_parent_operation_name
|
|
49
|
+
__recording_parent_reference_id
|
|
50
|
+
].freeze
|
|
51
|
+
|
|
52
|
+
def self.install(base, model:, record_params: true, record_result: nil, **_options)
|
|
34
53
|
base.extend(ClassMethods)
|
|
35
54
|
base.prepend(RunWrapper)
|
|
36
|
-
base.instance_variable_set(:@_recording_model,
|
|
37
|
-
base.instance_variable_set(:@_recording_record_params,
|
|
55
|
+
base.instance_variable_set(:@_recording_model, model)
|
|
56
|
+
base.instance_variable_set(:@_recording_record_params, record_params)
|
|
57
|
+
base.instance_variable_set(:@_recording_record_result, record_result)
|
|
38
58
|
end
|
|
39
59
|
|
|
40
60
|
module ClassMethods
|
|
@@ -62,6 +82,33 @@ module Easyop
|
|
|
62
82
|
true
|
|
63
83
|
end
|
|
64
84
|
end
|
|
85
|
+
|
|
86
|
+
# DSL for capturing result data after the operation runs.
|
|
87
|
+
# Three forms:
|
|
88
|
+
# record_result attrs: :key # one or more ctx keys
|
|
89
|
+
# record_result { |ctx| { k: ctx.k } } # block
|
|
90
|
+
# record_result :build_result # private instance method name
|
|
91
|
+
def record_result(value = nil, attrs: nil, &block)
|
|
92
|
+
@_recording_record_result = if block
|
|
93
|
+
block
|
|
94
|
+
elsif attrs
|
|
95
|
+
{ attrs: attrs }
|
|
96
|
+
elsif value.is_a?(Symbol)
|
|
97
|
+
value
|
|
98
|
+
else
|
|
99
|
+
value
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def _recording_record_result_config
|
|
104
|
+
if instance_variable_defined?(:@_recording_record_result)
|
|
105
|
+
@_recording_record_result
|
|
106
|
+
elsif superclass.respond_to?(:_recording_record_result_config)
|
|
107
|
+
superclass._recording_record_result_config
|
|
108
|
+
else
|
|
109
|
+
nil
|
|
110
|
+
end
|
|
111
|
+
end
|
|
65
112
|
end
|
|
66
113
|
|
|
67
114
|
module RunWrapper
|
|
@@ -70,6 +117,23 @@ module Easyop
|
|
|
70
117
|
return super unless (model = self.class._recording_model)
|
|
71
118
|
return super unless self.class.name # skip anonymous classes
|
|
72
119
|
|
|
120
|
+
# -- Flow tracing --
|
|
121
|
+
# Each operation gets its own reference_id. The root_reference_id is
|
|
122
|
+
# shared across the entire execution tree via ctx (set once, inherited).
|
|
123
|
+
reference_id = SecureRandom.uuid
|
|
124
|
+
root_reference_id = ctx[:__recording_root_reference_id] ||= SecureRandom.uuid
|
|
125
|
+
|
|
126
|
+
# Read current parent context — these become THIS operation's parent fields.
|
|
127
|
+
parent_operation_name = ctx[:__recording_parent_operation_name]
|
|
128
|
+
parent_reference_id = ctx[:__recording_parent_reference_id]
|
|
129
|
+
|
|
130
|
+
# Set THIS operation as the parent for any children that run inside super.
|
|
131
|
+
# Save the previous values so we can restore them after (for siblings).
|
|
132
|
+
prev_parent_name = parent_operation_name
|
|
133
|
+
prev_parent_id = parent_reference_id
|
|
134
|
+
ctx[:__recording_parent_operation_name] = self.class.name
|
|
135
|
+
ctx[:__recording_parent_reference_id] = reference_id
|
|
136
|
+
|
|
73
137
|
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
74
138
|
super
|
|
75
139
|
ensure
|
|
@@ -78,22 +142,37 @@ module Easyop
|
|
|
78
142
|
# branch the tap block would be skipped and failures inside flows would
|
|
79
143
|
# never be persisted.
|
|
80
144
|
if start
|
|
145
|
+
# Restore parent context so sibling steps see the correct parent.
|
|
146
|
+
ctx[:__recording_parent_operation_name] = prev_parent_name
|
|
147
|
+
ctx[:__recording_parent_reference_id] = prev_parent_id
|
|
148
|
+
|
|
81
149
|
ms = ((Process.clock_gettime(Process::CLOCK_MONOTONIC) - start) * 1000).round(2)
|
|
82
|
-
_recording_persist!(ctx, model, ms
|
|
150
|
+
_recording_persist!(ctx, model, ms,
|
|
151
|
+
root_reference_id: root_reference_id,
|
|
152
|
+
reference_id: reference_id,
|
|
153
|
+
parent_operation_name: parent_operation_name,
|
|
154
|
+
parent_reference_id: parent_reference_id)
|
|
83
155
|
end
|
|
84
156
|
end
|
|
85
157
|
|
|
86
158
|
private
|
|
87
159
|
|
|
88
|
-
def _recording_persist!(ctx, model, duration_ms
|
|
160
|
+
def _recording_persist!(ctx, model, duration_ms,
|
|
161
|
+
root_reference_id: nil, reference_id: nil,
|
|
162
|
+
parent_operation_name: nil, parent_reference_id: nil)
|
|
89
163
|
attrs = {
|
|
90
|
-
operation_name:
|
|
91
|
-
success:
|
|
92
|
-
error_message:
|
|
93
|
-
performed_at:
|
|
94
|
-
duration_ms:
|
|
164
|
+
operation_name: self.class.name,
|
|
165
|
+
success: ctx.success?,
|
|
166
|
+
error_message: ctx.error,
|
|
167
|
+
performed_at: Time.current,
|
|
168
|
+
duration_ms: duration_ms,
|
|
169
|
+
root_reference_id: root_reference_id,
|
|
170
|
+
reference_id: reference_id,
|
|
171
|
+
parent_operation_name: parent_operation_name,
|
|
172
|
+
parent_reference_id: parent_reference_id
|
|
95
173
|
}
|
|
96
174
|
attrs[:params_data] = _recording_safe_params(ctx) if self.class._recording_record_params?
|
|
175
|
+
attrs[:result_data] = _recording_safe_result(ctx) if self.class._recording_record_result_config
|
|
97
176
|
|
|
98
177
|
# Only write columns the model actually has
|
|
99
178
|
safe = attrs.select { |k, _| model.column_names.include?(k.to_s) }
|
|
@@ -104,13 +183,35 @@ module Easyop
|
|
|
104
183
|
|
|
105
184
|
def _recording_safe_params(ctx)
|
|
106
185
|
ctx.to_h
|
|
107
|
-
.except(*SCRUBBED_KEYS)
|
|
186
|
+
.except(*SCRUBBED_KEYS, *INTERNAL_CTX_KEYS)
|
|
108
187
|
.transform_values { |v| v.is_a?(ActiveRecord::Base) ? { id: v.id, class: v.class.name } : v }
|
|
109
188
|
.to_json
|
|
110
189
|
rescue
|
|
111
190
|
nil
|
|
112
191
|
end
|
|
113
192
|
|
|
193
|
+
def _recording_safe_result(ctx)
|
|
194
|
+
config = self.class._recording_record_result_config
|
|
195
|
+
return nil unless config
|
|
196
|
+
|
|
197
|
+
raw = case config
|
|
198
|
+
when Hash
|
|
199
|
+
keys = Array(config[:attrs])
|
|
200
|
+
keys.each_with_object({}) { |k, h| h[k] = ctx[k] }
|
|
201
|
+
when Proc
|
|
202
|
+
config.call(ctx)
|
|
203
|
+
when Symbol
|
|
204
|
+
send(config)
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
return nil unless raw.is_a?(Hash)
|
|
208
|
+
|
|
209
|
+
raw.transform_values { |v| v.is_a?(ActiveRecord::Base) ? { id: v.id, class: v.class.name } : v }
|
|
210
|
+
.to_json
|
|
211
|
+
rescue
|
|
212
|
+
nil
|
|
213
|
+
end
|
|
214
|
+
|
|
114
215
|
def _recording_warn(err)
|
|
115
216
|
return unless defined?(Rails) && Rails.respond_to?(:logger)
|
|
116
217
|
Rails.logger.warn "[EasyOp::Recording] Failed to record #{self.class.name}: #{err.message}"
|
data/lib/easyop/schema.rb
CHANGED
data/lib/easyop/version.rb
CHANGED
data/lib/easyop.rb
CHANGED
|
@@ -18,6 +18,17 @@ require_relative "easyop/flow"
|
|
|
18
18
|
# require "easyop/plugins/recording"
|
|
19
19
|
# require "easyop/plugins/async"
|
|
20
20
|
|
|
21
|
+
# Domain event plugins — require together or individually:
|
|
22
|
+
# require "easyop/events/event"
|
|
23
|
+
# require "easyop/events/bus"
|
|
24
|
+
# require "easyop/events/bus/memory"
|
|
25
|
+
# require "easyop/events/bus/active_support_notifications"
|
|
26
|
+
# require "easyop/events/bus/custom"
|
|
27
|
+
# require "easyop/events/bus/adapter" # inherit this to build a custom bus
|
|
28
|
+
# require "easyop/events/registry"
|
|
29
|
+
# require "easyop/plugins/events"
|
|
30
|
+
# require "easyop/plugins/event_handlers"
|
|
31
|
+
|
|
21
32
|
module Easyop
|
|
22
33
|
# Convenience: inherit from this instead of including Easyop::Operation
|
|
23
34
|
# when you want a common base class for all your operations.
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: easyop
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Pawel Niemczyk
|
|
@@ -53,12 +53,21 @@ files:
|
|
|
53
53
|
- lib/easyop.rb
|
|
54
54
|
- lib/easyop/configuration.rb
|
|
55
55
|
- lib/easyop/ctx.rb
|
|
56
|
+
- lib/easyop/events/bus.rb
|
|
57
|
+
- lib/easyop/events/bus/active_support_notifications.rb
|
|
58
|
+
- lib/easyop/events/bus/adapter.rb
|
|
59
|
+
- lib/easyop/events/bus/custom.rb
|
|
60
|
+
- lib/easyop/events/bus/memory.rb
|
|
61
|
+
- lib/easyop/events/event.rb
|
|
62
|
+
- lib/easyop/events/registry.rb
|
|
56
63
|
- lib/easyop/flow.rb
|
|
57
64
|
- lib/easyop/flow_builder.rb
|
|
58
65
|
- lib/easyop/hooks.rb
|
|
59
66
|
- lib/easyop/operation.rb
|
|
60
67
|
- lib/easyop/plugins/async.rb
|
|
61
68
|
- lib/easyop/plugins/base.rb
|
|
69
|
+
- lib/easyop/plugins/event_handlers.rb
|
|
70
|
+
- lib/easyop/plugins/events.rb
|
|
62
71
|
- lib/easyop/plugins/instrumentation.rb
|
|
63
72
|
- lib/easyop/plugins/recording.rb
|
|
64
73
|
- lib/easyop/plugins/transactional.rb
|