ruby_event_store 1.2.2 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -1
  3. data/lib/ruby_event_store.rb +3 -7
  4. data/lib/ruby_event_store/broker.rb +3 -3
  5. data/lib/ruby_event_store/client.rb +47 -23
  6. data/lib/ruby_event_store/composed_dispatcher.rb +2 -2
  7. data/lib/ruby_event_store/constants.rb +1 -0
  8. data/lib/ruby_event_store/errors.rb +0 -1
  9. data/lib/ruby_event_store/event.rb +8 -1
  10. data/lib/ruby_event_store/immediate_async_dispatcher.rb +2 -2
  11. data/lib/ruby_event_store/in_memory_repository.rb +98 -59
  12. data/lib/ruby_event_store/instrumented_dispatcher.rb +2 -2
  13. data/lib/ruby_event_store/instrumented_repository.rb +3 -3
  14. data/lib/ruby_event_store/mappers/default.rb +3 -8
  15. data/lib/ruby_event_store/mappers/encryption_mapper.rb +3 -4
  16. data/lib/ruby_event_store/mappers/instrumented_mapper.rb +4 -4
  17. data/lib/ruby_event_store/mappers/json_mapper.rb +7 -7
  18. data/lib/ruby_event_store/mappers/pipeline.rb +2 -5
  19. data/lib/ruby_event_store/mappers/pipeline_mapper.rb +2 -2
  20. data/lib/ruby_event_store/mappers/transformation/domain_event.rb +16 -8
  21. data/lib/ruby_event_store/mappers/transformation/encryption.rb +20 -12
  22. data/lib/ruby_event_store/mappers/transformation/event_class_remapper.rb +11 -4
  23. data/lib/ruby_event_store/mappers/transformation/stringify_metadata_keys.rb +12 -7
  24. data/lib/ruby_event_store/mappers/transformation/symbolize_metadata_keys.rb +12 -7
  25. data/lib/ruby_event_store/mappers/transformation/upcast.rb +37 -0
  26. data/lib/ruby_event_store/null.rb +13 -0
  27. data/lib/ruby_event_store/projection.rb +2 -1
  28. data/lib/ruby_event_store/record.rb +68 -0
  29. data/lib/ruby_event_store/serialized_record.rb +23 -4
  30. data/lib/ruby_event_store/spec/broker_lint.rb +9 -9
  31. data/lib/ruby_event_store/spec/event_repository_lint.rb +267 -105
  32. data/lib/ruby_event_store/spec/mapper_lint.rb +6 -6
  33. data/lib/ruby_event_store/spec/subscriptions_lint.rb +25 -0
  34. data/lib/ruby_event_store/specification.rb +100 -7
  35. data/lib/ruby_event_store/specification_reader.rb +2 -2
  36. data/lib/ruby_event_store/specification_result.rb +86 -2
  37. data/lib/ruby_event_store/subscriptions.rb +23 -9
  38. data/lib/ruby_event_store/transform_keys.rb +5 -5
  39. data/lib/ruby_event_store/version.rb +1 -1
  40. metadata +15 -21
  41. data/CHANGELOG.md +0 -93
  42. data/Gemfile +0 -11
  43. data/Makefile +0 -22
  44. data/lib/ruby_event_store/mappers/protobuf.rb +0 -24
  45. data/lib/ruby_event_store/mappers/transformation/item.rb +0 -56
  46. data/lib/ruby_event_store/mappers/transformation/proto_event.rb +0 -17
  47. data/lib/ruby_event_store/mappers/transformation/protobuf_encoder.rb +0 -30
  48. data/lib/ruby_event_store/mappers/transformation/protobuf_nested_struct_metadata.rb +0 -30
  49. data/lib/ruby_event_store/mappers/transformation/serialization.rb +0 -34
  50. data/lib/ruby_event_store/mappers/transformation/serialized_record.rb +0 -27
  51. data/ruby_event_store.gemspec +0 -29
