pg_eventstore 1.12.0 → 1.13.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/CHANGELOG.md +9 -0
- data/lib/pg_eventstore/cli/commands/base_command.rb +2 -0
- data/lib/pg_eventstore/cli/commands/callback_handlers/start_cmd_handlers.rb +1 -0
- data/lib/pg_eventstore/cli/commands/help_command.rb +1 -0
- data/lib/pg_eventstore/cli/commands/start_subscriptions_command.rb +3 -1
- data/lib/pg_eventstore/cli/commands/stop_subscriptions_command.rb +1 -0
- data/lib/pg_eventstore/cli/exit_codes.rb +1 -0
- data/lib/pg_eventstore/cli/parser_options/base_options.rb +1 -0
- data/lib/pg_eventstore/cli/parser_options/default_options.rb +1 -0
- data/lib/pg_eventstore/cli/parser_options/metadata.rb +1 -0
- data/lib/pg_eventstore/cli/parser_options/subscription_options.rb +1 -0
- data/lib/pg_eventstore/cli/try_to_delete_subscriptions_set.rb +2 -1
- data/lib/pg_eventstore/cli/try_unlock_subscriptions_set.rb +1 -0
- data/lib/pg_eventstore/cli/wait_for_subscriptions_set_shutdown.rb +1 -0
- data/lib/pg_eventstore/connection.rb +8 -3
- data/lib/pg_eventstore/extensions/callback_handlers_extension.rb +1 -0
- data/lib/pg_eventstore/pg_connection.rb +1 -0
- data/lib/pg_eventstore/query_builders/events_filtering.rb +1 -1
- data/lib/pg_eventstore/query_builders/partitions_filtering.rb +1 -1
- data/lib/pg_eventstore/subscriptions/basic_runner.rb +122 -35
- data/lib/pg_eventstore/subscriptions/callback_handlers/commands_handler_handlers.rb +1 -14
- data/lib/pg_eventstore/subscriptions/callback_handlers/events_processor_handlers.rb +4 -3
- data/lib/pg_eventstore/subscriptions/callback_handlers/subscription_feeder_handlers.rb +1 -14
- data/lib/pg_eventstore/subscriptions/callback_handlers/subscription_runner_handlers.rb +1 -19
- data/lib/pg_eventstore/subscriptions/command_handlers/subscription_feeder_commands.rb +1 -0
- data/lib/pg_eventstore/subscriptions/command_handlers/subscription_runners_commands.rb +1 -0
- data/lib/pg_eventstore/subscriptions/commands_handler.rb +5 -8
- data/lib/pg_eventstore/subscriptions/events_processor.rb +7 -2
- data/lib/pg_eventstore/subscriptions/extensions/base_command_extension.rb +1 -0
- data/lib/pg_eventstore/subscriptions/extensions/command_class_lookup_extension.rb +1 -0
- data/lib/pg_eventstore/subscriptions/runner_recovery_strategies/restore_connection.rb +44 -0
- data/lib/pg_eventstore/subscriptions/runner_recovery_strategies/restore_subscription_feeder.rb +27 -0
- data/lib/pg_eventstore/subscriptions/runner_recovery_strategies/restore_subscription_runner.rb +34 -0
- data/lib/pg_eventstore/subscriptions/runner_recovery_strategies.rb +5 -0
- data/lib/pg_eventstore/subscriptions/runner_recovery_strategy.rb +21 -0
- data/lib/pg_eventstore/subscriptions/subscription_feeder.rb +18 -5
- data/lib/pg_eventstore/subscriptions/subscription_runner.rb +1 -13
- data/lib/pg_eventstore/subscriptions/subscriptions_lifecycle.rb +1 -0
- data/lib/pg_eventstore/subscriptions/subscriptions_manager.rb +20 -3
- data/lib/pg_eventstore/subscriptions/subscriptions_set_lifecycle.rb +1 -0
- data/lib/pg_eventstore/version.rb +1 -1
- data/lib/pg_eventstore/web/application.rb +1 -0
- data/lib/pg_eventstore.rb +2 -1
- data/sig/pg_eventstore/connection.rbs +2 -0
- data/sig/pg_eventstore/subscriptions/basic_runner.rbs +26 -10
- data/sig/pg_eventstore/subscriptions/callback_handlers/commands_handler_handlers.rbs +5 -5
- data/sig/pg_eventstore/subscriptions/callback_handlers/subscription_feeder_handlers.rbs +1 -3
- data/sig/pg_eventstore/subscriptions/callback_handlers/subscription_runner_handlers.rbs +0 -4
- data/sig/pg_eventstore/subscriptions/commands_handler.rbs +8 -11
- data/sig/pg_eventstore/subscriptions/events_processor.rbs +5 -17
- data/sig/pg_eventstore/subscriptions/runner_recovery_strategies/restore_connection.rbs +18 -0
- data/sig/pg_eventstore/subscriptions/runner_recovery_strategies/restore_subscription_feeder.rbs +11 -0
- data/sig/pg_eventstore/subscriptions/runner_recovery_strategies/restore_subscription_runner.rbs +17 -0
- data/sig/pg_eventstore/subscriptions/runner_recovery_strategy.rbs +7 -0
- data/sig/pg_eventstore/subscriptions/subscription_feeder.rbs +6 -8
- data/sig/pg_eventstore/subscriptions/subscription_runner.rbs +6 -35
- data/sig/pg_eventstore/subscriptions/subscriptions_manager.rbs +8 -0
- metadata +11 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b8ddfb0310abc9f9b78b20c0f8c6466ad2ae585ce66fd7ecae7a94bd6fe179a6
|
4
|
+
data.tar.gz: 2e06fa6f70db70b61f867d33a02eb8c13b50937f6c5afc7cf29f670f8759a9af
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f31f6c07073da1a1f460cf65ec55056e1bc7ab28c72f69361cf2c77219ea529324eba85aebbd94cffecbcf3d0354c73b43ca9c3441a7dae39fbc91df8bce792f
|
7
|
+
data.tar.gz: 8b60ce11b14e5832d53f732690043c55662d5007a919d7a734199a55b4f07be7f1faa1ee13163dda12cac4e7772d6f7a12d57966a07ea021dd00b6cfee80a549
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [1.13.1]
|
4
|
+
|
5
|
+
- Do not modify public methods arguments
|
6
|
+
|
7
|
+
## [1.13.0]
|
8
|
+
|
9
|
+
- Introduce automatic subscriptions recovery from connection errors. This way if a subscription process loses the connection to the database - it will be trying to reconnect until the connection is restored.
|
10
|
+
- Resolve ambiguity in usage of `PgEventstore.config` method. It now returns the frozen object.
|
11
|
+
|
3
12
|
## [1.12.0]
|
4
13
|
|
5
14
|
- Introduce `#read_grouped` API method that allows to group events by type
|
@@ -5,6 +5,7 @@ require_relative 'callback_handlers/start_cmd_handlers'
|
|
5
5
|
module PgEventstore
|
6
6
|
module CLI
|
7
7
|
module Commands
|
8
|
+
# @!visibility private
|
8
9
|
class StartSubscriptionsCommand < BaseCommand
|
9
10
|
# @return [Integer] seconds
|
10
11
|
KEEP_ALIVE_INTERVAL = 2
|
@@ -55,8 +56,9 @@ module PgEventstore
|
|
55
56
|
manager.stop
|
56
57
|
end
|
57
58
|
end.each(&:join)
|
58
|
-
|
59
|
+
ensure
|
59
60
|
@running = false
|
61
|
+
Utils.remove_file(options.pid_path)
|
60
62
|
end
|
61
63
|
end
|
62
64
|
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
module PgEventstore
|
4
4
|
module CLI
|
5
|
+
# @!visibility private
|
5
6
|
class TryToDeleteSubscriptionsSet
|
6
7
|
class << self
|
7
8
|
def try_to_delete(...)
|
@@ -30,7 +31,7 @@ module PgEventstore
|
|
30
31
|
# Potentially CommandsHandler can be dead exactly at the same moment we expect it to process "Ping" command.
|
31
32
|
# Wait for potential recover plus run interval and plus another second to allow potential processing of
|
32
33
|
# "Ping" command. "Ping" command comes in prio, so it is guaranteed it will be processed as a first command.
|
33
|
-
sleep
|
34
|
+
sleep RunnerRecoveryStrategies::RestoreConnection::TIME_BETWEEN_RETRIES + CommandsHandler::PULL_INTERVAL + 1
|
34
35
|
if subscriptions_set_commands_queries.find_by(subscriptions_set_id: subscriptions_set_id, command_name: cmd_name)
|
35
36
|
# "Ping" command wasn't consumed. Related process must be dead.
|
36
37
|
subscriptions_set_queries.delete(subscriptions_set_id)
|
@@ -67,9 +67,9 @@ module PgEventstore
|
|
67
67
|
should_retry = true
|
68
68
|
@pool.with do |conn|
|
69
69
|
yield conn
|
70
|
-
rescue PG::ConnectionBad
|
71
|
-
# Recover connection after fork. We
|
72
|
-
#
|
70
|
+
rescue PG::ConnectionBad, PG::UnableToSend
|
71
|
+
# Recover a connection after fork or when we lost a connection to PostgreSQL. We retry only once and without any
|
72
|
+
# delay.
|
73
73
|
conn.sync_reset
|
74
74
|
raise unless should_retry
|
75
75
|
should_retry = false
|
@@ -77,6 +77,11 @@ module PgEventstore
|
|
77
77
|
end
|
78
78
|
end
|
79
79
|
|
80
|
+
# @return [void]
|
81
|
+
def shutdown
|
82
|
+
@pool.shutdown(&:close)
|
83
|
+
end
|
84
|
+
|
80
85
|
private
|
81
86
|
|
82
87
|
# @return [ConnectionPool]
|
@@ -82,7 +82,7 @@ module PgEventstore
|
|
82
82
|
# @return [Array<String>]
|
83
83
|
def extract_event_types_filter(options)
|
84
84
|
options in { filter: { event_types: Array => event_types } }
|
85
|
-
event_types&.select
|
85
|
+
event_types = event_types&.select do
|
86
86
|
_1.is_a?(String)
|
87
87
|
end
|
88
88
|
event_types || []
|
@@ -13,7 +13,7 @@ module PgEventstore
|
|
13
13
|
# @return [Array<String>]
|
14
14
|
def extract_event_types_filter(options)
|
15
15
|
options in { filter: { event_types: Array => event_types } }
|
16
|
-
event_types&.select
|
16
|
+
event_types = event_types&.select do
|
17
17
|
_1.is_a?(String)
|
18
18
|
end
|
19
19
|
event_types || []
|
@@ -1,9 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module PgEventstore
|
4
|
-
# Implements simple background
|
5
|
-
#
|
6
|
-
#
|
4
|
+
# Implements simple background job runner. A job execution is done via declaring a callback on a specific action. The
|
5
|
+
# implementation also allows you to hook into different places of life cycle of the runner by defining callbacks on
|
6
|
+
# various actions. Here is the list of available actions:
|
7
7
|
# - :before_runner_started. Happens before the runner's state switches from "initial"/"stopped" to "running" and
|
8
8
|
# runner's thread is started. It is also fired when the runner is restoring - right after :before_runner_restored
|
9
9
|
# action.
|
@@ -24,12 +24,41 @@ module PgEventstore
|
|
24
24
|
#
|
25
25
|
# def_delegators :@basic_runner, :start, :stop, :wait_for_finish, :stop_async, :restore
|
26
26
|
#
|
27
|
+
# class SimpleRecoveryStrategy
|
28
|
+
# include PgEventstore::RunnerRecoveryStrategy
|
29
|
+
#
|
30
|
+
# def initialize(restore_func)
|
31
|
+
# @attempts_count = 0
|
32
|
+
# @restore_func = restore_func
|
33
|
+
# end
|
34
|
+
#
|
35
|
+
# def recovers?(error)
|
36
|
+
# error.message.include?("I can not handle this any more!")
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
# def recover(error)
|
40
|
+
# (@attempts_count < 3).tap do |res|
|
41
|
+
# @attempts_count += 1
|
42
|
+
# @restore_func.call if res
|
43
|
+
# end
|
44
|
+
# end
|
45
|
+
# end
|
46
|
+
#
|
27
47
|
# def initialize
|
28
|
-
# @basic_runner = PgEventstore::BasicRunner.new(
|
48
|
+
# @basic_runner = PgEventstore::BasicRunner.new(
|
49
|
+
# run_interval: 1, async_shutdown_time: 2, recovery_strategies: recovery_strategies
|
50
|
+
# )
|
29
51
|
# @jobs_performed = 0
|
52
|
+
# @jobs_limit = 3
|
30
53
|
# attach_runner_callbacks
|
31
54
|
# end
|
32
55
|
#
|
56
|
+
# protected
|
57
|
+
#
|
58
|
+
# def work_harder
|
59
|
+
# @jobs_limit += 3
|
60
|
+
# end
|
61
|
+
#
|
33
62
|
# private
|
34
63
|
#
|
35
64
|
# def attach_runner_callbacks
|
@@ -42,7 +71,7 @@ module PgEventstore
|
|
42
71
|
# end
|
43
72
|
#
|
44
73
|
# def process_action
|
45
|
-
# raise "What's the point? I can not handle this any more!" if @jobs_performed >=
|
74
|
+
# raise "What's the point? I can not handle this any more!" if @jobs_performed >= @jobs_limit
|
46
75
|
# puts "Doing some heavy lifting job"
|
47
76
|
# sleep 2 # Simulate long running job
|
48
77
|
# end
|
@@ -67,6 +96,10 @@ module PgEventstore
|
|
67
96
|
# def after_runner_died(error)
|
68
97
|
# puts "Error occurred: #{error.inspect}"
|
69
98
|
# end
|
99
|
+
#
|
100
|
+
# def recovery_strategies
|
101
|
+
# [SimpleRecoveryStrategy.new(method(:work_harder))]
|
102
|
+
# end
|
70
103
|
# end
|
71
104
|
#
|
72
105
|
# runner = MyAwesomeRunner.new
|
@@ -85,11 +118,13 @@ module PgEventstore
|
|
85
118
|
# :after_runner_stopped callback
|
86
119
|
# @param async_shutdown_time [Integer, Float] seconds. Determines how long to wait before force-shutdown the runner.
|
87
120
|
# It is only meaningful for the #stop_async
|
88
|
-
def initialize(run_interval
|
121
|
+
def initialize(run_interval:, async_shutdown_time:, recovery_strategies: [])
|
89
122
|
@run_interval = run_interval
|
90
123
|
@async_shutdown_time = async_shutdown_time
|
124
|
+
@recovery_strategies = recovery_strategies
|
91
125
|
@state = RunnerState.new
|
92
126
|
@mutex = Thread::Mutex.new
|
127
|
+
@runner = nil
|
93
128
|
delegate_change_state_cbx
|
94
129
|
end
|
95
130
|
|
@@ -127,36 +162,40 @@ module PgEventstore
|
|
127
162
|
synchronize do
|
128
163
|
return self unless @state.running? || @state.dead?
|
129
164
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
165
|
+
begin
|
166
|
+
@state.halting!
|
167
|
+
ensure
|
168
|
+
Thread.new do
|
169
|
+
stopping_at = Time.now.utc
|
170
|
+
halt = false
|
171
|
+
loop do
|
172
|
+
synchronize do
|
173
|
+
# Give the runner up to @async_shutdown_time seconds for graceful shutdown
|
174
|
+
@runner&.exit if Time.now.utc - stopping_at > @async_shutdown_time
|
175
|
+
|
176
|
+
unless @runner&.alive?
|
177
|
+
@state.stopped!
|
178
|
+
callbacks.run_callbacks(:after_runner_stopped)
|
179
|
+
end
|
180
|
+
ensure
|
181
|
+
next if @runner&.alive?
|
138
182
|
|
139
|
-
unless @runner&.alive?
|
140
|
-
@state.stopped!
|
141
183
|
@runner = nil
|
142
|
-
callbacks.run_callbacks(:after_runner_stopped)
|
143
184
|
halt = true
|
144
185
|
end
|
186
|
+
break if halt
|
187
|
+
sleep 0.1
|
145
188
|
end
|
146
|
-
break if halt
|
147
|
-
sleep 0.1
|
148
189
|
end
|
149
190
|
end
|
150
|
-
self
|
151
191
|
end
|
192
|
+
self
|
152
193
|
end
|
153
194
|
|
154
195
|
# Restores the runner after its death.
|
155
196
|
# @return [self]
|
156
197
|
def restore
|
157
|
-
|
158
|
-
return self unless @state.dead?
|
159
|
-
|
198
|
+
within_state(:dead) do
|
160
199
|
callbacks.run_callbacks(:before_runner_restored)
|
161
200
|
_start
|
162
201
|
end
|
@@ -183,7 +222,7 @@ module PgEventstore
|
|
183
222
|
end
|
184
223
|
|
185
224
|
# @param state [Symbol]
|
186
|
-
# @return [Object] a result of evaluating of passed block
|
225
|
+
# @return [Object, nil] a result of evaluating of passed block
|
187
226
|
def within_state(state, &blk)
|
188
227
|
synchronize do
|
189
228
|
return unless @state.public_send("#{RunnerState::STATES.fetch(state)}?")
|
@@ -192,6 +231,20 @@ module PgEventstore
|
|
192
231
|
end
|
193
232
|
end
|
194
233
|
|
234
|
+
protected
|
235
|
+
|
236
|
+
# @param error [StandardError]
|
237
|
+
# @param strategy [PgEventstore::RunnerRecoveryStrategy]
|
238
|
+
# @param current_runner_id [Integer]
|
239
|
+
# @return [Thread]
|
240
|
+
def async_recover(error, strategy, current_runner_id)
|
241
|
+
Thread.new do
|
242
|
+
init_recovery_ripper(current_runner_id)
|
243
|
+
Thread.current.exit unless strategy.recover(error)
|
244
|
+
recoverable { restore }
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
195
248
|
private
|
196
249
|
|
197
250
|
def synchronize
|
@@ -201,19 +254,15 @@ module PgEventstore
|
|
201
254
|
# @return [void]
|
202
255
|
def _start
|
203
256
|
@state.running!
|
257
|
+
ensure
|
204
258
|
@runner = Thread.new do
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
callbacks.run_callbacks(:process_async)
|
210
|
-
end
|
211
|
-
rescue => error
|
212
|
-
synchronize do
|
213
|
-
raise unless @state.halting? || @state.running?
|
259
|
+
recoverable do
|
260
|
+
loop do
|
261
|
+
Thread.current.exit unless @state.running?
|
262
|
+
sleep @run_interval
|
214
263
|
|
215
|
-
|
216
|
-
|
264
|
+
callbacks.run_callbacks(:process_async)
|
265
|
+
end
|
217
266
|
end
|
218
267
|
end
|
219
268
|
end
|
@@ -228,5 +277,43 @@ module PgEventstore
|
|
228
277
|
def change_state(...)
|
229
278
|
callbacks.run_callbacks(:change_state, ...)
|
230
279
|
end
|
280
|
+
|
281
|
+
# @param error [StandardError]
|
282
|
+
# @return [PgEventstore::RunnerRecoveryStrategy, nil]
|
283
|
+
def suitable_strategy(error)
|
284
|
+
@recovery_strategies.find { _1.recovers?(error) }
|
285
|
+
end
|
286
|
+
|
287
|
+
# @return [void]
|
288
|
+
def recoverable
|
289
|
+
yield
|
290
|
+
rescue => error
|
291
|
+
synchronize do
|
292
|
+
raise unless @state.halting? || @state.running?
|
293
|
+
|
294
|
+
recovery_strategy = suitable_strategy(error)
|
295
|
+
@state.dead!
|
296
|
+
callbacks.run_callbacks(:after_runner_died, error)
|
297
|
+
ensure
|
298
|
+
async_recover(error, recovery_strategy, @runner.__id__) if recovery_strategy
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
# @param current_runner_id [Integer]
|
303
|
+
# @return [Thread]
|
304
|
+
def init_recovery_ripper(current_runner_id)
|
305
|
+
recovery_job = Thread.current
|
306
|
+
Thread.new do
|
307
|
+
loop do
|
308
|
+
synchronize do
|
309
|
+
recovery_job.exit unless @state.dead?
|
310
|
+
recovery_job.exit unless current_runner_id == @runner.__id__
|
311
|
+
end
|
312
|
+
break unless recovery_job.alive?
|
313
|
+
|
314
|
+
sleep 1
|
315
|
+
end
|
316
|
+
end
|
317
|
+
end
|
231
318
|
end
|
232
319
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module PgEventstore
|
4
|
+
# @!visibility private
|
4
5
|
class CommandsHandlerHandlers
|
5
6
|
include Extensions::CallbackHandlersExtension
|
6
7
|
|
@@ -19,20 +20,6 @@ module PgEventstore
|
|
19
20
|
def process_runners_commands(config_name, runners, subscription_feeder)
|
20
21
|
CommandHandlers::SubscriptionRunnersCommands.new(config_name, runners, subscription_feeder.id).process
|
21
22
|
end
|
22
|
-
|
23
|
-
# @param basic_runner [PgEventstore::BasicRunner]
|
24
|
-
# @param restart_delay [Integer]
|
25
|
-
# @param error [StandardError]
|
26
|
-
# @return [void]
|
27
|
-
def restore_runner(basic_runner, restart_delay, error)
|
28
|
-
PgEventstore.logger&.error "PgEventstore::CommandsHandler: Error occurred: #{error.message}"
|
29
|
-
PgEventstore.logger&.error "PgEventstore::CommandsHandler: Backtrace: #{error.backtrace&.join("\n")}"
|
30
|
-
PgEventstore.logger&.error "PgEventstore::CommandsHandler: Trying to auto-repair in #{restart_delay} seconds..."
|
31
|
-
Thread.new do
|
32
|
-
sleep restart_delay
|
33
|
-
basic_runner.restore
|
34
|
-
end
|
35
|
-
end
|
36
23
|
end
|
37
24
|
end
|
38
25
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module PgEventstore
|
4
|
+
# @!visibility private
|
4
5
|
class EventsProcessorHandlers
|
5
6
|
include Extensions::CallbackHandlersExtension
|
6
7
|
|
@@ -15,10 +16,10 @@ module PgEventstore
|
|
15
16
|
|
16
17
|
callbacks.run_callbacks(:process, Utils.original_global_position(raw_event)) do
|
17
18
|
handler.call(raw_event)
|
19
|
+
rescue => exception
|
20
|
+
raw_events.unshift(raw_event)
|
21
|
+
raise Utils.wrap_exception(exception, global_position: Utils.original_global_position(raw_event))
|
18
22
|
end
|
19
|
-
rescue => exception
|
20
|
-
raw_events.unshift(raw_event)
|
21
|
-
raise Utils.wrap_exception(exception, global_position: Utils.original_global_position(raw_event))
|
22
23
|
end
|
23
24
|
|
24
25
|
# @param callbacks [PgEventstore::Callbacks]
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module PgEventstore
|
4
|
+
# @!visibility private
|
4
5
|
class SubscriptionFeederHandlers
|
5
6
|
include Extensions::CallbackHandlersExtension
|
6
7
|
|
@@ -39,20 +40,6 @@ module PgEventstore
|
|
39
40
|
)
|
40
41
|
end
|
41
42
|
|
42
|
-
# @param subscriptions_set_lifecycle [PgEventstore::SubscriptionsSetLifecycle]
|
43
|
-
# @param basic_runner [PgEventstore::BasicRunner]
|
44
|
-
# @param _error [StandardError]
|
45
|
-
# @return [void]
|
46
|
-
def restart_runner(subscriptions_set_lifecycle, basic_runner, _error)
|
47
|
-
subscriptions_set = subscriptions_set_lifecycle.persisted_subscriptions_set
|
48
|
-
return if subscriptions_set.restart_count >= subscriptions_set.max_restarts_number
|
49
|
-
|
50
|
-
Thread.new do
|
51
|
-
sleep subscriptions_set.time_between_restarts
|
52
|
-
basic_runner.restore
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
43
|
# @param subscriptions_set_lifecycle [PgEventstore::SubscriptionsSetLifecycle]
|
57
44
|
# @return [void]
|
58
45
|
def ping_subscriptions_set(subscriptions_set_lifecycle)
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module PgEventstore
|
4
|
+
# @!visibility private
|
4
5
|
class SubscriptionRunnerHandlers
|
5
6
|
include Extensions::CallbackHandlersExtension
|
6
7
|
|
@@ -32,25 +33,6 @@ module PgEventstore
|
|
32
33
|
subscription.update(last_error: Utils.error_info(error), last_error_occurred_at: Time.now.utc)
|
33
34
|
end
|
34
35
|
|
35
|
-
# @param subscription [PgEventstore::Subscription]
|
36
|
-
# @param restart_terminator [#call, nil]
|
37
|
-
# @param failed_subscription_notifier [#call, nil]
|
38
|
-
# @param events_processor [PgEventstore::EventsProcessor]
|
39
|
-
# @param error [PgEventstore::WrappedException]
|
40
|
-
# @return [void]
|
41
|
-
def restart_events_processor(subscription, restart_terminator, failed_subscription_notifier, events_processor,
|
42
|
-
error)
|
43
|
-
return if restart_terminator&.call(subscription.dup)
|
44
|
-
if subscription.restart_count >= subscription.max_restarts_number
|
45
|
-
return failed_subscription_notifier&.call(subscription.dup, Utils.unwrap_exception(error))
|
46
|
-
end
|
47
|
-
|
48
|
-
Thread.new do
|
49
|
-
sleep subscription.time_between_restarts
|
50
|
-
events_processor.restore
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
36
|
# @param subscription [PgEventstore::Subscription]
|
55
37
|
# @param global_position [Integer]
|
56
38
|
# @return [void]
|
@@ -10,8 +10,6 @@ module PgEventstore
|
|
10
10
|
class CommandsHandler
|
11
11
|
extend Forwardable
|
12
12
|
|
13
|
-
# @return [Integer] the delay in seconds between runner restarts
|
14
|
-
RESTART_DELAY = 5
|
15
13
|
# @return [Integer] seconds, how often to check for new commands
|
16
14
|
PULL_INTERVAL = 1
|
17
15
|
|
@@ -24,7 +22,11 @@ module PgEventstore
|
|
24
22
|
@config_name = config_name
|
25
23
|
@subscription_feeder = subscription_feeder
|
26
24
|
@runners = runners
|
27
|
-
@basic_runner = BasicRunner.new(
|
25
|
+
@basic_runner = BasicRunner.new(
|
26
|
+
run_interval: PULL_INTERVAL,
|
27
|
+
async_shutdown_time: 0,
|
28
|
+
recovery_strategies: [RunnerRecoveryStrategies::RestoreConnection.new(config_name)]
|
29
|
+
)
|
28
30
|
attach_runner_callbacks
|
29
31
|
end
|
30
32
|
|
@@ -39,11 +41,6 @@ module PgEventstore
|
|
39
41
|
:process_async, :before,
|
40
42
|
CommandsHandlerHandlers.setup_handler(:process_runners_commands, @config_name, @runners, @subscription_feeder)
|
41
43
|
)
|
42
|
-
|
43
|
-
@basic_runner.define_callback(
|
44
|
-
:after_runner_died, :before,
|
45
|
-
CommandsHandlerHandlers.setup_handler(:restore_runner, @basic_runner, RESTART_DELAY)
|
46
|
-
)
|
47
44
|
end
|
48
45
|
end
|
49
46
|
end
|
@@ -13,10 +13,15 @@ module PgEventstore
|
|
13
13
|
# @param handler [#call]
|
14
14
|
# @param graceful_shutdown_timeout [Integer, Float] seconds. Determines how long to wait before force-shutdown
|
15
15
|
# the runner when stopping it using #stop_async
|
16
|
-
|
16
|
+
# @param recovery_strategies [Array<PgEventstore::RunnerRecoveryStrategy>]
|
17
|
+
def initialize(handler, graceful_shutdown_timeout:, recovery_strategies: [])
|
17
18
|
@handler = handler
|
18
19
|
@raw_events = []
|
19
|
-
@basic_runner = BasicRunner.new(
|
20
|
+
@basic_runner = BasicRunner.new(
|
21
|
+
run_interval: 0,
|
22
|
+
async_shutdown_time: graceful_shutdown_timeout,
|
23
|
+
recovery_strategies: recovery_strategies
|
24
|
+
)
|
20
25
|
attach_runner_callbacks
|
21
26
|
end
|
22
27
|
|