pg_eventstore 0.10.1 → 0.10.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9426880dd6354875d896f5bf37abeac180c4f04b26905db0efc035fec316e6b9
4
- data.tar.gz: 355a6c370451fff9e391aa0ecb1c6abf105c6fc537d99f6b7371359067dd2ee4
3
+ metadata.gz: ccfbe47f6f178820e5f7b5ccc9fb9298bf6beba4fa10081cd01bcd6ce3fe1001
4
+ data.tar.gz: b55180dc1c24ec04d13e99b0d4ba920eae5eef652ccde632f332ab67b27cc14e
5
5
  SHA512:
6
- metadata.gz: fc96e847b892e375115a08985678328d166742e5f6be3ee967f67dc808c80166a58f010555567b05fbac172b31c7d98276d1e898de6889d5d53d3ccf0ab2be47
7
- data.tar.gz: cba82b0c20d4104cd6878fd2471e5c4d0c70e60991f573cd5aa1a845e7e5b443cf9f15448b81754888a84883c6bfbaf932e452c13fd7d5d229b03185741f1dbd
6
+ metadata.gz: 4226be0aa1f6109b5a956febca5343b1a1d215c6a16e056267027287bcb629295cd4af1a7f6fc093e781c90a48f885f2b5932faff7962bdd993305519bfca053
7
+ data.tar.gz: 2eb04ad6b29569f29282768e806813823e990493674c627252963d312966aa1806f06139b4b01937699c0fcf4b25034c2e02cb7375710d65838d62bb3934099d
data/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.10.2] - 2024-03-13
4
+
5
+ - Review the approach to resolve link events
6
+ - Fix subscriptions restart interval option not being processed correctly
7
+
3
8
  ## [0.10.1] - 2024-03-12
4
9
 
5
10
  - Handle edge case when creating partitions
@@ -10,7 +10,7 @@ Configuration options:
10
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
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
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. |
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
14
  | subscription_max_retries | Integer | `5` | Max number of retries of failed subscription. |
15
15
  | subscription_retries_interval | Integer | `1` | Interval in seconds between retries of failed subscriptions. |
16
16
  | subscriptions_set_max_retries | Integer | `10` | Max number of retries for failed subscription sets. |
@@ -31,6 +31,10 @@ module PgEventstore
31
31
  # @return [String, nil] UUIDv4 of an event the current event points to. If it is not nil, then the current
32
32
  # event is a link
33
33
  attribute(:link_id)
34
+ # @!attribute link
35
+ # @return [PgEventstore::Event, nil] when resolve_link_tos: true option is provided during the read of events and
36
+ # event is a link event - this attribute will be pointing on that link
37
+ attribute(:link)
34
38
  # @!attribute created_at
35
39
  # @return [Time, nil] a timestamp an event was created at
36
40
  attribute(:created_at)
@@ -41,7 +45,7 @@ module PgEventstore
41
45
  def ==(other)
42
46
  return false unless other.is_a?(PgEventstore::Event)
43
47
 
44
- attributes_hash == other.attributes_hash
48
+ attributes_hash.except(:link) == other.attributes_hash.except(:link)
45
49
  end
46
50
 
47
51
  # Detect whether an event is a link event
@@ -27,6 +27,7 @@ module PgEventstore
27
27
  event.stream = PgEventstore::Stream.new(
28
28
  **attrs.slice('context', 'stream_name', 'stream_id').transform_keys(&:to_sym)
29
29
  )
30
+ event.link = without_middlewares.deserialize(attrs['link']) if attrs.key?('link')
30
31
  event
31
32
  end
32
33
 
@@ -47,6 +47,7 @@ module PgEventstore
47
47
  raw_events = connection.with do |conn|
48
48
  conn.exec_params(*exec_params)
49
49
  end.to_a
50
+ raw_events = links_resolver.resolve(raw_events) if options[:resolve_link_tos]
50
51
  deserializer.deserialize_many(raw_events)
51
52
  end
52
53
 
@@ -106,5 +107,10 @@ module PgEventstore
106
107
 
107
108
  QueryBuilders::EventsFiltering.specific_stream_filtering(stream, options)
108
109
  end
110
+
111
+ # @return [PgEventstore::LinksResolver]
112
+ def links_resolver
113
+ LinksResolver.new(connection)
114
+ end
109
115
  end
