ruby_event_store 2.19.2 → 3.1.0

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.
Files changed (29) hide show
  1. checksums.yaml +4 -4
  2. data/lib/ruby_event_store/broker.rb +1 -1
  3. data/lib/ruby_event_store/client.rb +2 -6
  4. data/lib/ruby_event_store/errors.rb +2 -0
  5. data/lib/ruby_event_store/in_memory_repository.rb +3 -10
  6. data/lib/ruby_event_store/instrumented_broker.rb +14 -42
  7. data/lib/ruby_event_store/instrumented_dispatcher.rb +1 -15
  8. data/lib/ruby_event_store/instrumented_repository.rb +8 -39
  9. data/lib/ruby_event_store/instrumented_subscriptions.rb +2 -2
  10. data/lib/ruby_event_store/mappers/default.rb +2 -12
  11. data/lib/ruby_event_store/mappers/instrumented_batch_mapper.rb +2 -18
  12. data/lib/ruby_event_store/mappers/instrumented_mapper.rb +2 -32
  13. data/lib/ruby_event_store/mappers/transformation/upcast.rb +6 -1
  14. data/lib/ruby_event_store/projection.rb +9 -70
  15. data/lib/ruby_event_store/record.rb +3 -34
  16. data/lib/ruby_event_store/serialized_record.rb +3 -34
  17. data/lib/ruby_event_store/spec/broker_lint.rb +2 -2
  18. data/lib/ruby_event_store/spec/event_repository_lint.rb +42 -0
  19. data/lib/ruby_event_store/specification.rb +0 -8
  20. data/lib/ruby_event_store/sync_scheduler.rb +1 -14
  21. data/lib/ruby_event_store/version.rb +1 -1
  22. data/lib/ruby_event_store.rb +0 -6
  23. metadata +3 -9
  24. data/lib/ruby_event_store/deprecated.rb +0 -98
  25. data/lib/ruby_event_store/dispatcher.rb +0 -6
  26. data/lib/ruby_event_store/immediate_async_dispatcher.rb +0 -6
  27. data/lib/ruby_event_store/mappers/json_mapper.rb +0 -16
  28. data/lib/ruby_event_store/mappers/null_mapper.rb +0 -11
  29. data/lib/ruby_event_store/mappers/transformation/event_class_remapper.rb +0 -32
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a38be596490cc7feffdf26968a8175a2a1606ba567f448382b2aecfe2e78ebd9
4
- data.tar.gz: c64882bef174236d979680f84ed1d16b37f8ef2ba2a48b50a49d55286cff523e
3
+ metadata.gz: 122d18b13759b12a2916e695e0f846a185912493275718bd7d8b1f665cdf6182
4
+ data.tar.gz: d744d6882572eeff995fe60d21a0e6ee1dc7bd486c4c9bd584b7f461c38c12c3
5
5
  SHA512:
6
- metadata.gz: 07a6509f6ac818e525834d0bae05b297ef2802643fee60cc45024cf3ea2faf49744f26dfe31896be18274dfc83e4a6be62abef1cb6faa27c67b8de8664998d11
7
- data.tar.gz: f4846eedf860127e23bcdc38c37b13028896b39836a3af75689943de59bbdf633d7b2dd0e30cade9728486710cc2395db99ec4adef98a60fcfbdb4c494724e3f
6
+ metadata.gz: 73529e99d9af66ee1c4bfba654854e48a7d381789fc12784e7f859bcfb509c66b3004c13cf3607a61871799d3b393683576eb28690829110e01935b9e422f071
7
+ data.tar.gz: b2d083b7458c6bf4b0b3dbc5800792b619028f679d7b3490f9c45d3941ec116a97410e9078f45acdc023fc486d85d81b27980ac2296667de428477bdfd0c9f6a
@@ -2,7 +2,7 @@
2
2
 
3
3
  module RubyEventStore
4
4
  class Broker
5
- def initialize(subscriptions: Subscriptions.new, dispatcher: Dispatcher.new)
5
+ def initialize(subscriptions: Subscriptions.new, dispatcher: SyncScheduler.new)
6
6
  @subscriptions = subscriptions
7
7
  @dispatcher = dispatcher
8
8
  end
@@ -99,9 +99,7 @@ module RubyEventStore
99
99
  # @param expected_version (see #publish)
100
100
  # @return [self]
101
101
  def link(event_ids, stream_name:, expected_version: :any)
102
- warn <<~EOW if event_ids.nil? || Array(event_ids).any?(&:nil?)
103
- Passing `nil` to link is deprecated and will raise ArgumentError in RubyEventStore 3.0.
104
- EOW
102
+ raise ArgumentError, "event_ids must not be nil" if event_ids.nil? || Array(event_ids).any?(&:nil?)
105
103
  @repository.link_to_stream(Array(event_ids), Stream.new(stream_name), ExpectedVersion.new(expected_version))
106
104
  self
107
105
  end
@@ -384,9 +382,7 @@ module RubyEventStore
384
382
  end
385
383
 
386
384
  def enrich_events_metadata(events)
387
- warn <<~EOW if events.nil? || Array(events).any?(&:nil?)
388
- Passing `nil` to publish/append is deprecated and will raise ArgumentError in RubyEventStore 3.0.
389
- EOW
385
+ raise ArgumentError, "events must not be nil" if events.nil? || Array(events).any?(&:nil?)
390
386
  events = Array(events)
391
387
  events.each { |event| enrich_event_metadata(event) }
392
388
  end
@@ -14,6 +14,8 @@ module RubyEventStore
14
14
  InvalidHandler = Class.new(Error)
15
15
  EventNotFoundInStream = Class.new(Error)
16
16
  SubscriptionsNotSupported = Class.new(Error)
17
+ StringsRequired = Class.new(Error)
18
+ InvalidUpcast = Class.new(Error)
17
19
 
18
20
  class EventNotFound < Error
19
21
  attr_reader :event_id
@@ -22,12 +22,11 @@ module RubyEventStore
22
22
  attr_reader :event_id, :position
23
23
  end
24
24
 
