pg_eventstore 1.0.3 → 1.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/lib/pg_eventstore/errors.rb +3 -0
- data/lib/pg_eventstore/queries/subscription_queries.rb +16 -0
- data/lib/pg_eventstore/subscriptions/events_processor.rb +4 -4
- data/lib/pg_eventstore/subscriptions/subscription.rb +22 -1
- data/lib/pg_eventstore/subscriptions/subscription_feeder.rb +19 -3
- data/lib/pg_eventstore/subscriptions/subscription_runner.rb +6 -5
- data/lib/pg_eventstore/subscriptions/subscription_runners_feeder.rb +2 -1
- data/lib/pg_eventstore/version.rb +1 -1
- data/lib/pg_eventstore/web/subscriptions/helpers.rb +2 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d5a69951bc18bd74869eb843b9e017a1c1f238bfc17750400e30b99f7d7b9f2d
|
4
|
+
data.tar.gz: 56ce94941096227944e8d5f11b9c7f9ca2f1fd816ad477cb02abe58604945c47
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f2f682990d1450b874e3d1ad9cf68e3e1cf7dcd546c78bb101982c5a03c5f355f31101442b2dd9a2c59531535e02eff01b12b119c79beca331f7262e927ebe5c
|
7
|
+
data.tar.gz: 2b2624a388eba5772c6a3bdd601ffe6fbcdb3c08c0d3c4585c1dfcf03862cf94f19e39db453950294f1a5a01a35e5ee33c975632c7ba6a2c966fcb85ff6dbb5d
|
data/CHANGELOG.md
CHANGED
data/lib/pg_eventstore/errors.rb
CHANGED
@@ -101,6 +101,22 @@ module PgEventstore
|
|
101
101
|
deserialize(updated_attrs)
|
102
102
|
end
|
103
103
|
|
104
|
+
# @param subscriptions_set_id [Integer] SubscriptionsSet#id
|
105
|
+
# @param subscriptions_ids [Array<Integer>] Array of Subscription#id
|
106
|
+
# @return [Hash<Integer => Time>]
|
107
|
+
def ping_all(subscriptions_set_id, subscriptions_ids)
|
108
|
+
pg_result = connection.with do |conn|
|
109
|
+
sql = <<~SQL
|
110
|
+
UPDATE subscriptions SET updated_at = $1 WHERE locked_by = $2 AND id = ANY($3::int[])
|
111
|
+
RETURNING id, updated_at
|
112
|
+
SQL
|
113
|
+
conn.exec_params(sql, [Time.now.utc, subscriptions_set_id, subscriptions_ids])
|
114
|
+
end
|
115
|
+
pg_result.to_h do |attrs|
|
116
|
+
[attrs['id'], attrs['updated_at']]
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
104
120
|
# @param query_options [Hash{Integer => Hash}] runner_id/query options association
|
105
121
|
# @return [Hash{Integer => Hash}] runner_id/events association
|
106
122
|
def subscriptions_events(query_options)
|
@@ -20,6 +20,8 @@ module PgEventstore
|
|
20
20
|
# @param raw_events [Array<Hash>]
|
21
21
|
# @return [void]
|
22
22
|
def feed(raw_events)
|
23
|
+
raise EmptyChunkFedError.new("Empty chunk was fed!") if raw_events.empty?
|
24
|
+
|
23
25
|
callbacks.run_callbacks(:feed, global_position(raw_events.last))
|
24
26
|
@raw_events.push(*raw_events)
|
25
27
|
end
|
@@ -69,11 +71,9 @@ module PgEventstore
|
|
69
71
|
callbacks.run_callbacks(:change_state, ...)
|
70
72
|
end
|
71
73
|
|
72
|
-
# @param raw_event [Hash
|
73
|
-
# @return [Integer
|
74
|
+
# @param raw_event [Hash]
|
75
|
+
# @return [Integer]
|
74
76
|
def global_position(raw_event)
|
75
|
-
return unless raw_event
|
76
|
-
|
77
77
|
raw_event['link'] ? raw_event['link']['global_position'] : raw_event['global_position']
|
78
78
|
end
|
79
79
|
end
|
@@ -73,6 +73,25 @@ module PgEventstore
|
|
73
73
|
# @return [Time]
|
74
74
|
attribute(:updated_at)
|
75
75
|
|
76
|
+
class << self
|
77
|
+
# @param subscriptions_set_id [Integer] SubscriptionsSet#id
|
78
|
+
# @param subscriptions [Array<PgEventstoreSubscription>]
|
79
|
+
# @return [void]
|
80
|
+
def ping_all(subscriptions_set_id, subscriptions)
|
81
|
+
result = subscription_queries.ping_all(subscriptions_set_id, subscriptions.map(&:id))
|
82
|
+
subscriptions.each do |subscription|
|
83
|
+
next unless result[subscription.id]
|
84
|
+
|
85
|
+
subscription.assign_attributes(updated_at: result[subscription.id])
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# @return [PgEventstore::SubscriptionQueries]
|
90
|
+
def subscription_queries
|
91
|
+
SubscriptionQueries.new(connection)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
76
95
|
def options=(val)
|
77
96
|
@options = Utils.deep_transform_keys(val, &:to_sym)
|
78
97
|
end
|
@@ -135,6 +154,7 @@ module PgEventstore
|
|
135
154
|
|
136
155
|
private
|
137
156
|
|
157
|
+
# @return [void]
|
138
158
|
def reset_runtime_attributes
|
139
159
|
update(
|
140
160
|
options: options,
|
@@ -151,8 +171,9 @@ module PgEventstore
|
|
151
171
|
)
|
152
172
|
end
|
153
173
|
|
174
|
+
# @return [PgEventstore::SubscriptionQueries]
|
154
175
|
def subscription_queries
|
155
|
-
|
176
|
+
self.class.subscription_queries
|
156
177
|
end
|
157
178
|
end
|
158
179
|
end
|
@@ -24,7 +24,7 @@ module PgEventstore
|
|
24
24
|
@commands_handler = CommandsHandler.new(@config_name, self, @runners)
|
25
25
|
@basic_runner = BasicRunner.new(0.2, 0)
|
26
26
|
@force_lock = false
|
27
|
-
@
|
27
|
+
@subscriptions_pinged_at = Time.at(0)
|
28
28
|
attach_runner_callbacks
|
29
29
|
end
|
30
30
|
|
@@ -100,6 +100,7 @@ module PgEventstore
|
|
100
100
|
@basic_runner.define_callback(:after_runner_died, :after, method(:restart_runner))
|
101
101
|
@basic_runner.define_callback(:process_async, :before, method(:ping_subscriptions_set))
|
102
102
|
@basic_runner.define_callback(:process_async, :before, method(:process_async))
|
103
|
+
@basic_runner.define_callback(:process_async, :after, method(:ping_subscriptions))
|
103
104
|
@basic_runner.define_callback(:after_runner_stopped, :before, method(:after_runner_stopped))
|
104
105
|
@basic_runner.define_callback(:before_runner_restored, :after, method(:update_runner_restarts))
|
105
106
|
end
|
@@ -140,10 +141,25 @@ module PgEventstore
|
|
140
141
|
|
141
142
|
# @return [void]
|
142
143
|
def ping_subscriptions_set
|
143
|
-
return
|
144
|
+
return if subscriptions_set.updated_at > Time.now.utc - HEARTBEAT_INTERVAL
|
144
145
|
|
145
146
|
subscriptions_set.update(updated_at: Time.now.utc)
|
146
|
-
|
147
|
+
end
|
148
|
+
|
149
|
+
# @return [void]
|
150
|
+
def ping_subscriptions
|
151
|
+
return if @subscriptions_pinged_at > Time.now.utc - HEARTBEAT_INTERVAL
|
152
|
+
|
153
|
+
runners = @runners.select do |runner|
|
154
|
+
next false unless runner.running?
|
155
|
+
|
156
|
+
runner.subscription.updated_at < Time.now.utc - HEARTBEAT_INTERVAL
|
157
|
+
end
|
158
|
+
unless runners.empty?
|
159
|
+
Subscription.using_connection(@config_name).ping_all(subscriptions_set.id, runners.map(&:subscription))
|
160
|
+
end
|
161
|
+
|
162
|
+
@subscriptions_pinged_at = Time.now.utc
|
147
163
|
end
|
148
164
|
|
149
165
|
# @return [void]
|
@@ -11,6 +11,7 @@ module PgEventstore
|
|
11
11
|
extend Forwardable
|
12
12
|
|
13
13
|
MAX_EVENTS_PER_CHUNK = 1_000
|
14
|
+
MIN_EVENTS_PER_CHUNK = 10
|
14
15
|
INITIAL_EVENTS_PER_CHUNK = 10
|
15
16
|
|
16
17
|
attr_reader :subscription
|
@@ -56,7 +57,10 @@ module PgEventstore
|
|
56
57
|
return INITIAL_EVENTS_PER_CHUNK if @stats.average_event_processing_time.zero?
|
57
58
|
|
58
59
|
events_per_chunk = (@subscription.chunk_query_interval / @stats.average_event_processing_time).round
|
59
|
-
[
|
60
|
+
events_to_fetch = [events_per_chunk, MAX_EVENTS_PER_CHUNK].min - @events_processor.events_left_in_chunk
|
61
|
+
return 0 if events_to_fetch < 0 # We still have a lot of events in the chunk - no need to fetch more
|
62
|
+
|
63
|
+
[events_to_fetch, MIN_EVENTS_PER_CHUNK].max
|
60
64
|
end
|
61
65
|
|
62
66
|
# @return [void]
|
@@ -103,12 +107,9 @@ module PgEventstore
|
|
103
107
|
@subscription.update(last_error: Utils.error_info(error), last_error_occurred_at: Time.now.utc)
|
104
108
|
end
|
105
109
|
|
106
|
-
# @param global_position [Integer
|
110
|
+
# @param global_position [Integer]
|
107
111
|
# @return [void]
|
108
112
|
def update_subscription_chunk_stats(global_position)
|
109
|
-
# nil means subscriptions events query were executed, but there were no new events
|
110
|
-
return @subscription.update(updated_at: Time.now.utc) if global_position.nil?
|
111
|
-
|
112
113
|
@subscription.update(last_chunk_fed_at: Time.now.utc, last_chunk_greatest_position: global_position)
|
113
114
|
end
|
114
115
|
|
@@ -17,8 +17,9 @@ module PgEventstore
|
|
17
17
|
|
18
18
|
runners_query_options = runners.to_h { |runner| [runner.id, runner.next_chunk_query_opts] }
|
19
19
|
grouped_events = subscription_queries.subscriptions_events(runners_query_options)
|
20
|
+
|
20
21
|
runners.each do |runner|
|
21
|
-
runner.feed(grouped_events[runner.id]
|
22
|
+
runner.feed(grouped_events[runner.id]) if grouped_events[runner.id]
|
22
23
|
end
|
23
24
|
end
|
24
25
|
|
@@ -43,7 +43,8 @@ module PgEventstore
|
|
43
43
|
# @return [String] html status
|
44
44
|
def colored_state(state, updated_at)
|
45
45
|
if state == RunnerState::STATES[:running]
|
46
|
-
|
46
|
+
# -1 is added as a margin to prevent false-positive result
|
47
|
+
if updated_at < Time.now.utc - SubscriptionFeeder::HEARTBEAT_INTERVAL - 1
|
47
48
|
title = <<~TEXT
|
48
49
|
Something is wrong. Last update was more than #{SubscriptionFeeder::HEARTBEAT_INTERVAL} seconds \
|
49
50
|
ago(#{updated_at}).
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pg_eventstore
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ivan Dzyzenko
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-06-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pg
|