110
116
  end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PgEventstore
4
+ # @!visibility private
5
+ class LinksResolver
6
+ attr_reader :connection
7
+ private :connection
8
+
9
+ # @param connection [PgEventstore::Connection]
10
+ def initialize(connection)
11
+ @connection = connection
12
+ end
13
+
14
+ # @param raw_events [Array<Hash>]
15
+ def resolve(raw_events)
16
+ ids = raw_events.map { _1['link_id'] }.compact.uniq
17
+ return raw_events if ids.empty?
18
+
19
+ original_events = connection.with do |conn|
20
+ conn.exec_params('select * from events where id = ANY($1::uuid[])', [ids])
21
+ end.to_h { |attrs| [attrs['id'], attrs] }
22
+
23
+ raw_events.map do |attrs|
24
+ original_event = original_events[attrs['link_id']]
25
+ next attrs unless original_event
26
+
27
+ original_event.merge('link' => attrs).merge(attrs.except(*original_event.keys))
28
+ end
29
+ end
30
+ end
31
+ end
@@ -73,15 +73,20 @@ module PgEventstore
73
73
  deserialize(pg_result.to_a.first)
74
74
  end
75
75
 
76
- # @param query_options [Array<Array<Integer, Hash>>] array of runner ids and query options
77
- # @return [Array<Hash>] array of raw events
76
+ # @param query_options [Hash{Integer => Hash}] runner_id/query options association
77
+ # @return [Hash{Integer => Hash}] runner_id/events association
78
78
  def subscriptions_events(query_options)
79
- return [] if query_options.empty?
79
+ return {} if query_options.empty?
80
80
 
81
81
  final_builder = union_builders(query_options.map { |id, opts| query_builder(id, opts) })
82
- connection.with do |conn|
82
+ raw_events = connection.with do |conn|
83
83
  conn.exec_params(*final_builder.to_exec_params)
84
84
  end.to_a
85
+ raw_events.group_by { _1['runner_id'] }.to_h do |runner_id, runner_raw_events|
86
+ next [runner_id, runner_raw_events] unless query_options[runner_id][:resolve_link_tos]
87
+
88
+ [runner_id, links_resolver.resolve(runner_raw_events)]
89
+ end
85
90
  end
86
91
 
87
92
  # @param id [Integer] subscription's id
@@ -144,9 +149,9 @@ module PgEventstore
144
149
  TransactionQueries.new(connection)
145
150
  end
146
151
 
147
- # @return [PgEventstore::EventTypeQueries]
148
- def event_type_queries
149
- EventTypeQueries.new(connection)
152
+ # @return [PgEventstore::LinksResolver]
153
+ def links_resolver
154
+ LinksResolver.new(connection)
150
155
  end
151
156
 
152
157
  # @param hash [Hash]
@@ -9,6 +9,7 @@ require_relative 'queries/subscription_queries'
9
9
  require_relative 'queries/subscriptions_set_queries'
10
10
  require_relative 'queries/subscription_command_queries'
11
11
  require_relative 'queries/subscriptions_set_command_queries'
12
+ require_relative 'queries/links_resolver'
12
13
 
13
14
  module PgEventstore
14
15
  # @!visibility private
@@ -31,7 +31,6 @@ module PgEventstore
31
31
  options in { filter: { event_types: Array => event_type_ids } }
32
32
  event_filter.add_event_types(event_type_ids)
33
33
  event_filter.add_limit(options[:max_count])
34
- event_filter.resolve_links(options[:resolve_link_tos])
35
34
  options in { filter: { streams: Array => streams } }
36
35
  streams&.each { |attrs| event_filter.add_stream_attrs(**attrs) }
37
36
  event_filter.add_global_position(options[:from_position], options[:direction])
@@ -47,7 +46,6 @@ module PgEventstore
47
46
  options in { filter: { event_types: Array => event_type_ids } }
48
47
  event_filter.add_event_types(event_type_ids)
49
48
  event_filter.add_limit(options[:max_count])
50
- event_filter.resolve_links(options[:resolve_link_tos])
51
49
  event_filter.add_stream_attrs(**stream.to_hash)
52
50
  event_filter.add_revision(options[:from_revision], options[:direction])
53
51
  event_filter.add_stream_direction(options[:direction])
@@ -128,17 +126,6 @@ module PgEventstore
128
126
  @sql_builder.limit(limit)