25
- def initialize(serializer: NULL, ensure_supported_any_usage: false)
25
+ def initialize(serializer: NULL)
26
26
  @serializer = serializer
27
27
  @streams = Hash.new { |h, k| h[k] = Array.new }
28
28
  @mutex = Mutex.new
29
29
  @storage = Hash.new
30
- @ensure_supported_any_usage = ensure_supported_any_usage
31
30
  end
32
31
 
33
32
  def append_to_stream(records, stream, expected_version)
@@ -149,7 +148,6 @@ module RubyEventStore
149
148
  serialized_records = serialized_records.reverse if spec.backward?
150
149
  serialized_records = serialized_records.drop(index_of(serialized_records, spec.start) + 1) if spec.start
151
150
  serialized_records = serialized_records.take(index_of(serialized_records, spec.stop)) if spec.stop
152
- serialized_records = serialized_records.take(spec.limit) if spec.limit?
153
151
  serialized_records =
154
152
  serialized_records.select do |sr|
155
153
  Time.iso8601(time_comparison_field(spec, sr)) < spec.older_than
@@ -166,6 +164,7 @@ module RubyEventStore
166
164
  serialized_records.select do |sr|
167
165
  Time.iso8601(time_comparison_field(spec, sr)) >= spec.newer_than_or_equal
168
166
  end if spec.newer_than_or_equal
167
+ serialized_records = serialized_records.take(spec.limit) if spec.limit?
169
168
  serialized_records
170
169
  end
171
170
 
@@ -239,13 +238,7 @@ module RubyEventStore
239
238
  (resolved_version.nil? && !stream_positions.compact.empty?) ||
240
239
  (!resolved_version.nil? && stream_positions.include?(nil))
241
240
 
242
- if violation
243
- if @ensure_supported_any_usage
244
- raise UnsupportedVersionAnyUsage
245
- else
246
- Deprecations.warn(:any_version_with_specific_position)
247
- end
248
- end
241
+ raise UnsupportedVersionAnyUsage if violation
249
242
  end
250
243
 
251
244
  attr_reader :streams, :mutex, :storage, :serializer
@@ -9,34 +9,28 @@ module RubyEventStore
9
9
 
10
10
  def call(topic, event, record)
11
11
  instrumentation.instrument("call.broker.ruby_event_store", topic: topic, event: event, record: record) do
12
- deprecated_instrument("call.broker.rails_event_store", topic: topic, event: event, record: record) do
13
- if broker.public_method(:call).arity == 3
14
- broker.call(topic, event, record)
15
- else
16
- warn <<~EOW
17
- Message broker shall support topics.
18
- Topic WILL BE IGNORED in the current broker.
19
- Modify the broker implementation to pass topic as an argument to broker.call method.
20
- EOW
21
- broker.call(event, record)
22
- end
12
+ if broker.public_method(:call).arity == 3
13
+ broker.call(topic, event, record)
14
+ else
15
+ warn <<~EOW
16
+ Message broker shall support topics.
17
+ Topic WILL BE IGNORED in the current broker.
18
+ Modify the broker implementation to pass topic as an argument to broker.call method.
19
+ EOW
20
+ broker.call(event, record)
23
21
  end
24
22
  end
25
23
  end
26
24
 
27
25
  def add_subscription(subscriber, topics)
28
26
  instrumentation.instrument("add_subscription.broker.ruby_event_store", subscriber: subscriber, topics: topics) do
29
- deprecated_instrument("add_subscription.broker.rails_event_store", subscriber: subscriber, topics: topics) do
30
- broker.add_subscription(subscriber, topics)
31
- end
27
+ broker.add_subscription(subscriber, topics)
32
28
  end
33
29
  end
34
30
 
35
31
  def add_global_subscription(subscriber)
36
32
  instrumentation.instrument("add_global_subscription.broker.ruby_event_store", subscriber: subscriber) do
37
- deprecated_instrument("add_global_subscription.broker.rails_event_store", subscriber: subscriber) do
38
- broker.add_global_subscription(subscriber)
39
- end
33
+ broker.add_global_subscription(subscriber)
40
34
  end
41
35
  end
42
36
 
@@ -45,28 +39,18 @@ module RubyEventStore
45
39
  "add_thread_subscription.broker.ruby_event_store",
46
40
  subscriber: subscriber,
47
41
  topics: topics,
48
- ) do
49
- deprecated_instrument(
50
- "add_thread_subscription.broker.rails_event_store",
51
- subscriber: subscriber,
52
- topics: topics,
53
- ) { broker.add_thread_subscription(subscriber, topics) }
54
- end
42
+ ) { broker.add_thread_subscription(subscriber, topics) }
55
43
  end
56
44
 
57
45
  def add_thread_global_subscription(subscriber)
58
46
  instrumentation.instrument("add_thread_global_subscription.broker.ruby_event_store", subscriber: subscriber) do
59
- deprecated_instrument("add_thread_global_subscription.broker.rails_event_store", subscriber: subscriber) do
60
- broker.add_thread_global_subscription(subscriber)
61
- end
47
+ broker.add_thread_global_subscription(subscriber)
62
48
  end
63
49
  end
64
50
 
65
51
  def all_subscriptions_for(topic)
66
52
  instrumentation.instrument("all_subscriptions_for.broker.ruby_event_store", topic: topic) do
67
- deprecated_instrument("all_subscriptions_for.broker.rails_event_store", topic: topic) do
68
- broker.all_subscriptions_for(topic)
69
- end
53
+ broker.all_subscriptions_for(topic)
70
54
  end
71
55
  end
72
56
 
@@ -85,17 +69,5 @@ module RubyEventStore
85
69
  private
86
70
 
87
71
  attr_reader :instrumentation, :broker
88
-
89
- def deprecated_instrument(name, payload, &block)
90
- canonical_name = name.sub("rails_event_store", "ruby_event_store")
91
- old_listeners = instrumentation.notifier.all_listeners_for(name)
92
- new_listeners = instrumentation.notifier.all_listeners_for(canonical_name)
93
- if (old_listeners - new_listeners).any?
94
- Deprecations.warn(:instrumentation_renamed)
95
- instrumentation.instrument(name, payload, &block)
96
- else
97
- yield
98
- end
99
- end
100
72
  end
