ruby_event_store 1.3.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/.mutant.yml +1 -0
  3. data/Gemfile +2 -4
  4. data/Gemfile.lock +118 -0
  5. data/Makefile +13 -3
  6. data/lib/ruby_event_store/broker.rb +3 -3
  7. data/lib/ruby_event_store/client.rb +47 -23
  8. data/lib/ruby_event_store/composed_dispatcher.rb +2 -2
  9. data/lib/ruby_event_store/constants.rb +1 -0
  10. data/lib/ruby_event_store/errors.rb +0 -1
  11. data/lib/ruby_event_store/event.rb +8 -1
  12. data/lib/ruby_event_store/immediate_async_dispatcher.rb +2 -2
  13. data/lib/ruby_event_store/in_memory_repository.rb +98 -59
  14. data/lib/ruby_event_store/instrumented_dispatcher.rb +2 -2
  15. data/lib/ruby_event_store/mappers/default.rb +28 -6
  16. data/lib/ruby_event_store/mappers/deprecated_wrapper.rb +33 -0
  17. data/lib/ruby_event_store/mappers/encryption_mapper.rb +1 -4
  18. data/lib/ruby_event_store/mappers/instrumented_mapper.rb +8 -4
  19. data/lib/ruby_event_store/mappers/json_mapper.rb +2 -4
  20. data/lib/ruby_event_store/mappers/pipeline.rb +26 -5
  21. data/lib/ruby_event_store/mappers/pipeline_mapper.rb +6 -2
  22. data/lib/ruby_event_store/mappers/transformation/domain_event.rb +16 -8
  23. data/lib/ruby_event_store/mappers/transformation/encryption.rb +20 -12
  24. data/lib/ruby_event_store/mappers/transformation/event_class_remapper.rb +11 -4
  25. data/lib/ruby_event_store/mappers/transformation/serialization.rb +16 -14
  26. data/lib/ruby_event_store/mappers/transformation/stringify_metadata_keys.rb +12 -7
  27. data/lib/ruby_event_store/mappers/transformation/symbolize_metadata_keys.rb +12 -7
  28. data/lib/ruby_event_store/null.rb +13 -0
  29. data/lib/ruby_event_store/projection.rb +2 -13
  30. data/lib/ruby_event_store/record.rb +68 -0
  31. data/lib/ruby_event_store/serialized_record.rb +23 -4
  32. data/lib/ruby_event_store/spec/broker_lint.rb +9 -9
  33. data/lib/ruby_event_store/spec/event_repository_lint.rb +200 -36
  34. data/lib/ruby_event_store/spec/mapper_lint.rb +6 -6
  35. data/lib/ruby_event_store/spec/subscriptions_lint.rb +6 -0
  36. data/lib/ruby_event_store/specification.rb +100 -7
  37. data/lib/ruby_event_store/specification_reader.rb +2 -2
  38. data/lib/ruby_event_store/specification_result.rb +86 -2
  39. data/lib/ruby_event_store/version.rb +1 -1
  40. data/lib/ruby_event_store.rb +4 -7
  41. data/ruby_event_store.gemspec +0 -2
  42. metadata +8 -9
  43. data/lib/ruby_event_store/mappers/protobuf.rb +0 -24
  44. data/lib/ruby_event_store/mappers/transformation/item.rb +0 -56
  45. data/lib/ruby_event_store/mappers/transformation/proto_event.rb +0 -17
  46. data/lib/ruby_event_store/mappers/transformation/protobuf_encoder.rb +0 -30
  47. data/lib/ruby_event_store/mappers/transformation/protobuf_nested_struct_metadata.rb +0 -30
  48. data/lib/ruby_event_store/mappers/transformation/serialized_record.rb +0 -27
@@ -7,9 +7,9 @@ module RubyEventStore
7
7
  @instrumentation = instrumentation
8
8
  end
9
9
 
10
- def call(subscriber, event, serialized_event)
10
+ def call(subscriber, event, record)
11
11
  instrumentation.instrument("call.dispatcher.rails_event_store", event: event, subscriber: subscriber) do
12
- dispatcher.call(subscriber, event, serialized_event)
12
+ dispatcher.call(subscriber, event, record)
13
13
  end
14
14
  end
15
15
 
@@ -5,13 +5,35 @@ require 'yaml'
5
5
  module RubyEventStore
6
6
  module Mappers
7
7
  class Default < PipelineMapper