129
127
  end
130
128
 
131
- # @param should_resolve [Boolean]
132
- # @return [void]
133
- def resolve_links(should_resolve)
134
- return unless should_resolve
135
-
136
- @sql_builder.
137
- unselect.
138
- select("(COALESCE(original_events.*, events.*)).*").
139
- join("LEFT JOIN events original_events ON original_events.id = events.link_id")
140
- end
141
-
142
129
  # @return [PgEventstore::SQLBuilder]
143
130
  def to_sql_builder
144
131
  @sql_builder
@@ -20,7 +20,7 @@ module PgEventstore
20
20
  # @param raw_events [Array<Hash>]
21
21
  # @return [void]
22
22
  def feed(raw_events)
23
- callbacks.run_callbacks(:feed, raw_events.last&.dig('global_position'))
23
+ callbacks.run_callbacks(:feed, global_position(raw_events.last))
24
24
  @raw_events.push(*raw_events)
25
25
  end
26
26
 
@@ -35,7 +35,7 @@ module PgEventstore
35
35
  # @param raw_event [Hash]
36
36
  # @return [void]
37
37
  def process_event(raw_event)
38
- callbacks.run_callbacks(:process, raw_event['global_position']) do
38
+ callbacks.run_callbacks(:process, global_position(raw_event)) do
39
39
  @handler.call(raw_event)
40
40
  end
41
41
  end
@@ -68,5 +68,13 @@ module PgEventstore
68
68
  def change_state(...)
69
69
  callbacks.run_callbacks(:change_state, ...)
70
70
  end
71
+
72
+ # @param raw_event [Hash, nil]
73
+ # @return [Integer, nil]
74
+ def global_position(raw_event)
75
+ return unless raw_event
76
+
77
+ raw_event['link'] ? raw_event['link']['global_position'] : raw_event['global_position']
78
+ end
71
79
  end
72
80
  end
@@ -130,6 +130,7 @@ module PgEventstore
130
130
  chunk_query_interval: chunk_query_interval,
131
131
  last_chunk_fed_at: Time.at(0).utc,
132
132
  last_chunk_greatest_position: nil,
133
+ time_between_restarts: time_between_restarts,
133
134
  state: RunnerState::STATES[:initial]
134
135
  )
135
136
  end
@@ -21,7 +21,7 @@ module PgEventstore
21
21
  @max_retries = max_retries
22
22
  @retries_interval = retries_interval
23
23
  @commands_handler = CommandsHandler.new(@config_name, self, @runners)
24
- @basic_runner = BasicRunner.new(1, 0)
24
+ @basic_runner = BasicRunner.new(0.2, 0)
25
25
  @force_lock = false
26
26
  attach_runner_callbacks
27
27
  end
@@ -15,9 +15,8 @@ module PgEventstore
15
15
  runners = runners.select(&:running?).select(&:time_to_feed?)
16
16
  return if runners.empty?
17
17
 
18
- runners_query_options = runners.map { |runner| [runner.id, runner.next_chunk_query_opts] }
19
- raw_events = subscription_queries.subscriptions_events(runners_query_options)
20
- grouped_events = raw_events.group_by { |attrs| attrs['runner_id'] }
18
+ runners_query_options = runners.to_h { |runner| [runner.id, runner.next_chunk_query_opts] }
19
+ grouped_events = subscription_queries.subscriptions_events(runners_query_options)
21
20
  runners.each do |runner|
22
21
  runner.feed(grouped_events[runner.id]) if grouped_events[runner.id]
23
22
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PgEventstore
4
- VERSION = "0.10.1"
4
+ VERSION = "0.10.2"
5
5
  end
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: 0.10.1
4
+ version: 0.10.2
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-03-12 00:00:00.000000000 Z
11
+ date: 2024-03-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pg
@@ -91,6 +91,7 @@ files:
91
91
  - lib/pg_eventstore/pg_connection.rb
92
92
  - lib/pg_eventstore/queries.rb
93
93
  - lib/pg_eventstore/queries/event_queries.rb
94
+ - lib/pg_eventstore/queries/links_resolver.rb
94
95
  - lib/pg_eventstore/queries/partition_queries.rb
95
96
  - lib/pg_eventstore/queries/subscription_command_queries.rb
96
97
  - lib/pg_eventstore/queries/subscription_queries.rb