101
73
  end
@@ -9,9 +9,7 @@ module RubyEventStore
9
9
 
10
10
  def call(subscriber, event, record)
11
11
  instrumentation.instrument("call.dispatcher.ruby_event_store", event: event, subscriber: subscriber) do
12
- deprecated_instrument("call.dispatcher.rails_event_store", event: event, subscriber: subscriber) do
13
- dispatcher.call(subscriber, event, record)
14
- end
12
+ dispatcher.call(subscriber, event, record)
15
13
  end
16
14
  end
17
15
 
@@ -30,17 +28,5 @@ module RubyEventStore
30
28
  private
31
29
 
32
30
  attr_reader :instrumentation, :dispatcher
33
-
34
- def deprecated_instrument(name, payload, &block)
35
- canonical_name = name.sub("rails_event_store", "ruby_event_store")
36
- old_listeners = instrumentation.notifier.all_listeners_for(name)
37
- new_listeners = instrumentation.notifier.all_listeners_for(canonical_name)
38
- if (old_listeners - new_listeners).any?
39
- Deprecations.warn(:instrumentation_renamed)
40
- instrumentation.instrument(name, payload, &block)
41
- else
42
- yield
43
- end
44
- end
45
31
  end
46
32
  end
@@ -11,62 +11,43 @@ module RubyEventStore
11
11
  instrumentation.instrument(
12
12
  "append_to_stream.repository.ruby_event_store",
13
13
  records: records,
14
- events: records,
15
14
  stream: stream,
16
- ) do
17
- deprecated_instrument(
18
- "append_to_stream.repository.rails_event_store",
19
- { records: records, events: records, stream: stream },
20
- ) { repository.append_to_stream(records, stream, expected_version) }
21
- end
15
+ ) { repository.append_to_stream(records, stream, expected_version) }
22
16
  end
23
17
 
24
18
  def link_to_stream(event_ids, stream, expected_version)
25
19
  instrumentation.instrument("link_to_stream.repository.ruby_event_store", event_ids: event_ids, stream: stream) do
26
- deprecated_instrument("link_to_stream.repository.rails_event_store", event_ids: event_ids, stream: stream) do
27
- repository.link_to_stream(event_ids, stream, expected_version)
28
- end
20
+ repository.link_to_stream(event_ids, stream, expected_version)
29
21
  end
30
22
  end
31
23
 
32
24
  def delete_stream(stream)
33
25
  instrumentation.instrument("delete_stream.repository.ruby_event_store", stream: stream) do
34
- deprecated_instrument("delete_stream.repository.rails_event_store", stream: stream) do
35
- repository.delete_stream(stream)
36
- end
26
+ repository.delete_stream(stream)
37
27
  end
38
28
  end
39
29
 
40
30
  def read(specification)
41
31
  instrumentation.instrument("read.repository.ruby_event_store", specification: specification) do
42
- deprecated_instrument("read.repository.rails_event_store", specification: specification) do
43
- repository.read(specification)
44
- end
32
+ repository.read(specification)
45
33
  end
46
34
  end
47
35
 
48
36
  def count(specification)
49
37
  instrumentation.instrument("count.repository.ruby_event_store", specification: specification) do
50
- deprecated_instrument("count.repository.rails_event_store", specification: specification) do
51
- repository.count(specification)
52
- end
38
+ repository.count(specification)
53
39
  end
54
40
  end
55
41
 
56
42
  def update_messages(records)
57
- instrumentation.instrument("update_messages.repository.ruby_event_store", records: records, messages: records) do
58
- deprecated_instrument(
59
- "update_messages.repository.rails_event_store",
60
- { records: records, messages: records },
61
- ) { repository.update_messages(records) }
43
+ instrumentation.instrument("update_messages.repository.ruby_event_store", records: records) do
44
+ repository.update_messages(records)
62
45
  end
63
46
  end
64
47
 
65
48
  def streams_of(event_id)
66
49
  instrumentation.instrument("streams_of.repository.ruby_event_store", event_id: event_id) do
67
- deprecated_instrument("streams_of.repository.rails_event_store", event_id: event_id) do
68
- repository.streams_of(event_id)
69
- end
50
+ repository.streams_of(event_id)
70
51
  end
71
52
  end
72
53
 
@@ -85,17 +66,5 @@ module RubyEventStore
85
66
  private
86
67
 
87
68
  attr_reader :repository, :instrumentation
88
-
89
- def deprecated_instrument(name, payload, &block)
90
- canonical_name = name.sub("rails_event_store", "ruby_event_store")
91
- old_listeners = instrumentation.notifier.all_listeners_for(name)
92
- new_listeners = instrumentation.notifier.all_listeners_for(canonical_name)
93
- if (old_listeners - new_listeners).any?
94
- Deprecations.warn(:instrumentation_renamed)
95
- instrumentation.instrument(name, payload, &block)
96
- else
97
- yield
98
- end
99
- end
100
69
  end
101
70
  end
@@ -42,9 +42,9 @@ module RubyEventStore
42
42
  private
43
43
 
44
44
  def instrument(args)
45
- instrumentation.instrument("add.subscriptions.rails_event_store", args) do
45
+ instrumentation.instrument("add.subscriptions.ruby_event_store", args) do
46
46
  unsubscribe = yield
47
- -> { instrumentation.instrument("remove.subscriptions.rails_event_store", args) { unsubscribe.call } }
47
+ -> { instrumentation.instrument("remove.subscriptions.ruby_event_store", args) { unsubscribe.call } }
48
48
  end
49
49
  end
50
50
 
@@ -3,18 +3,8 @@
3
3
  module RubyEventStore
4
4
  module Mappers
5
5
  class Default < PipelineMapper
6
- def initialize(events_class_remapping: {})
7
- if events_class_remapping.any?
8
- Deprecations.warn(:events_class_remapping_option)
9
- super(
10
- Pipeline.new(
11
- Transformation::EventClassRemapper.new(events_class_remapping),
12
- Transformation::SymbolizeMetadataKeys.new,
13
- ),
14
- )
15
- else
16
- super(Pipeline.new(Transformation::SymbolizeMetadataKeys.new))
17
- end
6
+ def initialize
7
+ super(Pipeline.new(Transformation::SymbolizeMetadataKeys.new))
18
8
  end
