pg_eventstore 1.3.4 → 1.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +21 -0
- data/docs/configuration.md +16 -15
- data/docs/subscriptions.md +4 -2
- data/lib/pg_eventstore/config.rb +3 -0
- data/lib/pg_eventstore/extensions/callback_handlers_extension.rb +21 -0
- data/lib/pg_eventstore/subscriptions/basic_runner.rb +2 -2
- data/lib/pg_eventstore/subscriptions/callback_handlers/commands_handler_handlers.rb +38 -0
- data/lib/pg_eventstore/subscriptions/callback_handlers/events_processor_handlers.rb +45 -0
- data/lib/pg_eventstore/subscriptions/callback_handlers/subscription_feeder_handlers.rb +103 -0
- data/lib/pg_eventstore/subscriptions/callback_handlers/subscription_runner_handlers.rb +75 -0
- data/lib/pg_eventstore/subscriptions/commands_handler.rb +13 -29
- data/lib/pg_eventstore/subscriptions/events_processor.rb +21 -43
- data/lib/pg_eventstore/subscriptions/subscription_feeder.rb +77 -125
- data/lib/pg_eventstore/subscriptions/subscription_runner.rb +30 -55
- data/lib/pg_eventstore/subscriptions/subscriptions_lifecycle.rb +70 -0
- data/lib/pg_eventstore/subscriptions/subscriptions_manager.rb +14 -3
- data/lib/pg_eventstore/subscriptions/subscriptions_set_lifecycle.rb +39 -0
- data/lib/pg_eventstore/utils.rb +8 -0
- data/lib/pg_eventstore/version.rb +1 -1
- data/lib/pg_eventstore/web/application.rb +9 -1
- data/lib/pg_eventstore/web/paginator/events_collection.rb +1 -3
- data/lib/pg_eventstore/web/paginator/helpers.rb +4 -1
- data/lib/pg_eventstore/web/public/javascripts/pg_eventstore.js +10 -1
- data/lib/pg_eventstore/web/subscriptions/helpers.rb +3 -4
- data/lib/pg_eventstore/web/views/home/dashboard.erb +11 -0
- data/lib/pg_eventstore/web/views/home/partials/events.erb +6 -1
- data/lib/pg_eventstore/web/views/subscriptions/index.erb +2 -2
- data/lib/pg_eventstore.rb +1 -0
- data/sig/interfaces/_raw_event_handler.rbs +3 -0
- data/sig/pg_eventstore/config.rbs +2 -0
- data/sig/pg_eventstore/extensions/callback_handlers_extension.rbs +11 -0
- data/sig/pg_eventstore/subscriptions/callback_handlers/commands_handler_handlers.rbs +10 -0
- data/sig/pg_eventstore/subscriptions/callback_handlers/events_processor_handlers.rbs +11 -0
- data/sig/pg_eventstore/subscriptions/callback_handlers/subscription_feeder_handlers.rbs +31 -0
- data/sig/pg_eventstore/subscriptions/callback_handlers/subscription_runner_handlers.rbs +19 -0
- data/sig/pg_eventstore/subscriptions/events_processor.rbs +1 -1
- data/sig/pg_eventstore/subscriptions/subscription_feeder.rbs +2 -30
- data/sig/pg_eventstore/subscriptions/subscriptions_lifecycle.rbs +27 -0
- data/sig/pg_eventstore/subscriptions/subscriptions_manager.rbs +3 -2
- data/sig/pg_eventstore/subscriptions/subscriptions_set_lifecycle.rbs +24 -0
- data/sig/pg_eventstore/utils.rbs +2 -0
- data/sig/pg_eventstore/web/subscriptions/helpers.rbs +1 -1
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ec41b398e1f38d66e73967447ea4f12896ed2cf57eb0dbad8b71acf4257f9cd4
|
4
|
+
data.tar.gz: ce571ef411adeeb18b7bae463cac339a053d96f1b36e3de0b1023b8551b03ac5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9273a4efb9855d219b1a92b5d9081e3d0d62f9de7f21c48e634949d218ed6a8278d81367f794ee8b70efa64541d7a4442ccf09e7b4cc3bcbd39398f5c7980ec2
|
7
|
+
data.tar.gz: ffb85f8c9063aa6e11b8f900e128b4b873e89db117b39e703de6603fc73c014811b63950ff0a0340b0316da11ed2562418f56f1faf42a04491fb0105d913fced
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,26 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [1.5.0]
|
4
|
+
- Add ability to toggle link events in the admin UI
|
5
|
+
- Mark linked events in the admin UI with "link" icon
|
6
|
+
|
7
|
+
## [1.4.0]
|
8
|
+
- Add an ability to configure subscription graceful shutdown timeout globally and per subscription. Default value is 15 seconds. Previously it was hardcoded to 5 seconds. Examples:
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
# Set it globally, for all subscriptions
|
12
|
+
PgEventstore.configure do |config|
|
13
|
+
config.subscription_graceful_shutdown_timeout = 5
|
14
|
+
end
|
15
|
+
|
16
|
+
# Set it per subscription
|
17
|
+
subscriptions_manager.subscribe(
|
18
|
+
'MySubscriptionWithHeavyLiftingTask',
|
19
|
+
handler: proc { |event| puts event },
|
20
|
+
graceful_shutdown_timeout: 20
|
21
|
+
)
|
22
|
+
```
|
23
|
+
|
3
24
|
## [1.3.4]
|
4
25
|
- Fix `NoMethodError` error in `Client#read_paginated` when stream does not exist or when there are no events matching the given filter
|
5
26
|
|
data/docs/configuration.md
CHANGED
@@ -2,21 +2,22 @@
|
|
2
2
|
|
3
3
|
Configuration options:
|
4
4
|
|
5
|
-
| name
|
6
|
-
|
7
|
-
| pg_uri
|
8
|
-
| max_count
|
9
|
-
| middlewares
|
10
|
-
| event_class_resolver
|
11
|
-
| connection_pool_size
|
12
|
-
| connection_pool_timeout
|
13
|
-
| subscription_pull_interval
|
14
|
-
| subscription_max_retries
|
15
|
-
| subscription_retries_interval
|
16
|
-
| subscriptions_set_max_retries
|
17
|
-
| subscriptions_set_retries_interval
|
18
|
-
| subscription_restart_terminator
|
19
|
-
| failed_subscription_notifier
|
5
|
+
| name | value | default value | description |
|
6
|
+
|----------------------------------------|----------------|--------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
7
|
+
| pg_uri | String | `'postgresql://postgres:postgres@localhost:5432/eventstore'` | PostgreSQL connection string. See PostgreSQL [docs](https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING-URIS) for more information. |
|
8
|
+
| max_count | Integer | `1000` | Number of events to return in one response when reading from a stream. |
|
9
|
+
| middlewares | Array | `{}` | A hash where a key is a name of your middleware and value is an object that respond to `#serialize` and `#deserialize` methods. See [**Writing middleware**](writing_middleware.md) chapter. |
|
10
|
+
| event_class_resolver | `#call` | `PgEventstore::EventClassResolver.new` | A `#call`-able object that accepts a string and returns an event's class. See **Resolving events classes** chapter bellow for more info. |
|
11
|
+
| connection_pool_size | Integer | `5` | Max number of connections per ruby process. It must equal the number of threads of your application. When using subscriptions it is recommended to set it to the number of subscriptions divided by two or greater. See [**Picking max connections number**](#picking-max-connections-number) chapter of this section. |
|
12
|
+
| connection_pool_timeout | Integer | `5` | Time in seconds to wait for a connection in the pool to be released. If no connections are available during this time - `ConnectionPool::TimeoutError` will be raised. See `connection_pool` gem [docs](https://github.com/mperham/connection_pool#usage) for more info. |
|
13
|
+
| subscription_pull_interval | Float | `1.0` | How often to pull new subscription events in seconds. The minimum meaningful value is `0.2`. Values less than `0.2` will act as it is `0.2`. |
|
14
|
+
| subscription_max_retries | Integer | `5` | Max number of retries of failed subscription. |
|
15
|
+
| subscription_retries_interval | Integer | `1` | Interval in seconds between retries of failed subscriptions. |
|
16
|
+
| subscriptions_set_max_retries | Integer | `10` | Max number of retries for failed subscription sets. |
|
17
|
+
| subscriptions_set_retries_interval | Integer | `1` | Interval in seconds between retries of failed subscription sets. |
|
18
|
+
| subscription_restart_terminator | `#call` | `nil` | A callable object that accepts `PgEventstore::Subscription` object to determine whether restarts should be stopped(true - stops restarts, false - continues restarts). |
|
19
|
+
| failed_subscription_notifier | `#call` | `nil` | A callable object which is invoked with `PgEventstore::Subscription` instance and error instance after the related subscription died due to error and no longer can be automatically restarted due to max retries number reached. You can use this hook to send a notification about failed subscription. |
|
20
|
+
| subscription_graceful_shutdown_timeout | Integer, Float | `15` | The number of seconds to wait until force-shutdown the subscription during the stop process. If your subscription handler does not finish current event processing during this time(for example because of heavy-lifting task) - it will be force-shutdown. |
|
20
21
|
|
21
22
|
## Multiple configurations
|
22
23
|
|
data/docs/subscriptions.md
CHANGED
@@ -151,7 +151,7 @@ You will then see the output of your subscription handlers. To gracefully stop t
|
|
151
151
|
|
152
152
|
## Overriding Subscription config values
|
153
153
|
|
154
|
-
You can override `subscription_pull_interval`, `subscription_max_retries`, `subscription_retries_interval`, `subscription_restart_terminator` and `
|
154
|
+
You can override `subscription_pull_interval`, `subscription_max_retries`, `subscription_retries_interval`, `subscription_restart_terminator`, `failed_subscription_notifier` and `subscription_graceful_shutdown_timeout` config values (see [**Configuration**](configuration.md) chapter for details) for the specific subscription by providing the corresponding arguments. Example:
|
155
155
|
|
156
156
|
```ruby
|
157
157
|
subscriptions_manager.subscribe(
|
@@ -166,7 +166,9 @@ subscriptions_manager.subscribe(
|
|
166
166
|
# overrides config.subscription_restart_terminator
|
167
167
|
restart_terminator: proc { |subscription| subscription.last_error['class'] == 'NoMethodError' },
|
168
168
|
# overrides config.failed_subscription_notifier
|
169
|
-
failed_subscription_notifier: proc { |_subscription, err| p err }
|
169
|
+
failed_subscription_notifier: proc { |_subscription, err| p err },
|
170
|
+
# overrides config.subscription_graceful_shutdown_timeout
|
171
|
+
graceful_shutdown_timeout: 20
|
170
172
|
)
|
171
173
|
```
|
172
174
|
|
data/lib/pg_eventstore/config.rb
CHANGED
@@ -52,6 +52,9 @@ module PgEventstore
|
|
52
52
|
# @return [#call, nil] provide callable object that accepts Subscription instance and error. It is useful when you
|
53
53
|
# want to be get notified when your Subscription fails and no longer can be restarted
|
54
54
|
option(:failed_subscription_notifier)
|
55
|
+
# @!attribute subscription_graceful_shutdown_timeout
|
56
|
+
# @return [Integer] the number of seconds to wait until force-shutdown the subscription during the stop process
|
57
|
+
option(:subscription_graceful_shutdown_timeout) { 15 }
|
55
58
|
|
56
59
|
# @param name [Symbol] config's name. Its value matches the appropriate key in PgEventstore.config hash
|
57
60
|
def initialize(name:, **options)
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PgEventstore
|
4
|
+
module Extensions
|
5
|
+
module CallbackHandlersExtension
|
6
|
+
def self.included(klass)
|
7
|
+
klass.extend(ClassMethods)
|
8
|
+
end
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
# @param name [Symbol] a name of the handler
|
12
|
+
# @return [Proc]
|
13
|
+
def setup_handler(name, *args)
|
14
|
+
proc do |*rest|
|
15
|
+
public_send(name, *args, *rest)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -83,8 +83,8 @@ module PgEventstore
|
|
83
83
|
|
84
84
|
# @param run_interval [Integer, Float] seconds. Determines how often to run async task. Async task is determined by
|
85
85
|
# :after_runner_stopped callback
|
86
|
-
# @param async_shutdown_time [Integer, Float] seconds. Determines how long to wait
|
87
|
-
# for the
|
86
|
+
# @param async_shutdown_time [Integer, Float] seconds. Determines how long to wait before force-shutdown the runner.
|
87
|
+
# It is only meaningful for the #stop_async
|
88
88
|
def initialize(run_interval, async_shutdown_time)
|
89
89
|
@run_interval = run_interval
|
90
90
|
@async_shutdown_time = async_shutdown_time
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PgEventstore
|
4
|
+
class CommandsHandlerHandlers
|
5
|
+
include Extensions::CallbackHandlersExtension
|
6
|
+
|
7
|
+
class << self
|
8
|
+
# @param config_name [Symbol]
|
9
|
+
# @param subscription_feeder [PgEventstore::SubscriptionFeeder]
|
10
|
+
# @return [void]
|
11
|
+
def process_feeder_commands(config_name, subscription_feeder)
|
12
|
+
CommandHandlers::SubscriptionFeederCommands.new(config_name, subscription_feeder).process
|
13
|
+
end
|
14
|
+
|
15
|
+
# @param config_name [Symbol]
|
16
|
+
# @param runners [Array<PgEventstore::SubscriptionRunner>]
|
17
|
+
# @param subscription_feeder [PgEventstore::SubscriptionFeeder]
|
18
|
+
# @return [void]
|
19
|
+
def process_runners_commands(config_name, runners, subscription_feeder)
|
20
|
+
CommandHandlers::SubscriptionRunnersCommands.new(config_name, runners, subscription_feeder.id).process
|
21
|
+
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
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PgEventstore
|
4
|
+
class EventsProcessorHandlers
|
5
|
+
include Extensions::CallbackHandlersExtension
|
6
|
+
|
7
|
+
class << self
|
8
|
+
# @param callbacks [PgEventstore::Callbacks]
|
9
|
+
# @param handler [#call]
|
10
|
+
# @param raw_events [Array<Hash>]
|
11
|
+
# @return [void]
|
12
|
+
def process_event(callbacks, handler, raw_events)
|
13
|
+
raw_event = raw_events.shift
|
14
|
+
return sleep 0.5 if raw_event.nil?
|
15
|
+
|
16
|
+
callbacks.run_callbacks(:process, Utils.original_global_position(raw_event)) do
|
17
|
+
handler.call(raw_event)
|
18
|
+
end
|
19
|
+
rescue
|
20
|
+
raw_events.unshift(raw_event)
|
21
|
+
raise
|
22
|
+
end
|
23
|
+
|
24
|
+
# @param callbacks [PgEventstore::Callbacks]
|
25
|
+
# @param error [StandardError]
|
26
|
+
# @return [void]
|
27
|
+
def after_runner_died(callbacks, error)
|
28
|
+
callbacks.run_callbacks(:error, error)
|
29
|
+
end
|
30
|
+
|
31
|
+
# @param callbacks [PgEventstore::Callbacks]
|
32
|
+
# @return [void]
|
33
|
+
def before_runner_restored(callbacks)
|
34
|
+
callbacks.run_callbacks(:restart)
|
35
|
+
end
|
36
|
+
|
37
|
+
# @param callbacks [PgEventstore::Callbacks]
|
38
|
+
# @param state [String]
|
39
|
+
# @return [void]
|
40
|
+
def change_state(callbacks, state)
|
41
|
+
callbacks.run_callbacks(:change_state, state)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PgEventstore
|
4
|
+
class SubscriptionFeederHandlers
|
5
|
+
include Extensions::CallbackHandlersExtension
|
6
|
+
|
7
|
+
class << self
|
8
|
+
# @param subscriptions_set_lifecycle [PgEventstore::SubscriptionsSetLifecycle]
|
9
|
+
# @param state [String]
|
10
|
+
# @return [void]
|
11
|
+
def update_subscriptions_set_state(subscriptions_set_lifecycle, state)
|
12
|
+
subscriptions_set_lifecycle.persisted_subscriptions_set.update(state: state)
|
13
|
+
end
|
14
|
+
|
15
|
+
# @param subscriptions_lifecycle [PgEventstore::SubscriptionsLifecycle]
|
16
|
+
# @return [void]
|
17
|
+
def lock_subscriptions(subscriptions_lifecycle)
|
18
|
+
subscriptions_lifecycle.lock_all
|
19
|
+
end
|
20
|
+
|
21
|
+
# @param subscriptions_lifecycle [PgEventstore::SubscriptionsLifecycle]
|
22
|
+
# @return [void]
|
23
|
+
def start_runners(subscriptions_lifecycle)
|
24
|
+
subscriptions_lifecycle.runners.each(&:start)
|
25
|
+
end
|
26
|
+
|
27
|
+
# @param cmds_handler [PgEventstore::CommandsHandler]
|
28
|
+
# @return [void]
|
29
|
+
def start_cmds_handler(cmds_handler)
|
30
|
+
cmds_handler.start
|
31
|
+
end
|
32
|
+
|
33
|
+
# @param subscriptions_set_lifecycle [PgEventstore::SubscriptionsSetLifecycle]
|
34
|
+
# @param error [StandardError]
|
35
|
+
# @return [void]
|
36
|
+
def persist_error_info(subscriptions_set_lifecycle, error)
|
37
|
+
subscriptions_set_lifecycle.persisted_subscriptions_set.update(
|
38
|
+
last_error: Utils.error_info(error), last_error_occurred_at: Time.now.utc
|
39
|
+
)
|
40
|
+
end
|
41
|
+
|
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
|
+
# @param subscriptions_set_lifecycle [PgEventstore::SubscriptionsSetLifecycle]
|
57
|
+
# @return [void]
|
58
|
+
def ping_subscriptions_set(subscriptions_set_lifecycle)
|
59
|
+
subscriptions_set_lifecycle.ping_subscriptions_set
|
60
|
+
end
|
61
|
+
|
62
|
+
# @param subscriptions_lifecycle [PgEventstore::SubscriptionsLifecycle]
|
63
|
+
# @param config_name [Symbol]
|
64
|
+
# @return [void]
|
65
|
+
def feed_runners(subscriptions_lifecycle, config_name)
|
66
|
+
SubscriptionRunnersFeeder.new(config_name).feed(subscriptions_lifecycle.runners)
|
67
|
+
end
|
68
|
+
|
69
|
+
# @param subscriptions_lifecycle [PgEventstore::SubscriptionsLifecycle]
|
70
|
+
# @return [void]
|
71
|
+
def ping_subscriptions(subscriptions_lifecycle)
|
72
|
+
subscriptions_lifecycle.ping_subscriptions
|
73
|
+
end
|
74
|
+
|
75
|
+
# @param subscriptions_lifecycle [PgEventstore::SubscriptionsLifecycle]
|
76
|
+
# @return [void]
|
77
|
+
def stop_runners(subscriptions_lifecycle)
|
78
|
+
subscriptions_lifecycle.runners.each(&:stop_async).each(&:wait_for_finish)
|
79
|
+
end
|
80
|
+
|
81
|
+
# @param subscriptions_set_lifecycle [PgEventstore::SubscriptionsSetLifecycle]
|
82
|
+
# @return [void]
|
83
|
+
def reset_subscriptions_set(subscriptions_set_lifecycle)
|
84
|
+
subscriptions_set_lifecycle.reset_subscriptions_set
|
85
|
+
end
|
86
|
+
|
87
|
+
# @param cmds_handler [PgEventstore::CommandsHandler]
|
88
|
+
# @return [void]
|
89
|
+
def stop_commands_handler(cmds_handler)
|
90
|
+
cmds_handler.stop
|
91
|
+
end
|
92
|
+
|
93
|
+
# @param subscriptions_set_lifecycle [PgEventstore::SubscriptionsSetLifecycle]
|
94
|
+
# @return [void]
|
95
|
+
def update_subscriptions_set_restarts(subscriptions_set_lifecycle)
|
96
|
+
subscriptions_set = subscriptions_set_lifecycle.persisted_subscriptions_set
|
97
|
+
subscriptions_set.update(
|
98
|
+
last_restarted_at: Time.now.utc, restart_count: subscriptions_set.restart_count + 1
|
99
|
+
)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PgEventstore
|
4
|
+
class SubscriptionRunnerHandlers
|
5
|
+
include Extensions::CallbackHandlersExtension
|
6
|
+
|
7
|
+
class << self
|
8
|
+
# @param stats [PgEventstore::SubscriptionHandlerPerformance]
|
9
|
+
# @param action [Proc]
|
10
|
+
# @param _current_position [Integer]
|
11
|
+
# @return [void]
|
12
|
+
def track_exec_time(stats, action, _current_position)
|
13
|
+
stats.track_exec_time { action.call }
|
14
|
+
end
|
15
|
+
|
16
|
+
# @param subscription [PgEventstore::Subscription]
|
17
|
+
# @param stats [PgEventstore::SubscriptionHandlerPerformance]
|
18
|
+
# @param current_position [Integer]
|
19
|
+
# @return [void]
|
20
|
+
def update_subscription_stats(subscription, stats, current_position)
|
21
|
+
subscription.update(
|
22
|
+
average_event_processing_time: stats.average_event_processing_time,
|
23
|
+
current_position: current_position,
|
24
|
+
total_processed_events: subscription.total_processed_events + 1
|
25
|
+
)
|
26
|
+
end
|
27
|
+
|
28
|
+
# @param subscription [PgEventstore::Subscription]
|
29
|
+
# @param error [StandardError]
|
30
|
+
# @return [void]
|
31
|
+
def update_subscription_error(subscription, error)
|
32
|
+
subscription.update(last_error: Utils.error_info(error), last_error_occurred_at: Time.now.utc)
|
33
|
+
end
|
34
|
+
|
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 [StandardError]
|
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, error)
|
46
|
+
end
|
47
|
+
|
48
|
+
Thread.new do
|
49
|
+
sleep subscription.time_between_restarts
|
50
|
+
events_processor.restore
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# @param subscription [PgEventstore::Subscription]
|
55
|
+
# @param global_position [Integer]
|
56
|
+
# @return [void]
|
57
|
+
def update_subscription_chunk_stats(subscription, global_position)
|
58
|
+
subscription.update(last_chunk_fed_at: Time.now.utc, last_chunk_greatest_position: global_position)
|
59
|
+
end
|
60
|
+
|
61
|
+
# @param subscription [PgEventstore::Subscription]
|
62
|
+
# @return [void]
|
63
|
+
def update_subscription_restarts(subscription)
|
64
|
+
subscription.update(last_restarted_at: Time.now.utc, restart_count: subscription.restart_count + 1)
|
65
|
+
end
|
66
|
+
|
67
|
+
# @param subscription [PgEventstore::Subscription]
|
68
|
+
# @param state [String]
|
69
|
+
# @return [void]
|
70
|
+
def update_subscription_state(subscription, state)
|
71
|
+
subscription.update(state: state)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -31,35 +31,19 @@ module PgEventstore
|
|
31
31
|
private
|
32
32
|
|
33
33
|
def attach_runner_callbacks
|
34
|
-
@basic_runner.define_callback(
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
PgEventstore.logger&.error "#{self.class.name}: Backtrace: #{error.backtrace&.join("\n")}"
|
48
|
-
PgEventstore.logger&.error "#{self.class.name}: Trying to auto-repair in #{RESTART_DELAY} seconds..."
|
49
|
-
Thread.new do
|
50
|
-
sleep RESTART_DELAY
|
51
|
-
@basic_runner.restore
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
# @return [PgEventstore::CommandHandlers::SubscriptionFeederCommands]
|
56
|
-
def subscription_feeder_commands
|
57
|
-
CommandHandlers::SubscriptionFeederCommands.new(@config_name, @subscription_feeder)
|
58
|
-
end
|
59
|
-
|
60
|
-
# @return [PgEventstore::CommandHandlers::SubscriptionRunnersCommands]
|
61
|
-
def subscription_runners_commands
|
62
|
-
CommandHandlers::SubscriptionRunnersCommands.new(@config_name, @runners, @subscription_feeder.id)
|
34
|
+
@basic_runner.define_callback(
|
35
|
+
:process_async, :before,
|
36
|
+
CommandsHandlerHandlers.setup_handler(:process_feeder_commands, @config_name, @subscription_feeder)
|
37
|
+
)
|
38
|
+
@basic_runner.define_callback(
|
39
|
+
:process_async, :before,
|
40
|
+
CommandsHandlerHandlers.setup_handler(:process_runners_commands, @config_name, @runners, @subscription_feeder)
|
41
|
+
)
|
42
|
+
|
43
|
+
@basic_runner.define_callback(
|
44
|
+
:after_runner_died, :before,
|
45
|
+
CommandsHandlerHandlers.setup_handler(:restore_runner, @basic_runner, RESTART_DELAY)
|
46
|
+
)
|
63
47
|
end
|
64
48
|
end
|
65
49
|
end
|
@@ -11,10 +11,12 @@ module PgEventstore
|
|
11
11
|
:within_state
|
12
12
|
|
13
13
|
# @param handler [#call]
|
14
|
-
|
14
|
+
# @param graceful_shutdown_timeout [Integer, Float] seconds. Determines how long to wait before force-shutdown
|
15
|
+
# the runner when stopping it using #stop_async
|
16
|
+
def initialize(handler, graceful_shutdown_timeout:)
|
15
17
|
@handler = handler
|
16
18
|
@raw_events = []
|
17
|
-
@basic_runner = BasicRunner.new(0,
|
19
|
+
@basic_runner = BasicRunner.new(0, graceful_shutdown_timeout)
|
18
20
|
attach_runner_callbacks
|
19
21
|
end
|
20
22
|
|
@@ -24,7 +26,7 @@ module PgEventstore
|
|
24
26
|
raise EmptyChunkFedError.new("Empty chunk was fed!") if raw_events.empty?
|
25
27
|
|
26
28
|
within_state(:running) do
|
27
|
-
callbacks.run_callbacks(:feed,
|
29
|
+
callbacks.run_callbacks(:feed, Utils.original_global_position(raw_events.last))
|
28
30
|
@raw_events.push(*raw_events)
|
29
31
|
end
|
30
32
|
end
|
@@ -42,47 +44,23 @@ module PgEventstore
|
|
42
44
|
|
43
45
|
private
|
44
46
|
|
45
|
-
# @param raw_event [Hash]
|
46
|
-
# @return [void]
|
47
|
-
def process_event(raw_event)
|
48
|
-
callbacks.run_callbacks(:process, global_position(raw_event)) do
|
49
|
-
@handler.call(raw_event)
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
47
|
def attach_runner_callbacks
|
54
|
-
@basic_runner.define_callback(
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
def after_runner_died(...)
|
71
|
-
callbacks.run_callbacks(:error, ...)
|
72
|
-
end
|
73
|
-
|
74
|
-
def before_runner_restored
|
75
|
-
callbacks.run_callbacks(:restart)
|
76
|
-
end
|
77
|
-
|
78
|
-
def change_state(...)
|
79
|
-
callbacks.run_callbacks(:change_state, ...)
|
80
|
-
end
|
81
|
-
|
82
|
-
# @param raw_event [Hash]
|
83
|
-
# @return [Integer]
|
84
|
-
def global_position(raw_event)
|
85
|
-
raw_event['link'] ? raw_event['link']['global_position'] : raw_event['global_position']
|
48
|
+
@basic_runner.define_callback(
|
49
|
+
:process_async, :before,
|
50
|
+
EventsProcessorHandlers.setup_handler(:process_event, @callbacks, @handler, @raw_events)
|
51
|
+
)
|
52
|
+
|
53
|
+
@basic_runner.define_callback(
|
54
|
+
:after_runner_died, :before, EventsProcessorHandlers.setup_handler(:after_runner_died, callbacks)
|
55
|
+
)
|
56
|
+
|
57
|
+
@basic_runner.define_callback(
|
58
|
+
:before_runner_restored, :before, EventsProcessorHandlers.setup_handler(:before_runner_restored, callbacks)
|
59
|
+
)
|
60
|
+
|
61
|
+
@basic_runner.define_callback(
|
62
|
+
:change_state, :before, EventsProcessorHandlers.setup_handler(:change_state, callbacks)
|
63
|
+
)
|
86
64
|
end
|
87
65
|
end
|
88
66
|
end
|