@@ -1,17 +1,17 @@
1
1
  module RubyEventStore
2
- RSpec.shared_examples :mapper do |mapper, domain_event|
3
- specify "event_to_serialized_record returns instance of SerializedRecord" do
4
- record = mapper.event_to_serialized_record(domain_event)
2
+ ::RSpec.shared_examples :mapper do |mapper, domain_event|
3
+ specify "event_to_record returns instance of Record" do
4
+ record = mapper.event_to_record(domain_event)
5
5
 
6
- expect(record).to be_kind_of(SerializedRecord)
6
+ expect(record).to be_kind_of(Record)
7
7
  expect(record.event_id).to eq(domain_event.event_id)
8
8
  expect(record.event_type).to eq(domain_event.event_type)
9
9
  end
10
10
 
11
11
  specify "serialize and deserialize gives equal event" do
12
- record = mapper.event_to_serialized_record(domain_event)
12
+ record = mapper.event_to_record(domain_event)
13
13
 
14
- expect(mapper.serialized_record_to_event(record)).to eq(domain_event)
14
+ expect(mapper.record_to_event(record)).to eq(domain_event)
15
15
  end
16
16
  end
17
17
  end
@@ -39,10 +39,16 @@ RSpec.shared_examples :subscriptions do |subscriptions_class|
39
39
  subscriptions.add_thread_subscription(handler, [Test1DomainEvent, Test3DomainEvent])
40
40
  subscriptions.add_thread_subscription(another_handler, [Test2DomainEvent])
41
41
  subscriptions.add_thread_global_subscription(global_handler)
42
+ t = Thread.new do
43
+ subscriptions.add_thread_subscription(handler, [Test2DomainEvent])
44
+ subscriptions.add_thread_global_subscription(another_handler)
45
+ expect(subscriptions.all_for('Test2DomainEvent')).to eq([another_handler, handler])
46
+ end
42
47
 
43
48
  expect(subscriptions.all_for('Test1DomainEvent')).to eq([global_handler, handler])
44
49
  expect(subscriptions.all_for('Test2DomainEvent')).to eq([global_handler, another_handler])
45
50
  expect(subscriptions.all_for('Test3DomainEvent')).to eq([global_handler, handler])
51
+ t.join
46
52
  end
47
53
 
48
54
  it 'returns lambda as an output of global subscribe methods' do
@@ -108,4 +114,23 @@ RSpec.shared_examples :subscriptions do |subscriptions_class|
108
114
 
109
115
  expect(subscriptions.all_for('Test1DomainEvent')).to eq([handler, handler])
110
116
  end
117
+
118
+ it 'subscribes by type of event which is a class' do
119
+ handler = TestHandler.new
120
+ subscriptions.add_subscription(handler, [Test1DomainEvent])
121
+ subscriptions.add_thread_subscription(handler, [Test1DomainEvent])
122
+
123
+ expect(subscriptions.all_for('Test1DomainEvent')).to eq([handler, handler])
124
+ expect(subscriptions.all_for(Test1DomainEvent)).to eq([handler, handler])
125
+ end
126
+
127
+ it 'subscribes by type of event which is a class or string with custom type resolver' do
128
+ subscriptions = subscriptions_class.new(event_type_resolver: ->(type) { type.to_s.reverse })
129
+ handler = TestHandler.new
130
+ subscriptions.add_subscription(handler, [Test1DomainEvent])
131
+ subscriptions.add_thread_subscription(handler, ['Test1DomainEvent'])
132
+
133
+ expect(subscriptions.all_for('Test1DomainEvent')).to eq([handler, handler])
134
+ expect(subscriptions.all_for(Test1DomainEvent)).to eq([handler, handler])
135
+ end
111
136
  end
@@ -35,7 +35,7 @@ module RubyEventStore
35
35
  # Limits the query to events before or after another event.