19
9
  end
20
10
  end
@@ -10,35 +10,19 @@ module RubyEventStore
10
10
 
11
11
  def events_to_records(events)
12
12
  instrumentation.instrument("events_to_records.mapper.ruby_event_store", domain_events: events) do
13
- deprecated_instrument("events_to_records.mapper.rails_event_store", domain_events: events) do
14
- mapper.events_to_records(events)
15
- end
13
+ mapper.events_to_records(events)
16
14
  end
17
15
  end
18
16
 
19
17
  def records_to_events(records)
20
18
  instrumentation.instrument("records_to_events.mapper.ruby_event_store", records: records) do
21
- deprecated_instrument("records_to_events.mapper.rails_event_store", records: records) do
22
- mapper.records_to_events(records)
23
- end
19
+ mapper.records_to_events(records)
24
20
  end
25
21
  end
26
22
 
27
23
  private
28
24
 
29
25
  attr_reader :instrumentation, :mapper
30
-
31
- def deprecated_instrument(name, payload, &block)
32
- canonical_name = name.sub("rails_event_store", "ruby_event_store")
33
- old_listeners = instrumentation.notifier.all_listeners_for(name)
34
- new_listeners = instrumentation.notifier.all_listeners_for(canonical_name)
35
- if (old_listeners - new_listeners).any?
36
- Deprecations.warn(:instrumentation_renamed)
37
- instrumentation.instrument(name, payload, &block)
38
- else
39
- yield
40
- end
41
- end
42
26
  end
43
27
  end
44
28
  end
@@ -10,49 +10,19 @@ module RubyEventStore
10
10
 
11
11
  def event_to_record(event)
12
12
  instrumentation.instrument("event_to_record.mapper.ruby_event_store", event: event) do
13
- deprecated_instrument(
14
- "serialize.mapper.ruby_event_store",
15
- { domain_event: event },
16
- canonical: "event_to_record.mapper.ruby_event_store",
17
- key: :instrumented_mapper_serialize_deprecated,
18
- ) do
19
- deprecated_instrument("serialize.mapper.rails_event_store", { domain_event: event }) do
20
- mapper.event_to_record(event)
21
- end
22
- end
13
+ mapper.event_to_record(event)
23
14
  end
24
15
  end
25
16
 
26
17
  def record_to_event(record)
27
18
  instrumentation.instrument("record_to_event.mapper.ruby_event_store", record: record) do
28
- deprecated_instrument(
29
- "deserialize.mapper.ruby_event_store",
30
- { record: record },
31
- canonical: "record_to_event.mapper.ruby_event_store",
32
- key: :instrumented_mapper_serialize_deprecated,
33
- ) do
34
- deprecated_instrument("deserialize.mapper.rails_event_store", { record: record }) do
35
- mapper.record_to_event(record)
36
- end
37
- end
19
+ mapper.record_to_event(record)
38
20
  end
39
21
  end
40
22
 
41
23
  private
42
24
 
43
25
  attr_reader :instrumentation, :mapper
44
-
45
- def deprecated_instrument(name, payload, canonical: nil, key: :instrumentation_renamed, &block)
46
- canonical_name = canonical || name.sub("rails_event_store", "ruby_event_store")
47
- old_listeners = instrumentation.notifier.all_listeners_for(name)
48
- new_listeners = instrumentation.notifier.all_listeners_for(canonical_name)
49
- if (old_listeners - new_listeners).any?
50
- Deprecations.warn(key)
51
- instrumentation.instrument(name, payload, &block)
52
- else
53
- yield
54
- end
55
- end
56
26
  end
57
27
  end
58
28
  end
@@ -12,7 +12,12 @@ module RubyEventStore
12
12
  def call(record)
13
13
  identity = lambda { |r| r }
14
14
  new_record = @upcast_map.fetch(record.event_type, identity)[record]
15
- new_record.equal?(record) ? record : call(new_record)
15
+ return record if new_record.equal?(record)
16
+ if new_record.event_type == record.event_type
17
+ raise InvalidUpcast,
18
+ "Upcast for '#{record.event_type}' returned the same event_type. In order to upcast provide a new event_type (e.g. '#{record.event_type}_v2')."
19
+ end
20
+ call(new_record)
16
21
  end
17
22
  end
18
23
 
@@ -5,15 +5,15 @@ module RubyEventStore
5
5
  ANONYMOUS_CLASS = "#<Class:".freeze
6
6
  private_constant :ANONYMOUS_CLASS
7
7
 
8
- def initialize(initial_state = nil, _internal: false)
9
- Deprecations.warn(:projection_new_constructor) unless _internal
10
- @handlers = {}
11
- @init = -> { initial_state }
12
- @streams = []
13
- end
8
+ private_class_method :new
14
9
 
15
10
  def self.init(initial_state = nil)
16
- new(initial_state, _internal: true)
11
+ new(initial_state)
12
+ end
13
+
14
+ def initialize(initial_state)
15
+ @handlers = {}
16
+ @init = -> { initial_state }
17
17
  end
18
18
 
19
19
  def on(*event_klasses, &block)
@@ -28,61 +28,10 @@ module RubyEventStore
28
28
  self
29
29
  end
30
30
 
31
- def call(*scopes)
31
+ def call(scope)
32
32
  return initial_state if handled_events.empty?
33
33
 
