ruby_event_store-outbox 0.0.11 → 0.0.12
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/lib/generators/ruby_event_store/outbox/templates/create_event_store_outbox_template.rb +8 -0
- data/lib/ruby_event_store/outbox.rb +1 -0
- data/lib/ruby_event_store/outbox/cli.rb +3 -1
- data/lib/ruby_event_store/outbox/consumer.rb +120 -45
- data/lib/ruby_event_store/outbox/consumer_process.rb +6 -0
- data/lib/ruby_event_store/outbox/fetch_specification.rb +13 -0
- data/lib/ruby_event_store/outbox/metrics/influx.rb +16 -2
- data/lib/ruby_event_store/outbox/metrics/null.rb +3 -0
- data/lib/ruby_event_store/outbox/record.rb +88 -0
- data/lib/ruby_event_store/outbox/sidekiq_processor.rb +44 -0
- data/lib/ruby_event_store/outbox/sidekiq_producer.rb +27 -0
- data/lib/ruby_event_store/outbox/sidekiq_scheduler.rb +9 -16
- data/lib/ruby_event_store/outbox/version.rb +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c1d9945d7b34ce9254c8150dc671453cdf3c72a5799bc39b11f1e86e109baa8c
|
4
|
+
data.tar.gz: 58fb2365dd712495a8681fb78ed444662422cfddf3b2b165fda5e4299082dc91
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 01fbff71356a4095838f197b96e9673762d02f9677d0d0df3075757861c273131b636b6e181db0ce165fa7d04f2d45b6450e4cd19a49261eb6f9e87d6782b8f7
|
7
|
+
data.tar.gz: 53bea6ab8e0e3c2bfad41018fbc65d7f2de33af168b05d5578cf6349a56614be4c4e00448b3954ed59ca42f637908e635701f5c2eb2ef7d4958f1078c8eac18d
|
@@ -11,5 +11,13 @@ class CreateEventStoreOutbox < ActiveRecord::Migration<%= migration_version %>
|
|
11
11
|
end
|
12
12
|
add_index :event_store_outbox, [:format, :enqueued_at, :split_key], name: "index_event_store_outbox_for_pool"
|
13
13
|
add_index :event_store_outbox, [:created_at, :enqueued_at], name: "index_event_store_outbox_for_clear"
|
14
|
+
|
15
|
+
create_table(:event_store_outbox_locks, force: false) do |t|
|
16
|
+
t.string :format, null: false
|
17
|
+
t.string :split_key, null: false
|
18
|
+
t.datetime :locked_at, null: true
|
19
|
+
t.string :locked_by, null: true, limit: 36
|
20
|
+
end
|
21
|
+
add_index :event_store_outbox_locks, [:format, :split_key], name: "index_event_store_outbox_locks_for_locking", unique: true
|
14
22
|
end
|
15
23
|
end
|
@@ -59,7 +59,8 @@ module RubyEventStore
|
|
59
59
|
end
|
60
60
|
|
61
61
|
def build_consumer(options)
|
62
|
-
|
62
|
+
consumer_uuid = SecureRandom.uuid
|
63
|
+
logger = Logger.new(STDOUT, level: options.log_level, progname: "RES-Outbox #{consumer_uuid}")
|
63
64
|
consumer_configuration = Consumer::Configuration.new(
|
64
65
|
split_keys: options.split_keys,
|
65
66
|
message_format: options.message_format,
|
@@ -69,6 +70,7 @@ module RubyEventStore
|
|
69
70
|
)
|
70
71
|
metrics = Metrics.from_url(options.metrics_url)
|
71
72
|
outbox_consumer = RubyEventStore::Outbox::Consumer.new(
|
73
|
+
consumer_uuid,
|
72
74
|
options,
|
73
75
|
logger: logger,
|
74
76
|
metrics: metrics,
|
@@ -3,11 +3,13 @@ require "redis"
|
|
3
3
|
require "active_record"
|
4
4
|
require "ruby_event_store/outbox/record"
|
5
5
|
require "ruby_event_store/outbox/sidekiq5_format"
|
6
|
+
require "ruby_event_store/outbox/sidekiq_processor"
|
6
7
|
|
7
8
|
module RubyEventStore
|
8
9
|
module Outbox
|
9
10
|
class Consumer
|
10
11
|
SLEEP_TIME_WHEN_NOTHING_TO_DO = 0.1
|
12
|
+
MAXIMUM_BATCH_FETCHES_IN_ONE_LOCK = 10
|
11
13
|
|
12
14
|
class Configuration
|
13
15
|
def initialize(
|
@@ -38,28 +40,26 @@ module RubyEventStore
|
|
38
40
|
attr_reader :split_keys, :message_format, :batch_size, :database_url, :redis_url
|
39
41
|
end
|
40
42
|
|
41
|
-
def initialize(configuration, clock: Time, logger:, metrics:)
|
43
|
+
def initialize(consumer_uuid, configuration, clock: Time, logger:, metrics:)
|
42
44
|
@split_keys = configuration.split_keys
|
43
45
|
@clock = clock
|
44
|
-
@redis = Redis.new(url: configuration.redis_url)
|
45
46
|
@logger = logger
|
46
47
|
@metrics = metrics
|
47
48
|
@batch_size = configuration.batch_size
|
49
|
+
@consumer_uuid = consumer_uuid
|
48
50
|
ActiveRecord::Base.establish_connection(configuration.database_url) unless ActiveRecord::Base.connected?
|
49
51
|
if ActiveRecord::Base.connection.adapter_name == "Mysql2"
|
50
|
-
ActiveRecord::Base.connection.execute("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;")
|
51
52
|
ActiveRecord::Base.connection.execute("SET SESSION innodb_lock_wait_timeout = 1;")
|
52
53
|
end
|
53
54
|
|
54
55
|
raise "Unknown format" if configuration.message_format != SIDEKIQ5_FORMAT
|
55
|
-
@
|
56
|
+
@processor = SidekiqProcessor.new(Redis.new(url: configuration.redis_url))
|
56
57
|
|
57
58
|
@gracefully_shutting_down = false
|
58
59
|
prepare_traps
|
59
60
|
end
|
60
61
|
|
61
62
|
def init
|
62
|
-
@redis.sadd("queues", split_keys)
|
63
63
|
logger.info("Initiated RubyEventStore::Outbox v#{VERSION}")
|
64
64
|
logger.info("Handling split keys: #{split_keys ? split_keys.join(", ") : "(all of them)"}")
|
65
65
|
end
|
@@ -76,62 +76,129 @@ module RubyEventStore
|
|
76
76
|
end
|
77
77
|
|
78
78
|
def one_loop
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
79
|
+
remaining_split_keys = @split_keys.dup
|
80
|
+
|
81
|
+
was_something_changed = false
|
82
|
+
while (split_key = remaining_split_keys.shift)
|
83
|
+
was_something_changed |= handle_split(FetchSpecification.new(processor.message_format, split_key))
|
84
|
+
end
|
85
|
+
was_something_changed
|
86
|
+
end
|
87
|
+
|
88
|
+
def handle_split(fetch_specification)
|
89
|
+
obtained_lock = obtain_lock_for_process(fetch_specification)
|
90
|
+
return false unless obtained_lock
|
91
|
+
|
92
|
+
something_processed = false
|
93
|
+
|
94
|
+
MAXIMUM_BATCH_FETCHES_IN_ONE_LOCK.times do
|
95
|
+
batch = retrieve_batch(fetch_specification)
|
96
|
+
if batch.empty?
|
97
|
+
break
|
86
98
|
end
|
87
99
|
|
88
|
-
now = @clock.now.utc
|
89
100
|
failed_record_ids = []
|
90
|
-
|
101
|
+
updated_record_ids = []
|
102
|
+
batch.each do |record|
|
91
103
|
begin
|
92
|
-
|
93
|
-
|
104
|
+
now = @clock.now.utc
|
105
|
+
processor.process(record, now)
|
106
|
+
|
107
|
+
record.update_column(:enqueued_at, now)
|
108
|
+
something_processed |= true
|
109
|
+
updated_record_ids << record.id
|
94
110
|
rescue => e
|
95
|
-
failed_record_ids.
|
111
|
+
failed_record_ids << record.id
|
96
112
|
e.full_message.split($/).each {|line| logger.error(line) }
|
97
113
|
end
|
98
114
|
end
|
99
115
|
|
100
|
-
|
101
|
-
|
102
|
-
|
116
|
+
metrics.write_point_queue(
|
117
|
+
enqueued: updated_record_ids.size,
|
118
|
+
failed: failed_record_ids.size,
|
119
|
+
format: fetch_specification.message_format,
|
120
|
+
split_key: fetch_specification.split_key,
|
121
|
+
remaining: get_remaining_count(fetch_specification)
|
122
|
+
)
|
103
123
|
|
104
124
|
logger.info "Sent #{updated_record_ids.size} messages from outbox table"
|
105
|
-
|
125
|
+
|
126
|
+
obtained_lock = refresh_lock_for_process(obtained_lock)
|
127
|
+
break unless obtained_lock
|
106
128
|
end
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
129
|
+
|
130
|
+
metrics.write_point_queue(
|
131
|
+
format: fetch_specification.message_format,
|
132
|
+
split_key: fetch_specification.split_key,
|
133
|
+
remaining: get_remaining_count(fetch_specification)
|
134
|
+
) unless something_processed
|
135
|
+
|
136
|
+
release_lock_for_process(fetch_specification)
|
137
|
+
|
138
|
+
processor.after_batch
|
139
|
+
|
140
|
+
something_processed
|
115
141
|
end
|
116
142
|
|
117
143
|
private
|
118
|
-
attr_reader :split_keys, :logger, :
|
119
|
-
|
120
|
-
def
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
144
|
+
attr_reader :split_keys, :logger, :batch_size, :metrics, :processor, :consumer_uuid
|
145
|
+
|
146
|
+
def obtain_lock_for_process(fetch_specification)
|
147
|
+
result = Lock.obtain(fetch_specification, consumer_uuid, clock: @clock)
|
148
|
+
case result
|
149
|
+
when :deadlocked
|
150
|
+
logger.warn "Obtaining lock for split_key '#{fetch_specification.split_key}' failed (deadlock)"
|
151
|
+
metrics.write_operation_result("obtain", "deadlocked")
|
152
|
+
return false
|
153
|
+
when :lock_timeout
|
154
|
+
logger.warn "Obtaining lock for split_key '#{fetch_specification.split_key}' failed (lock timeout)"
|
155
|
+
metrics.write_operation_result("obtain", "lock_timeout")
|
156
|
+
return false
|
157
|
+
when :taken
|
158
|
+
logger.debug "Obtaining lock for split_key '#{fetch_specification.split_key}' unsuccessful (taken)"
|
159
|
+
metrics.write_operation_result("obtain", "taken")
|
160
|
+
return false
|
161
|
+
else
|
162
|
+
return result
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def release_lock_for_process(fetch_specification)
|
167
|
+
result = Lock.release(fetch_specification, consumer_uuid)
|
168
|
+
case result
|
169
|
+
when :ok
|
170
|
+
when :deadlocked
|
171
|
+
logger.warn "Releasing lock for split_key '#{fetch_specification.split_key}' failed (deadlock)"
|
172
|
+
metrics.write_operation_result("release", "deadlocked")
|
173
|
+
when :lock_timeout
|
174
|
+
logger.warn "Releasing lock for split_key '#{fetch_specification.split_key}' failed (lock timeout)"
|
175
|
+
metrics.write_operation_result("release", "lock_timeout")
|
176
|
+
when :not_taken_by_this_process
|
177
|
+
logger.debug "Releasing lock for split_key '#{fetch_specification.split_key}' failed (not taken by this process)"
|
178
|
+
metrics.write_operation_result("release", "not_taken_by_this_process")
|
179
|
+
else
|
180
|
+
raise "Unexpected result #{result}"
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
def refresh_lock_for_process(lock)
|
185
|
+
result = lock.refresh(clock: @clock)
|
186
|
+
case result
|
187
|
+
when :deadlocked
|
188
|
+
logger.warn "Refreshing lock for split_key '#{lock.split_key}' failed (deadlock)"
|
189
|
+
metrics.write_operation_result("refresh", "deadlocked")
|
190
|
+
return false
|
191
|
+
when :lock_timeout
|
192
|
+
logger.warn "Refreshing lock for split_key '#{lock.split_key}' failed (lock timeout)"
|
193
|
+
metrics.write_operation_result("refresh", "lock_timeout")
|
194
|
+
return false
|
195
|
+
when :stolen
|
196
|
+
logger.debug "Refreshing lock for split_key '#{lock.split_key}' unsuccessful (stolen)"
|
197
|
+
metrics.write_operation_result("refresh", "stolen")
|
198
|
+
return false
|
199
|
+
else
|
200
|
+
return result
|
132
201
|
end
|
133
|
-
@redis.lpush("queue:#{split_key}", elements)
|
134
|
-
failed
|
135
202
|
end
|
136
203
|
|
137
204
|
def prepare_traps
|
@@ -146,6 +213,14 @@ module RubyEventStore
|
|
146
213
|
def initiate_graceful_shutdown
|
147
214
|
@gracefully_shutting_down = true
|
148
215
|
end
|
216
|
+
|
217
|
+
def retrieve_batch(fetch_specification)
|
218
|
+
Record.remaining_for(fetch_specification).order("id ASC").limit(batch_size).to_a
|
219
|
+
end
|
220
|
+
|
221
|
+
def get_remaining_count(fetch_specification)
|
222
|
+
Record.remaining_for(fetch_specification).count
|
223
|
+
end
|
149
224
|
end
|
150
225
|
end
|
151
226
|
end
|
@@ -17,14 +17,28 @@ module RubyEventStore
|
|
17
17
|
@influxdb_client = InfluxDB::Client.new(**options)
|
18
18
|
end
|
19
19
|
|
20
|
-
def
|
20
|
+
def write_operation_result(operation, result)
|
21
|
+
write_point("ruby_event_store.outbox.lock", {
|
22
|
+
values: {
|
23
|
+
value: 1,
|
24
|
+
},
|
25
|
+
tags: {
|
26
|
+
operation: operation,
|
27
|
+
result: result,
|
28
|
+
}
|
29
|
+
})
|
30
|
+
end
|
31
|
+
|
32
|
+
def write_point_queue(enqueued: 0, failed: 0, remaining: 0, format: nil, split_key: nil)
|
21
33
|
write_point("ruby_event_store.outbox.queue", {
|
22
34
|
values: {
|
23
35
|
enqueued: enqueued,
|
24
36
|
failed: failed,
|
37
|
+
remaining: remaining,
|
25
38
|
},
|
26
39
|
tags: {
|
27
|
-
|
40
|
+
format: format,
|
41
|
+
split_key: split_key,
|
28
42
|
}
|
29
43
|
})
|
30
44
|
end
|
@@ -8,9 +8,97 @@ module RubyEventStore
|
|
8
8
|
self.primary_key = :id
|
9
9
|
self.table_name = 'event_store_outbox'
|
10
10
|
|
11
|
+
def self.remaining_for(fetch_specification)
|
12
|
+
where(format: fetch_specification.message_format, split_key: fetch_specification.split_key, enqueued_at: nil)
|
13
|
+
end
|
14
|
+
|
11
15
|
def hash_payload
|
12
16
|
JSON.parse(payload).deep_symbolize_keys
|
13
17
|
end
|
18
|
+
|
19
|
+
def enqueued?
|
20
|
+
!enqueued_at.nil?
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class Lock < ::ActiveRecord::Base
|
25
|
+
self.primary_key = :split_key
|
26
|
+
self.table_name = 'event_store_outbox_locks'
|
27
|
+
|
28
|
+
def self.obtain(fetch_specification, process_uuid, clock:)
|
29
|
+
l = nil
|
30
|
+
transaction do
|
31
|
+
l = get_lock_record(fetch_specification)
|
32
|
+
|
33
|
+
return :taken if l.recently_locked?
|
34
|
+
|
35
|
+
l.update!(
|
36
|
+
locked_by: process_uuid,
|
37
|
+
locked_at: clock.now,
|
38
|
+
)
|
39
|
+
end
|
40
|
+
l
|
41
|
+
rescue ActiveRecord::Deadlocked
|
42
|
+
:deadlocked
|
43
|
+
rescue ActiveRecord::LockWaitTimeout
|
44
|
+
:lock_timeout
|
45
|
+
end
|
46
|
+
|
47
|
+
def refresh(clock:)
|
48
|
+
transaction do
|
49
|
+
current_process_uuid = locked_by
|
50
|
+
lock!
|
51
|
+
if locked_by == current_process_uuid
|
52
|
+
update!(locked_at: clock.now)
|
53
|
+
return self
|
54
|
+
else
|
55
|
+
return :stolen
|
56
|
+
end
|
57
|
+
end
|
58
|
+
rescue ActiveRecord::Deadlocked
|
59
|
+
:deadlocked
|
60
|
+
rescue ActiveRecord::LockWaitTimeout
|
61
|
+
:lock_timeout
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.release(fetch_specification, process_uuid)
|
65
|
+
transaction do
|
66
|
+
l = get_lock_record(fetch_specification)
|
67
|
+
return :not_taken_by_this_process if !l.locked_by?(process_uuid)
|
68
|
+
|
69
|
+
l.update!(locked_by: nil, locked_at: nil)
|
70
|
+
end
|
71
|
+
:ok
|
72
|
+
rescue ActiveRecord::Deadlocked
|
73
|
+
:deadlocked
|
74
|
+
rescue ActiveRecord::LockWaitTimeout
|
75
|
+
:lock_timeout
|
76
|
+
end
|
77
|
+
|
78
|
+
def locked_by?(process_uuid)
|
79
|
+
locked_by.eql?(process_uuid)
|
80
|
+
end
|
81
|
+
|
82
|
+
def recently_locked?
|
83
|
+
locked_by && locked_at > 10.minutes.ago
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
def self.lock_for_split_key(fetch_specification)
|
88
|
+
lock.find_by(format: fetch_specification.message_format, split_key: fetch_specification.split_key)
|
89
|
+
end
|
90
|
+
|
91
|
+
def self.get_lock_record(fetch_specification)
|
92
|
+
l = lock_for_split_key(fetch_specification)
|
93
|
+
if l.nil?
|
94
|
+
begin
|
95
|
+
l = create!(format: fetch_specification.message_format, split_key: fetch_specification.split_key)
|
96
|
+
rescue ActiveRecord::RecordNotUnique
|
97
|
+
l = lock_for_split_key(fetch_specification)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
l
|
101
|
+
end
|
14
102
|
end
|
15
103
|
end
|
16
104
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "ruby_event_store/outbox/sidekiq5_format"
|
4
|
+
|
5
|
+
module RubyEventStore
|
6
|
+
module Outbox
|
7
|
+
class SidekiqProcessor
|
8
|
+
InvalidPayload = Class.new(StandardError)
|
9
|
+
|
10
|
+
def initialize(redis)
|
11
|
+
@redis = redis
|
12
|
+
@recently_used_queues = Set.new
|
13
|
+
end
|
14
|
+
|
15
|
+
def process(record, now)
|
16
|
+
parsed_record = JSON.parse(record.payload)
|
17
|
+
|
18
|
+
queue = parsed_record["queue"]
|
19
|
+
raise InvalidPayload.new("Missing queue") if queue.nil? || queue.empty?
|
20
|
+
payload = JSON.generate(parsed_record.merge({
|
21
|
+
"enqueued_at" => now.to_f,
|
22
|
+
}))
|
23
|
+
|
24
|
+
redis.lpush("queue:#{queue}", payload)
|
25
|
+
|
26
|
+
@recently_used_queues << queue
|
27
|
+
end
|
28
|
+
|
29
|
+
def after_batch
|
30
|
+
if !@recently_used_queues.empty?
|
31
|
+
redis.sadd("queues", @recently_used_queues.to_a)
|
32
|
+
@recently_used_queues.clear
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def message_format
|
37
|
+
SIDEKIQ5_FORMAT
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
attr_reader :redis
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'sidekiq'
|
4
|
+
require "ruby_event_store/outbox/sidekiq5_format"
|
5
|
+
|
6
|
+
module RubyEventStore
|
7
|
+
module Outbox
|
8
|
+
class SidekiqProducer
|
9
|
+
def call(klass, args)
|
10
|
+
sidekiq_client = Sidekiq::Client.new(Sidekiq.redis_pool)
|
11
|
+
item = {
|
12
|
+
'class' => klass,
|
13
|
+
'args' => args,
|
14
|
+
}
|
15
|
+
normalized_item = sidekiq_client.__send__(:normalize_item, item)
|
16
|
+
payload = sidekiq_client.__send__(:process_single, normalized_item.fetch('class'), normalized_item)
|
17
|
+
if payload
|
18
|
+
Record.create!(
|
19
|
+
format: SIDEKIQ5_FORMAT,
|
20
|
+
split_key: payload.fetch('queue'),
|
21
|
+
payload: payload.to_json
|
22
|
+
)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -1,31 +1,24 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require "ruby_event_store/outbox/sidekiq5_format"
|
3
|
+
require "ruby_event_store/outbox/sidekiq_producer"
|
5
4
|
|
6
5
|
module RubyEventStore
|
7
6
|
module Outbox
|
8
7
|
class SidekiqScheduler
|
8
|
+
def initialize
|
9
|
+
@sidekiq_producer = SidekiqProducer.new
|
10
|
+
end
|
11
|
+
|
9
12
|
def call(klass, serialized_event)
|
10
|
-
|
11
|
-
item = {
|
12
|
-
'class' => klass,
|
13
|
-
'args' => [serialized_event.to_h],
|
14
|
-
}
|
15
|
-
normalized_item = sidekiq_client.__send__(:normalize_item, item)
|
16
|
-
payload = sidekiq_client.__send__(:process_single, normalized_item.fetch('class'), normalized_item)
|
17
|
-
if payload
|
18
|
-
Record.create!(
|
19
|
-
format: SIDEKIQ5_FORMAT,
|
20
|
-
split_key: payload.fetch('queue'),
|
21
|
-
payload: payload.to_json
|
22
|
-
)
|
23
|
-
end
|
13
|
+
sidekiq_producer.call(klass, [serialized_event.to_h])
|
24
14
|
end
|
25
15
|
|
26
16
|
def verify(subscriber)
|
27
17
|
Class === subscriber && subscriber.respond_to?(:through_outbox?) && subscriber.through_outbox?
|
28
18
|
end
|
19
|
+
|
20
|
+
private
|
21
|
+
attr_reader :sidekiq_producer
|
29
22
|
end
|
30
23
|
end
|
31
24
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby_event_store-outbox
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.12
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Arkency
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-08-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ruby_event_store
|
@@ -53,12 +53,16 @@ files:
|
|
53
53
|
- lib/ruby_event_store/outbox.rb
|
54
54
|
- lib/ruby_event_store/outbox/cli.rb
|
55
55
|
- lib/ruby_event_store/outbox/consumer.rb
|
56
|
+
- lib/ruby_event_store/outbox/consumer_process.rb
|
57
|
+
- lib/ruby_event_store/outbox/fetch_specification.rb
|
56
58
|
- lib/ruby_event_store/outbox/metrics.rb
|
57
59
|
- lib/ruby_event_store/outbox/metrics/influx.rb
|
58
60
|
- lib/ruby_event_store/outbox/metrics/null.rb
|
59
61
|
- lib/ruby_event_store/outbox/record.rb
|
60
62
|
- lib/ruby_event_store/outbox/sidekiq5_format.rb
|
61
63
|
- lib/ruby_event_store/outbox/sidekiq_message_handler.rb
|
64
|
+
- lib/ruby_event_store/outbox/sidekiq_processor.rb
|
65
|
+
- lib/ruby_event_store/outbox/sidekiq_producer.rb
|
62
66
|
- lib/ruby_event_store/outbox/sidekiq_scheduler.rb
|
63
67
|
- lib/ruby_event_store/outbox/version.rb
|
64
68
|
homepage: https://railseventstore.org
|