36
36
  # {http://railseventstore.org/docs/read/ Find out more}.
37
37
  #
38
- # @param start [String] id of event to start reading from.
38
+ # @param stop [String] id of event to start reading from.
39
39
  # @return [Specification]
40
40
  def to(stop)
41
41
  raise InvalidPageStop if stop.nil? || stop.empty?
@@ -43,6 +43,99 @@ module RubyEventStore
43
43
  Specification.new(reader, result.dup { |r| r.stop = stop })
44
44
  end
45
45
 
46
+ # Limits the query to events that later than given time.
47
+ # {http://railseventstore.org/docs/read/ Find out more}.
48
+ #
49
+ # @param time [Time]
50
+ # @return [Specification]
51
+ def older_than(time)
52
+ raise ArgumentError unless time.respond_to?(:to_time)
53
+ Specification.new(
54
+ reader,
55
+ result.dup do |r|
56
+ r.older_than = time
57
+ r.older_than_or_equal = nil
58
+ end
59
+ )
60
+ end
61
+
62
+ # Limits the query to events that occurred on given time or later.
63
+ # {http://railseventstore.org/docs/read/ Find out more}.
64
+ #
65
+ # @param time [Time]
66
+ # @return [Specification]
67
+ def older_than_or_equal(time)
68
+ raise ArgumentError unless time.respond_to?(:to_time)
69
+ Specification.new(
70
+ reader,
71
+ result.dup do |r|
72
+ r.older_than = nil
73
+ r.older_than_or_equal = time
74
+ end
75
+ )
76
+ end
77
+
78
+ # Limits the query to events that occurred earlier than given time.
79
+ # {http://railseventstore.org/docs/read/ Find out more}.
80
+ #
81
+ # @param time [Time]
82
+ # @return [Specification]
83
+ def newer_than(time)
84
+ raise ArgumentError unless time.respond_to?(:to_time)
85
+ Specification.new(
86
+ reader,
87
+ result.dup do |r|
88
+ r.newer_than_or_equal = nil
89
+ r.newer_than = time
90
+ end
91
+ )
92
+ end
93
+
94
+ # Limits the query to events that occurred on given time or earlier.
95
+ # {http://railseventstore.org/docs/read/ Find out more}.
96
+ #
97
+ # @param time [Time]
98
+ # @return [Specification]
99
+ def newer_than_or_equal(time)
100
+ raise ArgumentError unless time.respond_to?(:to_time)
101
+ Specification.new(
102
+ reader,
103
+ result.dup do |r|
104
+ r.newer_than_or_equal = time
105
+ r.newer_than = nil
106
+ end
107
+ )
108
+ end
109
+
110
+ # Limits the query to events within given time range.
111
+ # {http://railseventstore.org/docs/read/ Find out more}.
112
+ #
113
+ # @param time_range [Range]
114
+ # @return [Specification]
115
+ def between(time_range)
116
+ if time_range.exclude_end?
117
+ newer_than_or_equal(time_range.first).older_than(time_range.last)
118
+ else
119
+ newer_than_or_equal(time_range.first).older_than_or_equal(time_range.last)
120
+ end
121
+ end
122
+
123
+ # Sets the order of time sorting using transaction time
124
+ # {http://railseventstore.org/docs/read/ Find out more}
125
+ #
126
+ # @return [Specification]
127
+ def as_at
128
+ Specification.new(reader, result.dup { |r| r.time_sort_by = :as_at})
129
+ end
130
+
131
+ # Sets the order of time sorting using validity time
132
+ # {http://railseventstore.org/docs/read/ Find out more}
133
+ #
134
+ # @return [Specification]
135
+ def as_of
136
+ Specification.new(reader, result.dup { |r| r.time_sort_by = :as_of })
137
+ end
138
+
46
139
  # Sets the order of reading events to ascending (forward from the start).
47
140
  # {http://railseventstore.org/docs/read/ Find out more}.
48
141
  #