34
- Deprecations.warn(:projection_multiple_scopes) if scopes.size > 1
35
-
36
- scopes.reduce(initial_state) { |state, scope| scope.of_type(handled_events).reduce(state, &method(:transition)) }
37
- end
38
-
39
- def self.from_stream(stream_or_streams)
40
- streams = Array(stream_or_streams)
41
- raise(ArgumentError, "At least one stream must be given") if streams.empty?
42
- projection = new(_internal: true)
43
- projection.instance_variable_set(:@streams, streams)
44
- projection
45
- end
46
-
47
- def self.from_all_streams
48
- new(_internal: true)
49
- end
50
-
51
- def init(handler)
52
- @init = handler
53
- self
54
- end
55
-
56
- def when(events, handler)
57
- Array(events).each do |event_klass|
58
- name = event_klass.to_s
59
- @handlers[name] = ->(state, event) do
60
- handler.call(state, event)
61
- state
62
- end
63
- end
64
- self
65
- end
66
-
67
- def run(event_store, start: nil, count: PAGE_SIZE)
68
- if @streams.any?
69
- raise ArgumentError, "Start must be an array with event ids" unless valid_start_for_streams?(start)
70
- scopes =
71
- @streams
72
- .zip(start || [])
73
- .map do |stream, start_event_id|
74
- scope = event_store.read.stream(stream).in_batches(count)
75
- scope = scope.from(start_event_id) if start_event_id
76
- scope
77
- end
78
- else
79
- raise ArgumentError, "Start must be valid event id" unless valid_start_for_all_streams?(start)
80
- scope = event_store.read.in_batches(count)
81
- scope = scope.from(start) if start
82
- scopes = [scope]
83
- end
84
-
85
- call(*scopes)
34
+ scope.of_type(handled_events).reduce(initial_state, &method(:transition))
86
35
  end
87
36
 
88
37
  private
@@ -98,15 +47,5 @@ module RubyEventStore
98
47
  def transition(state, event)
99
48
  @handlers.fetch(event.event_type).call(state, event)
100
49
  end
101
-
102
- def valid_start_for_streams?(start)
103
- return true unless start
104
- start.instance_of?(Array) && start.size == @streams.size
105
- end
106
-
107
- def valid_start_for_all_streams?(start)
108
- return true unless start
109
- start.instance_of?(String)
110
- end
111
50
  end
112
51
  end
@@ -1,41 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RubyEventStore
4
- class Record
5
- StringsRequired = Class.new(StandardError)
4
+ Record = Data.define(:event_id, :data, :metadata, :event_type, :timestamp, :valid_at) do
6
5
  def initialize(event_id:, data:, metadata:, event_type:, timestamp:, valid_at:)
7
6
  raise StringsRequired unless [event_id, event_type].all? { |v| v.instance_of?(String) }
8
- @event_id = event_id
9
- @data = data
10
- @metadata = metadata
11
- @event_type = event_type
12
- @timestamp = timestamp
13
- @valid_at = valid_at
14
7
  @serialized_records = {}
15
- freeze
16
- end
17
-
18
- attr_reader :event_id, :data, :metadata, :event_type, :timestamp, :valid_at
19
-
20
- def hash
21
- [event_id, data, metadata, event_type, timestamp, valid_at].hash ^ self.class.hash
22
- end
23
-
24
- def ==(other)
25
- other.instance_of?(self.class) && other.event_id.eql?(event_id) && other.data.eql?(data) &&
26
- other.metadata.eql?(metadata) && other.event_type.eql?(event_type) && other.timestamp.eql?(timestamp) &&
27
- other.valid_at.eql?(valid_at)
28
- end
29
-
30
- def to_h
31
- {
32
- event_id: event_id,
33
- data: data,
34
- metadata: metadata,
35
- event_type: event_type,
36
- timestamp: timestamp,
37
- valid_at: valid_at,
38
- }
8
+ super
39
9
  end
40
10
 
41
11
  def serialize(serializer)
@@ -48,7 +18,6 @@ module RubyEventStore
48
18
  valid_at: valid_at.iso8601(TIMESTAMP_PRECISION),
49
19
  )
50
20
  end
51
-
52
- alias_method :eql?, :==
53
21
  end
22
+ Record::StringsRequired = StringsRequired
54
23
  end
@@ -1,40 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RubyEventStore
4
- class SerializedRecord
5
- StringsRequired = Class.new(StandardError)
4
+ SerializedRecord = Data.define(:event_id, :data, :metadata, :event_type, :timestamp, :valid_at) do
6
5
  def initialize(event_id:, data:, metadata:, event_type:, timestamp:, valid_at:)
7
6
  raise StringsRequired unless [event_id, event_type].all? { |v| v.instance_of?(String) }
8
- @event_id = event_id
9
- @data = data
10
- @metadata = metadata
11
- @event_type = event_type
12
- @timestamp = timestamp
13
- @valid_at = valid_at
14
- freeze
15
- end
16
-
17
- attr_reader :event_id, :data, :metadata, :event_type, :timestamp, :valid_at
18
-
19
- def hash
20
- [event_id, data, metadata, event_type, timestamp, valid_at].hash ^ self.class.hash
21
- end
22
-
23
- def ==(other)
24
- other.instance_of?(self.class) && other.event_id.eql?(event_id) && other.data.eql?(data) &&
25
- other.metadata.eql?(metadata) && other.event_type.eql?(event_type) && other.timestamp.eql?(timestamp) &&
26
- other.valid_at.eql?(valid_at)
27
- end
28
-
29
- def to_h
30
- {
31
- event_id: event_id,
32
- data: data,
33
- metadata: metadata,
34
- event_type: event_type,
35
- timestamp: timestamp,
36
- valid_at: valid_at,
37
- }
7
+ super
38
8
  end
39
9
 
40
10
  def deserialize(serializer)
@@ -47,7 +17,6 @@ module RubyEventStore
47
17
  valid_at: Time.iso8601(valid_at),
48
18
  )
49
19
  end
50
-
51
- alias_method :eql?, :==
52
20
  end
21
+ SerializedRecord::StringsRequired = StringsRequired
53
22
  end
@@ -5,7 +5,7 @@ RSpec.shared_examples "broker" do |broker_klass|
5
5
  let(:record) { instance_double(::RubyEventStore::Record) }
6
6
  let(:handler) { HandlerClass.new }
7
7
  let(:subscriptions) { ::RubyEventStore::Subscriptions.new }
8
- let(:dispatcher) { ::RubyEventStore::Dispatcher.new }
8
+ let(:dispatcher) { ::RubyEventStore::SyncScheduler.new }
9
9
  let(:broker) { broker_klass.new(subscriptions: subscriptions, dispatcher: dispatcher) }