8
- def initialize(serializer: YAML, events_class_remapping: {})
8
+ UNSET = Object.new.freeze
9
+
10
+ attr_reader :serializer
11
+
12
+ def initialize(serializer: UNSET, events_class_remapping: {})
13
+ case serializer
14
+ when UNSET
15
+ @serializer = YAML
16
+ else
17
+ warn <<~EOW
18
+ Passing serializer: to #{self.class} has been deprecated.
19
+
20
+ Pass it directly to the repository and the scheduler. For example:
21
+
22
+ Rails.configuration.event_store = RailsEventStore::Client.new(
23
+ mapper: RubyEventStore::Mappers::Default.new,
24
+ repository: RailsEventStoreActiveRecord::EventRepository.new(serializer: #{serializer}),
25
+ dispatcher: RubyEventStore::ComposedDispatcher.new(
26
+ RailsEventStore::AfterCommitAsyncDispatcher.new(scheduler: RailsEventStore::ActiveJobScheduler.new(serializer: #{serializer}),
27
+ RubyEventStore::Dispatcher.new
28
+ )
29
+ )
30
+ EOW
31
+ @serializer = serializer
32
+ end
33
+
9
34
  super(Pipeline.new(
10
- transformations: [
11
- Transformation::EventClassRemapper.new(events_class_remapping),
12
- Transformation::SymbolizeMetadataKeys.new,
13
- Transformation::Serialization.new(serializer: serializer),
14
- ]
35
+ Transformation::EventClassRemapper.new(events_class_remapping),
36
+ Transformation::SymbolizeMetadataKeys.new,
15
37
  ))
16
38
  end
17
39
  end
@@ -0,0 +1,33 @@
1
+ module RubyEventStore
2
+ module Mappers
3
+ class DeprecatedWrapper
4
+ def initialize(mapper)
5
+ @mapper = mapper
6
+ end
7
+
8
+ def serializer
9
+ @mapper.serializer
10
+ end
11
+
12
+ def event_to_record(any)
13
+ @mapper.event_to_record(any)
14
+ rescue NoMethodError => e
15
+ raise unless e.message =~ /undefined method `event_to_record/
16
+ warn <<~EOW
17
+ Deprecation: Please rename #{@mapper.class}#event_to_serialized_record to #{@mapper.class}#event_to_record.
18
+ EOW
19
+ @mapper.event_to_serialized_record(any)
20
+ end
21
+
22
+ def record_to_event(any)
23
+ @mapper.record_to_event(any)
24
+ rescue NoMethodError => e
25
+ raise unless e.message =~ /undefined method `record_to_event/
26
+ warn <<~EOW
27
+ Deprecation: Please rename #{@mapper.class}#serialized_record_to_event to #{@mapper.class}#record_to_event.
28
+ EOW
29
+ @mapper.serialized_record_to_event(any)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -5,10 +5,7 @@ module RubyEventStore
5
5
  class EncryptionMapper < PipelineMapper
6
6
  def initialize(key_repository, serializer: YAML, forgotten_data: ForgottenData.new)
7
7
  super(Pipeline.new(
8
- transformations: [
9
- Transformation::Encryption.new(key_repository, serializer: serializer, forgotten_data: forgotten_data),
10
- Transformation::Serialization.new(serializer: serializer),
11
- ]
8
+ Transformation::Encryption.new(key_repository, serializer: serializer, forgotten_data: forgotten_data),
12
9
  ))
13
10
  end
14
11
  end
@@ -8,18 +8,22 @@ module RubyEventStore
8
8
  @instrumentation = instrumentation
9
9
  end
10
10
 
11
- def event_to_serialized_record(domain_event)
11
+ def event_to_record(domain_event)
12
12
  instrumentation.instrument("serialize.mapper.rails_event_store", domain_event: domain_event) do
13
- mapper.event_to_serialized_record(domain_event)
13
+ mapper.event_to_record(domain_event)
14
14
  end
15
15
  end
16
16
 
17
- def serialized_record_to_event(record)
17
+ def record_to_event(record)
18
18
  instrumentation.instrument("deserialize.mapper.rails_event_store", record: record) do
19
- mapper.serialized_record_to_event(record)
19
+ mapper.record_to_event(record)
20
20
  end
21
21
  end
22
22
 
23
+ def serializer
24
+ mapper.serializer
25
+ end
26
+
23
27
  private
24
28
 
25
29
  attr_reader :instrumentation, :mapper
@@ -5,10 +5,8 @@ module RubyEventStore
5
5
  class JSONMapper < PipelineMapper
6
6
  def initialize(events_class_remapping: {})
7
7
  super(Pipeline.new(
8
- transformations: [
9
- Transformation::EventClassRemapper.new(events_class_remapping),
10
- Transformation::SymbolizeMetadataKeys.new,
11
- ],
8
+ Transformation::EventClassRemapper.new(events_class_remapping),
9
+ Transformation::SymbolizeMetadataKeys.new,
12
10
  ))
13
11
  end
14
12
  end
@@ -3,13 +3,13 @@
3
3
  module RubyEventStore
4
4
  module Mappers
5
5
  class Pipeline
6
- def initialize(to_domain_event: Transformation::DomainEvent.new,
7
- to_serialized_record: Transformation::SerializedRecord.new,
8
- transformations: nil)
6
+ UNSET = Object.new.freeze
7
+
8
+ def initialize(*transformations_, transformations: UNSET, to_domain_event: Transformation::DomainEvent.new)
9
9
  @transformations = [
10
10
  to_domain_event,
11
- Array(transformations),
12
- to_serialized_record
11
+ deprecated_transformations(transformations),
12
+ transformations_,
13
13
  ].flatten.freeze
14
14
  end
15
15
 
@@ -26,6 +26,27 @@ module RubyEventStore
26
26
  end
27
27
 
28
28
  attr_reader :transformations
29
+
30
+ private
31
+
32
+ def deprecated_transformations(transformations)
33
+ case transformations
34
+ when UNSET
35
+ []
36
+ else
37
+ warn <<~EOW
38
+ Passing transformations via keyword parameter is deprecated.
39
+ Please use positional arguments from now on.
40
+
41
+ Was:
42
+ RubyEventStore::Mappers::Pipeline.new(transformations: transformations)
43
+
44
+ Is now:
45
+ RubyEventStore::Mappers::Pipeline.new(*transformations)
46
+ EOW
47
+ transformations
48
+ end
49
+ end
29
50
  end
30
51
  end
31
52
  end
@@ -7,14 +7,18 @@ module RubyEventStore
7
7
  @pipeline = pipeline
8
8
  end
9
9
 
10
- def event_to_serialized_record(domain_event)
10
+ def event_to_record(domain_event)
11
11
  pipeline.dump(domain_event)
12
12
  end
13
13
 
14
- def serialized_record_to_event(record)
14
+ def record_to_event(record)
15
15
  pipeline.load(record)
16
16
  end
17
17
 
18
+ def serializer
19
+ NULL
20
+ end
21
+
18
22
  private
19
23
  attr_reader :pipeline
20
24
  end
@@ -5,19 +5,27 @@ module RubyEventStore
5
5
  module Transformation
6
6
  class DomainEvent
7
7
  def dump(domain_event)
8
- Item.new(
8
+ metadata = domain_event.metadata.to_h
9
+ timestamp = metadata.delete(:timestamp)
10
+ valid_at = metadata.delete(:valid_at)
11
+ Record.new(
9
12
  event_id: domain_event.event_id,
10
- metadata: domain_event.metadata.to_h,
13
+ metadata: metadata,
11
14
  data: domain_event.data,
12
- event_type: domain_event.event_type
15
+ event_type: domain_event.event_type,
16
+ timestamp: timestamp,
17
+ valid_at: valid_at,
13
18
  )
14
19
  end
15
20
 
16
- def load(item)
17
- Object.const_get(item.event_type).new(
18
- event_id: item.event_id,
19
- metadata: item.metadata,
20
- data: item.data
21
+ def load(record)
22
+ Object.const_get(record.event_type).new(
23
+ event_id: record.event_id,
24
+ metadata: record.metadata.merge(
25
+ timestamp: record.timestamp,
26
+ valid_at: record.valid_at,
27
+ ),
28
+ data: record.data,
21
29
  )
22
30
  end
23
31
  end
@@ -23,27 +23,35 @@ module RubyEventStore
23
23
  @forgotten_data = forgotten_data
24
24
  end
25
25
 
26
- def dump(item)
27
- data = item.data
28
- metadata = item.metadata.dup
29
- event_class = Object.const_get(item.event_type)
26
+ def dump(record)
27
+ data = record.data
28
+ metadata = record.metadata.dup
29
+ event_class = Object.const_get(record.event_type)
30
30
 
31
31
  crypto_description = encryption_metadata(data, encryption_schema(event_class))
32
32
  metadata[:encryption] = crypto_description unless crypto_description.empty?
33
33
 
34
- item.merge(
35
- data: encrypt_data(deep_dup(data), crypto_description),
36
- metadata: metadata
34
+ Record.new(
35
+ event_id: record.event_id,
36
+ event_type: record.event_type,
37
+ data: encrypt_data(deep_dup(data), crypto_description),
38
+ metadata: metadata,
39
+ timestamp: record.timestamp,
40
+ valid_at: record.valid_at,
37
41
  )
38
42
  end
39
43
 
40
- def load(item)
41
- metadata = item.metadata.dup
44
+ def load(record)
45
+ metadata = record.metadata.dup
42
46
  crypto_description = Hash(metadata.delete(:encryption))
43
47
 
44
- item.merge(
45
- data: decrypt_data(item.data, crypto_description),
46
- metadata: metadata
48
+ Record.new(
49
+ event_id: record.event_id,
50
+ event_type: record.event_type,
51
+ data: decrypt_data(record.data, crypto_description),
52
+ metadata: metadata,
53
+ timestamp: record.timestamp,
54
+ valid_at: record.valid_at,
47
55
  )
48
56
  end
49
57
 
@@ -8,12 +8,19 @@ module RubyEventStore
8
8
  @class_map = class_map
9
9
  end
10
10
 
11
- def dump(item)
12
- item
11
+ def dump(record)
12
+ record
13
13
  end
14
14
 
15
- def load(item)
16
- item.merge(event_type: class_map[item.fetch(:event_type)] || item.fetch(:event_type))
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
+ )
17
24
  end
18
25
 
19
26
  private
@@ -7,26 +7,28 @@ module RubyEventStore
7
7
  module Transformation
8
8
  class Serialization
9
9
  def initialize(serializer: YAML)
10
- @serializer = serializer
10
+ warn <<~EOW
11
+ #{self.class} has been deprecated and is effectively no-op. You should remove this transformation from your pipeline.
12
+
13
+ Instead, pass the serializer directly to the repository and the scheduler. For example:
14
+
15
+ Rails.configuration.event_store = RailsEventStore::Client.new(
16
+ mapper: RubyEventStore::Mappers::Default.new,
17
+ repository: RailsEventStoreActiveRecord::EventRepository.new(serializer: #{serializer}),
18
+ dispatcher: RubyEventStore::ComposedDispatcher.new(
19
+ RubyEventStore::ImmediateAsyncDispatcher.new(scheduler: ActiveJobScheduler.new(serializer: #{serializer}),
20
+ RubyEventStore::Dispatcher.new
21
+ )
22
+ )
23
+ EOW
11
24
  end
12
- attr_reader :serializer
13
25
 
14
26
  def dump(item)
15
- Item.new(
16
- event_id: item.event_id,
17
- metadata: serializer.dump(item.metadata),
18
- data: serializer.dump(item.data),
19
- event_type: item.event_type
20
- )
27
+ item
21
28
  end
22
29
 
23
30
  def load(item)
24
- Item.new(
25
- event_id: item.event_id,
26
- metadata: serializer.load(item.metadata),
27
- data: serializer.load(item.data),
28
- event_type: item.event_type
29
- )
31
+ item
30
32
  end
31
33
  end
32
34
  end
@@ -4,18 +4,23 @@ module RubyEventStore
4
4
  module Mappers
5
5
  module Transformation
6
6
  class StringifyMetadataKeys
7
- def dump(item)
8
- stringify(item)
7
+ def dump(record)
8
+ stringify(record)
9
9
  end
10
10
 
11
- def load(item)
12
- stringify(item)
11
+ def load(record)
12
+ stringify(record)
13
13
  end
14
14
 
15
15
  private
16
- def stringify(item)
17
- item.merge(
18
- metadata: TransformKeys.stringify(item.metadata),
16
+ def stringify(record)
17
+ Record.new(
18
+ event_id: record.event_id,
19
+ event_type: record.event_type,
20
+ data: record.data,
21
+ metadata: TransformKeys.stringify(record.metadata),
22
+ timestamp: record.timestamp,
23
+ valid_at: record.valid_at,
19
24
  )
20
25
  end
21
26
  end
@@ -4,18 +4,23 @@ module RubyEventStore
4
4
  module Mappers
5
5
  module Transformation
6
6
  class SymbolizeMetadataKeys
7
- def dump(item)
8
- symbolize(item)
7
+ def dump(record)
8
+ symbolize(record)
9
9
  end
10
10
 
11
- def load(item)
12
- symbolize(item)
11
+ def load(record)
12
+ symbolize(record)
13
13
  end
14
14
 
15
15
  private
16
- def symbolize(item)
17
- item.merge(
18
- metadata: TransformKeys.symbolize(item.metadata),
16
+ def symbolize(record)
17
+ Record.new(
18
+ event_id: record.event_id,
19
+ event_type: record.event_type,
20
+ data: record.data,
21
+ metadata: TransformKeys.symbolize(record.metadata),
22
+ timestamp: record.timestamp,
23
+ valid_at: record.valid_at,
19
24
  )
20
25
  end
21
26
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyEventStore
4
+ module NULL
5
+ def self.dump(value)
6
+ value
7
+ end
8
+
9
+ def self.load(value)
10
+ value
11
+ end
12
+ end
13
+ end