@@ -73,7 +166,7 @@ module RubyEventStore
73
166
  # Yields each batch of records that was retrieved from the store.
74
167
  # {http://railseventstore.org/docs/read/ Find out more}.
75
168
  #
76
- # @yield [Array<Event, Proto>] batch of events
169
+ # @yield [Array<Event>] batch of events
77
170
  # @return [Enumerator, nil] Enumerator is returned when block not given
78
171
  def each_batch
79
172
  return to_enum(:each_batch) unless block_given?
@@ -87,7 +180,7 @@ module RubyEventStore
87
180
  # Yields events read from the store if block given. Otherwise, returns enumerable collection.
88
181
  # {http://railseventstore.org/docs/read/ Find out more}.
89
182
  #
90
- # @yield [Event, Proto] event
183
+ # @yield [Event] event
91
184
  # @return [Enumerator, nil] Enumerator is returned when block not given
92
185
  def each
93
186
  return to_enum unless block_given?
@@ -111,7 +204,7 @@ module RubyEventStore
111
204
  # built up to this point result using provided block.
112
205
  # {http://railseventstore.org/docs/read/ Find out more}.
113
206
  #
114
- # @accumulator starting state for reduce operation
207
+ # @param accumulator starting state for reduce operation
115
208
  # @return reduce result as defined by block given
116
209
  def reduce(accumulator = nil, &block)
117
210
  raise ArgumentError.new("Block must be given") unless block_given?
@@ -130,7 +223,7 @@ module RubyEventStore
130
223
  # Returns array of domain events.
131
224
  # {http://railseventstore.org/docs/read/ Find out more}.
132
225
  #
133
- # @return [Array<Event, Proto>]
226
+ # @return [Array<Event>]
134
227
  def to_a
135
228
  each.to_a
136
229
  end
@@ -200,7 +293,7 @@ module RubyEventStore
200
293
  # Limits the query to certain events by given even ids.
201
294
  # {http://railseventstore.org/docs/read/ Find out more}.
202
295
  #
203
- # @param even_ids [Array(String)] ids of event to look for.
296
+ # @param event_ids [Array(String)] ids of event to look for.
204
297
  # @return [Specification]
205
298
  def with_id(event_ids)
206
299
  Specification.new(reader, result.dup{ |r| r.with_ids = event_ids })
@@ -231,7 +324,7 @@ module RubyEventStore
231
324
  # read from the store if block given. Otherwise, returns enumerable collection.
232
325
  # {http://railseventstore.org/docs/read/ Find out more}.
233
326
  #
234
- # @yield [Event, Proto] event
327
+ # @yield [Event] event
235
328
  # @return [Enumerator] Enumerator is returned when block not given
236
329
  def events(event_ids)
237
330
  with_id(event_ids).each
@@ -14,14 +14,14 @@ module RubyEventStore
14
14
  # @private
15
15
  def one(specification_result)
16
16
  record = repository.read(specification_result)
17
- mapper.serialized_record_to_event(record) if record
17
+ mapper.record_to_event(record) if record
18
18
  end
19
19
 
20
20
  # @api private
21
21
  # @private
22
22
  def each(specification_result)
23
23
  repository.read(specification_result).each do |batch|
24
- yield batch.map { |serialized_record| mapper.serialized_record_to_event(serialized_record) }
24
+ yield batch.map { |record| mapper.record_to_event(record) }
25
25
  end
26
26
  end
27
27
 
@@ -5,14 +5,48 @@ module RubyEventStore
5
5
  def initialize(direction: :forward,
6
6
  start: nil,
7
7
  stop: nil,
8
+ older_than: nil,
9
+ older_than_or_equal: nil,
10
+ newer_than: nil,
11
+ newer_than_or_equal: nil,
12
+ time_sort_by: nil,
8
13
  count: nil,
9
14
  stream: Stream.new(GLOBAL_STREAM),
10
15
  read_as: :all,
11
16
  batch_size: Specification::DEFAULT_BATCH_SIZE,
12
17
  with_ids: nil,
13
18
  with_types: nil)