10
10
 
11
11
  specify "no dispatch when no subscriptions" do
@@ -56,7 +56,7 @@ RSpec.shared_examples "broker" do |broker_klass|
56
56
  allow(dispatcher).to receive(:verify).and_return(false)
57
57
  expect { broker.add_subscription(HandlerClass, []) }.to raise_error(
58
58
  RubyEventStore::InvalidHandler,
59
- /Handler HandlerClass is invalid for dispatcher .*Dispatcher/,
59
+ /Handler HandlerClass is invalid for dispatcher .*SyncScheduler/,
60
60
  )
61
61
  expect { broker.add_global_subscription(HandlerClass) }.to raise_error(
62
62
  RubyEventStore::InvalidHandler,
@@ -1309,6 +1309,19 @@ module RubyEventStore
1309
1309
  )
1310
1310
  end
1311
1311
 
1312
+ specify "limit applies to records matching the time filter, not before it" do
1313
+ event_1 = SRecord.new(event_id: "8a6f053e-3ce2-4c82-a55b-4d02c66ae6ea", timestamp: Time.utc(2020, 1, 1))
1314
+ event_2 = SRecord.new(event_id: "8cee1139-4f96-483a-a175-2b947283c3c7", timestamp: Time.utc(2020, 1, 2))
1315
+ event_3 = SRecord.new(event_id: "d345f86d-b903-4d78-803f-38990c078d9e", timestamp: Time.utc(2020, 1, 3))
1316
+ repository.append_to_stream([event_1, event_2, event_3], Stream.new("whatever"), version_any)
1317
+
1318
+ expect(
1319
+ repository.read(
1320
+ specification.stream("whatever").backward.older_than_or_equal(Time.utc(2020, 1, 2)).limit(2).result,
1321
+ ).to_a,
1322
+ ).to eq([event_2, event_1])
1323
+ end
1324
+
1312
1325
  specify "fetching records older than or equal to specified date in stream" do
1313
1326
  event_1 = SRecord.new(event_id: "8a6f053e-3ce2-4c82-a55b-4d02c66ae6ea", timestamp: Time.utc(2020, 1, 1))
1314
1327
  event_2 = SRecord.new(event_id: "8cee1139-4f96-483a-a175-2b947283c3c7", timestamp: Time.utc(2020, 1, 2))
@@ -1578,6 +1591,35 @@ module RubyEventStore
1578
1591
  )
1579
1592
  end
1580
1593
 
1594
+ specify "named stream order is respected also when reading backward" do
1595
+ repository.append_to_stream(
1596
+ records = [
1597
+ RubyEventStore::SRecord.new(timestamp: with_precision(Time.new(2023, 1, 1, 12, 29, 0))),
1598
+ RubyEventStore::SRecord.new(timestamp: with_precision(Time.new(2023, 1, 1, 12, 28, 0))),
1599
+ RubyEventStore::SRecord.new(timestamp: with_precision(Time.new(2023, 1, 1, 12, 27, 0))),
1600
+ RubyEventStore::SRecord.new(
1601
+ timestamp: with_precision(Time.new(2023, 1, 1, 12, 26, 0)),
1602
+ valid_at: with_precision(Time.new(2023, 1, 1, 12, 30, 0)),
1603
+ ),
1604
+ ],
1605
+ RubyEventStore::Stream.new("stream"),
1606
+ RubyEventStore::ExpectedVersion.any,
1607
+ )
1608
+
1609
+ expect(repository.read(specification.stream("stream").backward.result).to_a).to eq(
1610
+ [records[3], records[2], records[1], records[0]],
1611
+ )
1612
+ expect(repository.read(specification.stream("stream").as_at.backward.result).to_a).to eq(
1613
+ [records[0], records[1], records[2], records[3]],
1614
+ )
1615
+ expect(repository.read(specification.stream("stream").as_at.backward.limit(2).result).to_a).to eq(
1616
+ [records[0], records[1]],
1617
+ )
1618
+ expect(repository.read(specification.stream("stream").as_of.backward.result).to_a).to eq(
1619
+ [records[3], records[0], records[1], records[2]],
1620
+ )
1621
+ end
1622
+
1581
1623
  specify "reading last event sorted by valid_at" do
1582
1624
  repository.append_to_stream(
1583
1625
  records = [
@@ -245,10 +245,6 @@ module RubyEventStore
245
245
  )
246
246
  end
247
247
 
248
- def in_batches_of(batch_size = DEFAULT_BATCH_SIZE)
249
- in_batches(batch_size)
250
- end
251
-
252
248
  # Specifies that only first event should be read.
253
249
  # {https://railseventstore.org/docs/core-concepts/read Find out more}.
254
250
  #
@@ -292,10 +288,6 @@ module RubyEventStore
292
288
  Specification.new(reader, result.dup { |r| r.with_types = types.flatten })
293
289
  end
294
290
 
295
- def of_types(*types)
296
- of_type(*types)
297
- end
298
-
299
291
  # Limits the query to certain events by given even ids.
300
292
  # {https://railseventstore.org/docs/core-concepts/read Find out more}.
301
293
  #
@@ -3,24 +3,11 @@
3
3
  module RubyEventStore
4
4
  class SyncScheduler
5
5
  def call(subscriber, event, _)
6
- if Class === subscriber
7
- Deprecations.warn(:class_subscriber)
8
- subscriber = subscriber.new
9
- end
10
6
  subscriber.call(event)
11
7
  end
12
8
 
13
9
  def verify(subscriber)
14
- if Class === subscriber
15
- Deprecations.warn(:class_subscriber)
16
- begin
17
- subscriber.new.respond_to?(:call)
18
- rescue ArgumentError
19
- false
20
- end
21
- else
22
- subscriber.respond_to?(:call)
23
- end
10
+ subscriber.respond_to?(:call)
24
11
  end
25
12
  end
26
13
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RubyEventStore
4
- VERSION = "2.19.2"
4
+ VERSION = "3.1.0"
5
5
  end
@@ -2,7 +2,6 @@
2
2
 
3
3
  require_relative "ruby_event_store/deprecations"
4
4
  require_relative "ruby_event_store/sync_scheduler"
5
- require_relative "ruby_event_store/dispatcher"
6
5
  require_relative "ruby_event_store/subscriptions"
7
6
  require_relative "ruby_event_store/broker"
8
7
  require_relative "ruby_event_store/in_memory_repository"
@@ -25,7 +24,6 @@ require_relative "ruby_event_store/mappers/encryption_key"
25
24
  require_relative "ruby_event_store/mappers/in_memory_encryption_key_repository"
26
25
  require_relative "ruby_event_store/mappers/transformation/domain_event"
27
26
  require_relative "ruby_event_store/mappers/transformation/encryption"
28
- require_relative "ruby_event_store/mappers/transformation/event_class_remapper"
29
27
  require_relative "ruby_event_store/mappers/transformation/upcast"
30
28
  require_relative "ruby_event_store/mappers/transformation/stringify_metadata_keys"
31
29
  require_relative "ruby_event_store/mappers/transformation/symbolize_metadata_keys"
@@ -38,14 +36,11 @@ require_relative "ruby_event_store/mappers/forgotten_data"
38
36
  require_relative "ruby_event_store/mappers/encryption_mapper"
39
37
  require_relative "ruby_event_store/mappers/instrumented_mapper"
40
38
  require_relative "ruby_event_store/mappers/instrumented_batch_mapper"
41
- require_relative "ruby_event_store/mappers/json_mapper"
42
- require_relative "ruby_event_store/mappers/null_mapper"
43
39
  require_relative "ruby_event_store/serializers/yaml"
44
40
  require_relative "ruby_event_store/batch_enumerator"
45
41
  require_relative "ruby_event_store/correlated_commands"
46
42
  require_relative "ruby_event_store/link_by_metadata"
47
43
  require_relative "ruby_event_store/immediate_dispatcher"
48
- require_relative "ruby_event_store/immediate_async_dispatcher"
49
44
  require_relative "ruby_event_store/composed_dispatcher"
50
45
  require_relative "ruby_event_store/composed_broker"
51
46
  require_relative "ruby_event_store/version"
@@ -54,4 +49,3 @@ require_relative "ruby_event_store/instrumented_dispatcher"
54
49
  require_relative "ruby_event_store/instrumented_subscriptions"
55
50
  require_relative "ruby_event_store/instrumented_broker"
56
51
  require_relative "ruby_event_store/event_type_resolver"
57
- require_relative "ruby_event_store/deprecated"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_event_store
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.19.2
4
+ version: 3.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Arkency
@@ -47,14 +47,11 @@ files:
47
47
  - lib/ruby_event_store/composed_dispatcher.rb
48
48
  - lib/ruby_event_store/constants.rb
49
49
  - lib/ruby_event_store/correlated_commands.rb
50
- - lib/ruby_event_store/deprecated.rb
51
50
  - lib/ruby_event_store/deprecations.rb
52
- - lib/ruby_event_store/dispatcher.rb
53
51
  - lib/ruby_event_store/errors.rb
54
52
  - lib/ruby_event_store/event.rb
55
53
  - lib/ruby_event_store/event_type_resolver.rb
56
54
  - lib/ruby_event_store/expected_version.rb
57
- - lib/ruby_event_store/immediate_async_dispatcher.rb
58
55
  - lib/ruby_event_store/immediate_dispatcher.rb
59
56
  - lib/ruby_event_store/in_memory_repository.rb
60
57
  - lib/ruby_event_store/instrumented_broker.rb
@@ -70,13 +67,10 @@ files:
70
67
  - lib/ruby_event_store/mappers/in_memory_encryption_key_repository.rb
71
68
  - lib/ruby_event_store/mappers/instrumented_batch_mapper.rb
72
69
  - lib/ruby_event_store/mappers/instrumented_mapper.rb
73
- - lib/ruby_event_store/mappers/json_mapper.rb
74
- - lib/ruby_event_store/mappers/null_mapper.rb
75
70
  - lib/ruby_event_store/mappers/pipeline.rb
76
71
  - lib/ruby_event_store/mappers/pipeline_mapper.rb
77
72
  - lib/ruby_event_store/mappers/transformation/domain_event.rb
78
73
  - lib/ruby_event_store/mappers/transformation/encryption.rb
79
- - lib/ruby_event_store/mappers/transformation/event_class_remapper.rb
80
74
  - lib/ruby_event_store/mappers/transformation/preserve_types.rb
81
75
  - lib/ruby_event_store/mappers/transformation/stringify_metadata_keys.rb
82
76
  - lib/ruby_event_store/mappers/transformation/symbolize_metadata_keys.rb
@@ -118,14 +112,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
118
112
  requirements:
119
113
  - - ">="
120
114
  - !ruby/object:Gem::Version
121
- version: '2.7'
115
+ version: '3.3'
122
116
  required_rubygems_version: !ruby/object:Gem::Requirement
123
117
  requirements:
124
118
  - - ">="
125
119
  - !ruby/object:Gem::Version
126
120
  version: '0'
127
121
  requirements: []
128
- rubygems_version: 4.0.10
122
+ rubygems_version: 3.6.9
129
123
  specification_version: 4
130
124
  summary: Implementation of an event store in Ruby
131
125
  test_files: []
@@ -1,98 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RubyEventStore
4
- Deprecations.register(
5
- :dispatcher_renamed,
6
- "`RubyEventStore::Dispatcher` is deprecated and will be removed in the next major release.\n" \
7
- "Use `RubyEventStore::SyncScheduler` instead.",
8
- )
9
- Deprecations.deprecate(Dispatcher, :initialize, key: :dispatcher_renamed)
10
-
11
- Deprecations.register(
12
- :immediate_async_dispatcher_renamed,
13
- "`RubyEventStore::ImmediateAsyncDispatcher` is deprecated and will be removed in the next major release.\n" \
14
- "Use `RubyEventStore::ImmediateDispatcher` instead.",
15
- )
16
- Deprecations.deprecate(ImmediateAsyncDispatcher, :initialize, key: :immediate_async_dispatcher_renamed)
17
-
18
- Deprecations.register(
19
- :class_subscriber,
20
- "Passing a class as a subscriber is deprecated and will be removed in the next major release.\n" \
21
- "Pass an instance or lambda instead, e.g. subscribe(MyHandler.new, to: [MyEvent]).",
22
- )
23
-
24
- Deprecations.register(
25
- :null_mapper,
26
- "`RubyEventStore::Mappers::NullMapper` is deprecated and will be removed in the next major release.\n" \
27
- "Use `RubyEventStore::Mappers::Default.new` instead.",
28
- )
29
- Deprecations.deprecate(Mappers::NullMapper, :initialize, key: :null_mapper)
30
-
31
- Deprecations.register(
32
- :events_class_remapping_option,
33
- "`events_class_remapping` option in `RubyEventStore::Mappers::Default` is deprecated and will be removed in the next major release.\n" \
34
- "Use `RubyEventStore::Mappers::Transformation::Upcast` instead.",
35
- )
36
-
37
- Deprecations.register(
38
- :event_class_remapper,
39
- "`RubyEventStore::Mappers::Transformation::EventClassRemapper` is deprecated and will be removed in the next major release.\n" \
40
- "Use `RubyEventStore::Mappers::Transformation::Upcast` instead.",
41
- )
42
- Deprecations.deprecate(Mappers::Transformation::EventClassRemapper, :initialize, key: :event_class_remapper)
43
-
44
- Deprecations.register(
45
- :any_version_with_specific_position,
46
- "Mixing expected version :any and specific position (or :auto) is deprecated and will raise UnsupportedVersionAnyUsage in RubyEventStore 3.0.",
47
- )
48
-
49
- Deprecations.register(
50
- :projection_new_constructor,
51
- "RubyEventStore::Projection.new is deprecated and will be removed in the next major release.\n" \
52
- "Use Projection.init(initial_state) instead.",
53
- )
54
-
55
- Deprecations.register(
56
- :projection_multiple_scopes,
57
- "Passing multiple scopes to RubyEventStore::Projection#call is deprecated and will be removed in the next major release.\n" \
58
- "Use a single scope instead, e.g. call(event_store.read.stream(\"stream_name\")).",
59
- )
60
-
61
- Deprecations.register(
62
- :projection_old_api,
63
- "RubyEventStore::Projection from_stream/from_all_streams/init/when/run API is deprecated and will be removed in the next major release.\n" \
64
- "Use Projection.init(initial_state).on(EventClass) { |state, event| new_state }.call(scope) instead.",
65
- )
66
- Deprecations.deprecate_class_method(Projection, :from_stream, key: :projection_old_api)
67
- Deprecations.deprecate_class_method(Projection, :from_all_streams, key: :projection_old_api)
68
- Deprecations.deprecate(Projection, :init, key: :projection_old_api)
69
- Deprecations.deprecate(Projection, :when, key: :projection_old_api)
70
- Deprecations.deprecate(Projection, :run, key: :projection_old_api)
71
-
72
- Deprecations.register(
73
- :instrumentation_renamed,
74
- "Instrumentation event names *.rails_event_store are deprecated and will be removed in the next major release.\n" \
75
- "Use *.ruby_event_store instead.",
76
- )
77
-
78
- Deprecations.register(
79
- :instrumented_mapper_serialize_deprecated,
80
- "Instrumentation event names serialize.mapper.ruby_event_store and deserialize.mapper.ruby_event_store are deprecated and will be removed in the next major release.\n" \
81
- "Use event_to_record.mapper.ruby_event_store and record_to_event.mapper.ruby_event_store instead.\n" \
82
- "The domain_event: payload key in serialize.mapper.ruby_event_store has been renamed to event: in event_to_record.mapper.ruby_event_store.",
83
- )
84
-
85
- Deprecations.register(
86
- :specification_in_batches_of,
87
- "RubyEventStore::Specification#in_batches_of is deprecated and will be removed in the next major release.\n\n" \
88
- "Use #in_batches instead.",
89
- )
90
- Deprecations.deprecate(Specification, :in_batches_of, key: :specification_in_batches_of)
91
-
92
- Deprecations.register(
93
- :specification_of_types,
94
- "RubyEventStore::Specification#of_types is deprecated and will be removed in the next major release.\n\n" \
95
- "Use #of_type instead.",
96
- )
97
- Deprecations.deprecate(Specification, :of_types, key: :specification_of_types)
98
- end
@@ -1,6 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RubyEventStore
4
- class Dispatcher < SyncScheduler
5
- end
6
- end
@@ -1,6 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RubyEventStore
4
- class ImmediateAsyncDispatcher < ImmediateDispatcher
5
- end
6
- end
@@ -1,16 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RubyEventStore
4
- module Mappers
5
- class JSONMapper < Default
6
- def initialize(events_class_remapping: {})
7
- warn <<~EOW
8
- Please replace RubyEventStore::Mappers::JSONMapper with RubyEventStore::Mappers::Default
9
-
10
- They're now identical and the former will be removed in next major release.
11
- EOW
12
- super
13
- end
14
- end
15
- end
16
- end
@@ -1,11 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RubyEventStore
4
- module Mappers
5
- class NullMapper < PipelineMapper
6
- def initialize
7
- super(Pipeline.new)
8
- end
9
- end
10
- end
11
- end
@@ -1,32 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RubyEventStore
4
- module Mappers
5
- module Transformation
6
- class EventClassRemapper
7
- def initialize(class_map)
8
- @class_map = class_map
9
- end
10
-
11
- def dump(record)
12
- record
13
- end
14
-
15
- def load(record)
16
- Record.new(
17
- event_id: record.event_id,
18
- event_type: class_map[record.event_type] || record.event_type,
19
- data: record.data,
20
- metadata: record.metadata,
21
- timestamp: record.timestamp,
22
- valid_at: record.valid_at,
23
- )
24
- end
25
-
26
- private
27
-
28
- attr_reader :class_map
29
- end
30
- end
31
- end
32
- end