14
- @attributes = Struct.new(:direction, :start, :stop, :count, :stream, :read_as, :batch_size, :with_ids, :with_types)
15
- .new(direction, start, stop, count, stream, read_as, batch_size, with_ids, with_types)
19
+ @attributes = Struct.new(
20
+ :direction,
21
+ :start,
22
+ :stop,
23
+ :older_than,
24
+ :older_than_or_equal,
25
+ :newer_than,
26
+ :newer_than_or_equal,
27
+ :time_sort_by,
28
+ :count,
29
+ :stream,
30
+ :read_as,
31
+ :batch_size,
32
+ :with_ids,
33
+ :with_types
34
+ ).new(
35
+ direction,
36
+ start,
37
+ stop,
38
+ older_than,
39
+ older_than_or_equal,
40
+ newer_than,
41
+ newer_than_or_equal,
42
+ time_sort_by,
43
+ count,
44
+ stream,
45
+ read_as,
46
+ batch_size,
47
+ with_ids,
48
+ with_types
49
+ )
16
50
  freeze
17
51
  end
18
52
 
@@ -56,6 +90,46 @@ module RubyEventStore
56
90
  attributes.stop
57
91
  end
58
92
 
93
+ # Ending time.
94
+ # {http://railseventstore.org/docs/read/ Find out more}.
95
+ #
96
+ # @return [Time]
97
+ def older_than
98
+ attributes.older_than
99
+ end
100
+
101
+ # Ending time.
102
+ # {http://railseventstore.org/docs/read/ Find out more}.
103
+ #
104
+ # @return [Time]
105
+ def older_than_or_equal
106
+ attributes.older_than_or_equal
107
+ end
108
+
109
+ # Starting time.
110
+ # {http://railseventstore.org/docs/read/ Find out more}.
111
+ #
112
+ # @return [Time]
113
+ def newer_than
114
+ attributes.newer_than
115
+ end
116
+
117
+ # Starting time.
118
+ # {http://railseventstore.org/docs/read/ Find out more}.
119
+ #
120
+ # @return [Time]
121
+ def newer_than_or_equal
122
+ attributes.newer_than_or_equal
123
+ end
124
+
125
+ # Time sorting strategy. Nil when not specified.
126
+ # {http://railseventstore.org/docs/read/ Find out more}.
127
+ #
128
+ # @return [Symbol]
129
+ def time_sort_by
130
+ attributes.time_sort_by
131
+ end
132
+
59
133
  # Read direction. True is reading forward
60
134
  # {http://railseventstore.org/docs/read/ Find out more}.
61
135
  #
@@ -179,6 +253,11 @@ module RubyEventStore
179
253
  # * direction
180
254
  # * start
181
255
  # * stop
256
+ # * older_than
257
+ # * older_than_or_equal
258
+ # * newer_than
259
+ # * newer_than_or_equal
260
+ # * time_sort_by
182
261
  # * count
183
262
  # * stream
184
263
  # * read_as
@@ -193,6 +272,11 @@ module RubyEventStore
193
272
  get_direction,
194
273
  start,
195
274
  stop,
275
+ older_than,
276
+ older_than_or_equal,
277
+ newer_than,
278
+ newer_than_or_equal,
279
+ time_sort_by,
196
280
  limit,
197
281
  stream,
198
282
  attributes.read_as,
@@ -4,14 +4,15 @@ require 'concurrent'
4
4
 
5
5
  module RubyEventStore
6
6
  class Subscriptions
7
- def initialize
7
+ def initialize(event_type_resolver: default_event_type_resolver)
8
+ @event_type_resolver = event_type_resolver
8
9
  @local = LocalSubscriptions.new
9
10
  @global = GlobalSubscriptions.new
10
- @thread = ThreadSubscriptions.new
11
+ @thread = ThreadSubscriptions.new
11
12
  end
12
13
 
13
14
  def add_subscription(subscriber, event_types)
14
- local.add(subscriber, event_types)
15
+ local.add(subscriber, resolve_event_types(event_types))
15
16
  end
16
17
 
17
18
  def add_global_subscription(subscriber)
@@ -19,7 +20,7 @@ module RubyEventStore
19
20
  end
20
21
 
21
22
  def add_thread_subscription(subscriber, event_types)
22
- thread.local.add(subscriber, event_types)
23
+ thread.local.add(subscriber, resolve_event_types(event_types))
23
24
  end
24
25
 
25
26
  def add_thread_global_subscription(subscriber)
@@ -27,12 +28,25 @@ module RubyEventStore
27
28
  end
28
29
 
29
30
  def all_for(event_type)
30
- [local, global, thread].map{|r| r.all_for(event_type)}.reduce(&:+)
31
+ resolved_event_type = resolve_event_type(event_type)
32
+ [local, global, thread].map{|r| r.all_for(resolved_event_type)}.reduce(&:+)
31
33
  end
32
34
 
33
35
  private
34
36
  attr_reader :local, :global, :thread
35
37
 
38
+ def default_event_type_resolver
39
+ ->(value) { value.to_s }
40
+ end
41
+
42
+ def resolve_event_types(event_types)
43
+ event_types.map(&method(:resolve_event_type))
44
+ end
45
+
46
+ def resolve_event_type(type)
47
+ @event_type_resolver.call(type)
48
+ end
49
+
36
50
  class ThreadSubscriptions
37
51
  def initialize
38
52
  @local = ThreadLocalSubscriptions.new
@@ -51,8 +65,8 @@ module RubyEventStore
51
65
  end
52
66
 
53
67
  def add(subscription, event_types)
54
- event_types.each{ |type| @subscriptions[type.to_s] << subscription }
55
- ->() {event_types.each{ |type| @subscriptions.fetch(type.to_s).delete(subscription) } }
68
+ event_types.each{ |type| @subscriptions[type] << subscription }
69
+ ->() {event_types.each{ |type| @subscriptions.fetch(type).delete(subscription) } }
56
70
  end
57
71
 
58
72
  def all_for(event_type)
@@ -83,8 +97,8 @@ module RubyEventStore
83
97
  end
84
98
 
85
99
  def add(subscription, event_types)
86
- event_types.each{ |type| @subscriptions.value[type.to_s] << subscription }
87
- ->() {event_types.each{ |type| @subscriptions.value.fetch(type.to_s).delete(subscription) } }
100
+ event_types.each{ |type| @subscriptions.value[type] << subscription }
101
+ ->() {event_types.each{ |type| @subscriptions.value.fetch(type).delete(subscription) } }
88
102
  end
89
103
 
90
104
  def all_for(event_type)
@@ -4,23 +4,23 @@ module RubyEventStore
4
4
  class TransformKeys
5
5
  class << self
6
6
  def stringify(data)
7
- transform(data) {|k| k.to_s}
7
+ deep_transform(data, &:to_s)
8
8
  end
9
9
 
10
10
  def symbolize(data)
11
- transform(data) {|k| k.to_sym}
11
+ deep_transform(data, &:to_sym)
12
12
  end
13
13
 
14
14
  private
15
15
 
16
- def transform(data, &block)
16
+ def deep_transform(data, &block)
17
17
  data.each_with_object({}) do |(k, v), h|
18
18
  h[yield(k)] =
19
19
  case v
20
20
  when Hash
21
- transform(v, &block)
21
+ deep_transform(v, &block)
22
22
  when Array
23
- v.map{|i| Hash === i ? transform(i, &block) : i}
23
+ v.map{|i| Hash === i ? deep_transform(i, &block) : i}
24
24
  else
25
25
  v
26
26
  end