ruby_event_store 2.1.0 → 2.4.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 (46) hide show
  1. checksums.yaml +4 -4
  2. data/lib/ruby_event_store/batch_enumerator.rb +3 -3
  3. data/lib/ruby_event_store/broker.rb +5 -4
  4. data/lib/ruby_event_store/client.rb +81 -48
  5. data/lib/ruby_event_store/composed_dispatcher.rb +1 -3
  6. data/lib/ruby_event_store/correlated_commands.rb +4 -15
  7. data/lib/ruby_event_store/errors.rb +11 -10
  8. data/lib/ruby_event_store/event.rb +9 -14
  9. data/lib/ruby_event_store/expected_version.rb +3 -7
  10. data/lib/ruby_event_store/in_memory_repository.rb +100 -37
  11. data/lib/ruby_event_store/instrumented_dispatcher.rb +11 -2
  12. data/lib/ruby_event_store/instrumented_repository.rb +13 -8
  13. data/lib/ruby_event_store/link_by_metadata.rb +4 -21
  14. data/lib/ruby_event_store/mappers/default.rb +6 -4
  15. data/lib/ruby_event_store/mappers/encryption_key.rb +7 -16
  16. data/lib/ruby_event_store/mappers/encryption_mapper.rb +6 -6
  17. data/lib/ruby_event_store/mappers/forgotten_data.rb +1 -1
  18. data/lib/ruby_event_store/mappers/in_memory_encryption_key_repository.rb +1 -1
  19. data/lib/ruby_event_store/mappers/null_mapper.rb +0 -1
  20. data/lib/ruby_event_store/mappers/pipeline.rb +3 -10
  21. data/lib/ruby_event_store/mappers/pipeline_mapper.rb +1 -0
  22. data/lib/ruby_event_store/mappers/transformation/domain_event.rb +22 -12
  23. data/lib/ruby_event_store/mappers/transformation/encryption.rb +21 -25
  24. data/lib/ruby_event_store/mappers/transformation/event_class_remapper.rb +6 -5
  25. data/lib/ruby_event_store/mappers/transformation/stringify_metadata_keys.rb +6 -5
  26. data/lib/ruby_event_store/mappers/transformation/symbolize_metadata_keys.rb +6 -5
  27. data/lib/ruby_event_store/mappers/transformation/upcast.rb +2 -6
  28. data/lib/ruby_event_store/metadata.rb +46 -17
  29. data/lib/ruby_event_store/projection.rb +12 -20
  30. data/lib/ruby_event_store/record.rb +14 -26
  31. data/lib/ruby_event_store/serialized_record.rb +14 -26
  32. data/lib/ruby_event_store/serializers/yaml.rb +17 -0
  33. data/lib/ruby_event_store/spec/broker_lint.rb +38 -28
  34. data/lib/ruby_event_store/spec/event_lint.rb +10 -10
  35. data/lib/ruby_event_store/spec/event_repository_lint.rb +746 -730
  36. data/lib/ruby_event_store/spec/mapper_lint.rb +2 -2
  37. data/lib/ruby_event_store/spec/subscriptions_lint.rb +58 -68
  38. data/lib/ruby_event_store/specification.rb +20 -16
  39. data/lib/ruby_event_store/specification_reader.rb +2 -3
  40. data/lib/ruby_event_store/specification_result.rb +52 -46
  41. data/lib/ruby_event_store/stream.rb +3 -7
  42. data/lib/ruby_event_store/subscriptions.rb +17 -17
  43. data/lib/ruby_event_store/transform_keys.rb +1 -1
  44. data/lib/ruby_event_store/version.rb +1 -1
  45. data/lib/ruby_event_store.rb +44 -43
  46. metadata +6 -4
@@ -1,26 +1,49 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'ostruct'
3
+ require "ostruct"
4
4
  module RubyEventStore
5
5
  class InMemoryRepository
6
+ class UnsupportedVersionAnyUsage < StandardError
7
+ def initialize
8
+ super <<~EOS
9
+ Mixing expected version :any and specific position (or :auto) is unsupported.
10
+
11
+ Read more about expected versions here:
12
+ https://railseventstore.org/docs/v2/expected_version/
13
+ EOS
14
+ end
15
+ end
16
+
17
+ class EventInStream
18
+ def initialize(event_id, position)
19
+ @event_id = event_id
20
+ @position = position
21
+ end
22
+
23
+ attr_reader :event_id, :position
24
+ end
6
25
 
7
- def initialize(serializer: NULL)
26
+ def initialize(serializer: NULL, ensure_supported_any_usage: false)
8
27
  @serializer = serializer
9
28
  @streams = Hash.new { |h, k| h[k] = Array.new }
10
- @mutex = Mutex.new
29
+ @mutex = Mutex.new
11
30
  @storage = Hash.new
31
+ @ensure_supported_any_usage = ensure_supported_any_usage
12
32
  end
13
33
 
14
34
  def append_to_stream(records, stream, expected_version)
15
35
  serialized_records = records.map { |record| record.serialize(serializer) }
16
36
 
17
37
  with_synchronize(expected_version, stream) do |resolved_version|
18
- raise WrongExpectedEventVersion unless last_stream_version(stream).equal?(resolved_version)
38
+ ensure_supported_any_usage(resolved_version, stream)
39
+ unless resolved_version.nil? || last_stream_version(stream).equal?(resolved_version)
40
+ raise WrongExpectedEventVersion
41
+ end
19
42
 
20
- serialized_records.each do |serialized_record|
43
+ serialized_records.each_with_index do |serialized_record, index|
21
44
  raise EventDuplicatedInStream if has_event?(serialized_record.event_id)
22
45
  storage[serialized_record.event_id] = serialized_record
23
- streams[stream.name] << serialized_record.event_id
46
+ add_to_stream(stream, serialized_record, resolved_version, index)
24
47
  end
25
48
  end
26
49
  self
@@ -30,11 +53,14 @@ module RubyEventStore
30
53
  serialized_records = event_ids.map { |id| read_event(id) }
31
54
 
32
55
  with_synchronize(expected_version, stream) do |resolved_version|
33
- raise WrongExpectedEventVersion unless last_stream_version(stream).equal?(resolved_version)
56
+ ensure_supported_any_usage(resolved_version, stream)
57
+ unless resolved_version.nil? || last_stream_version(stream).equal?(resolved_version)
58
+ raise WrongExpectedEventVersion
59
+ end
34
60
 
35
- serialized_records.each do |serialized_record|
61
+ serialized_records.each_with_index do |serialized_record, index|
36
62
  raise EventDuplicatedInStream if has_event_in_stream?(serialized_record.event_id, stream.name)
37
- streams[stream.name] << serialized_record.event_id
63
+ add_to_stream(stream, serialized_record, resolved_version, index)
38
64
  end
39
65
  end
40
66
  self
@@ -69,9 +95,7 @@ module RubyEventStore
69
95
  serialized_records.last&.deserialize(serializer)
70
96
  else
71
97
  Enumerator.new do |y|
72
- serialized_records.each do |serialized_record|
73
- y << serialized_record.deserialize(serializer)
74
- end
98
+ serialized_records.each { |serialized_record| y << serialized_record.deserialize(serializer) }
75
99
  end
76
100
  end
77
101
  end
@@ -84,38 +108,61 @@ module RubyEventStore
84
108
  records.each do |record|
85
109
  read_event(record.event_id)
86
110
  serialized_record =
87
- Record.new(
88
- event_id: record.event_id,
89
- event_type: record.event_type,
90
- data: record.data,
91
- metadata: record.metadata,
92
- timestamp: Time.iso8601(storage.fetch(record.event_id).timestamp),
93
- valid_at: record.valid_at,
94
- ).serialize(serializer)
111
+ Record
112
+ .new(
113
+ event_id: record.event_id,
114
+ event_type: record.event_type,
115
+ data: record.data,
116
+ metadata: record.metadata,
117
+ timestamp: Time.iso8601(storage.fetch(record.event_id).timestamp),
118
+ valid_at: record.valid_at
119
+ )
120
+ .serialize(serializer)
95
121
  storage[record.event_id] = serialized_record
96
122
  end
97
123
  end
98
124
 
99
125
  def streams_of(event_id)
100
- streams
101
- .select { |name,| has_event_in_stream?(event_id, name) }
102
- .map { |name,| Stream.new(name) }
126
+ streams.select { |name,| has_event_in_stream?(event_id, name) }.map { |name,| Stream.new(name) }
127
+ end
128
+
129
+ def position_in_stream(event_id, stream)
130
+ event_in_stream = streams[stream.name].find { |event_in_stream| event_in_stream.event_id.eql?(event_id) }
131
+ raise EventNotFoundInStream if event_in_stream.nil?
132
+ event_in_stream.position
133
+ end
134
+
135
+ def global_position(event_id)
136
+ storage.keys.index(event_id) or raise EventNotFound.new(event_id)
137
+ end
138
+
139
+ def event_in_stream?(event_id, stream)
140
+ !streams[stream.name].find { |event_in_stream| event_in_stream.event_id.eql?(event_id) }.nil?
103
141
  end
104
142
 
105
143
  private
144
+
106
145
  def read_scope(spec)
107
146
  serialized_records = serialized_records_of_stream(spec.stream)
108
147
  serialized_records = ordered(serialized_records, spec)
109
- serialized_records = serialized_records.select{|e| spec.with_ids.any?{|x| x.eql?(e.event_id)}} if spec.with_ids?
110
- serialized_records = serialized_records.select{|e| spec.with_types.any?{|x| x.eql?(e.event_type)}} if spec.with_types?
148
+ serialized_records = serialized_records.select { |e| spec.with_ids.any? { |x| x.eql?(e.event_id) } } if spec
149
+ .with_ids?
150
+ serialized_records = serialized_records.select { |e| spec.with_types.any? { |x| x.eql?(e.event_type) } } if spec
151
+ .with_types?
111
152
  serialized_records = serialized_records.reverse if spec.backward?
112
153
  serialized_records = serialized_records.drop(index_of(serialized_records, spec.start) + 1) if spec.start
113
154
  serialized_records = serialized_records.take(index_of(serialized_records, spec.stop)) if spec.stop
114
155
  serialized_records = serialized_records.take(spec.limit) if spec.limit?
115
- serialized_records = serialized_records.select { |sr| Time.iso8601(sr.timestamp) < spec.older_than } if spec.older_than
116
- serialized_records = serialized_records.select { |sr| Time.iso8601(sr.timestamp) <= spec.older_than_or_equal } if spec.older_than_or_equal
117
- serialized_records = serialized_records.select { |sr| Time.iso8601(sr.timestamp) > spec.newer_than } if spec.newer_than
118
- serialized_records = serialized_records.select { |sr| Time.iso8601(sr.timestamp) >= spec.newer_than_or_equal } if spec.newer_than_or_equal
156
+ serialized_records = serialized_records.select { |sr| Time.iso8601(sr.timestamp) < spec.older_than } if spec
157
+ .older_than
158
+ serialized_records =
159
+ serialized_records.select { |sr| Time.iso8601(sr.timestamp) <= spec.older_than_or_equal } if spec
160
+ .older_than_or_equal
161
+ serialized_records = serialized_records.select { |sr| Time.iso8601(sr.timestamp) > spec.newer_than } if spec
162
+ .newer_than
163
+ serialized_records =
164
+ serialized_records.select { |sr| Time.iso8601(sr.timestamp) >= spec.newer_than_or_equal } if spec
165
+ .newer_than_or_equal
119
166
  serialized_records
120
167
  end
121
168
 
@@ -124,7 +171,7 @@ module RubyEventStore
124
171
  end
125
172
 
126
173
  def event_ids_of_stream(stream)
127
- streams.fetch(stream.name, Array.new)
174
+ streams.fetch(stream.name, Array.new).map(&:event_id)
128
175
  end
129
176
 
130
177
  def serialized_records_of_stream(stream)
@@ -143,7 +190,7 @@ module RubyEventStore
143
190
  end
144
191
 
145
192
  def last_stream_version(stream)
146
- event_ids_of_stream(stream).size - 1
193
+ streams.fetch(stream.name, Array.new).size - 1
147
194
  end
148
195
 
149
196
  def with_synchronize(expected_version, stream, &block)
@@ -157,18 +204,34 @@ module RubyEventStore
157
204
  # conditions more likely. And we only use mutex.synchronize for writing
158
205
  # not for the whole read+write algorithm.
159
206
  Thread.pass
160
- mutex.synchronize do
161
- resolved_version = last_stream_version(stream) if expected_version.any?
162
- block.call(resolved_version)
163
- end
207
+ mutex.synchronize { block.call(resolved_version) }
164
208
  end
165
209
 
166
210
  def has_event_in_stream?(event_id, stream_name)
167
- streams.fetch(stream_name, Array.new).any? { |id| id.eql?(event_id) }
211
+ streams.fetch(stream_name, Array.new).any? { |event_in_stream| event_in_stream.event_id.eql?(event_id) }
168
212
  end
169
213
 
170
214
  def index_of(source, event_id)
171
- source.index {|item| item.event_id.eql?(event_id)}
215
+ source.index { |item| item.event_id.eql?(event_id) }
216
+ end
217
+
218
+ def compute_position(resolved_version, index)
219
+ resolved_version + index + 1 unless resolved_version.nil?
220
+ end
221
+
222
+ def add_to_stream(stream, serialized_record, resolved_version, index)
223
+ streams[stream.name] << EventInStream.new(serialized_record.event_id, compute_position(resolved_version, index))
224
+ end
225
+
226
+ def ensure_supported_any_usage(resolved_version, stream)
227
+ if @ensure_supported_any_usage
228
+ stream_positions = streams.fetch(stream.name, Array.new).map(&:position)
229
+ if resolved_version.nil?
230
+ raise UnsupportedVersionAnyUsage if !stream_positions.compact.empty?
231
+ else
232
+ raise UnsupportedVersionAnyUsage if stream_positions.include?(nil)
233
+ end
234
+ end
172
235
  end
173
236
 
174
237
  attr_reader :streams, :mutex, :storage, :serializer
@@ -13,11 +13,20 @@ module RubyEventStore
13
13
  end
14
14
  end
15
15
 
16
- def verify(subscriber)
17
- dispatcher.verify(subscriber)
16
+ def method_missing(method_name, *arguments, **keyword_arguments, &block)
17
+ if respond_to?(method_name)
18
+ dispatcher.public_send(method_name, *arguments, **keyword_arguments, &block)
19
+ else
20
+ super
21
+ end
22
+ end
23
+
24
+ def respond_to_missing?(method_name, _include_private)
25
+ dispatcher.respond_to?(method_name)
18
26
  end
19
27
 
20
28
  private
29
+
21
30
  attr_reader :instrumentation, :dispatcher
22
31
  end
23
32
  end
@@ -25,14 +25,6 @@ module RubyEventStore
25
25
  end
26
26
  end
27
27
 
28
- def has_event?(event_id)
29
- repository.has_event?(event_id)
30
- end
31
-
32
- def last_stream_event(stream)
33
- repository.last_stream_event(stream)
34
- end
35
-
36
28
  def read(specification)
37
29
  instrumentation.instrument("read.repository.rails_event_store", specification: specification) do
38
30
  repository.read(specification)
@@ -57,7 +49,20 @@ module RubyEventStore
57
49
  end
58
50
  end
59
51
 
52
+ def method_missing(method_name, *arguments, **keyword_arguments, &block)
53
+ if respond_to?(method_name)
54
+ repository.public_send(method_name, *arguments, **keyword_arguments, &block)
55
+ else
56
+ super
57
+ end
58
+ end
59
+
60
+ def respond_to_missing?(method_name, _include_private)
61
+ repository.respond_to?(method_name)
62
+ end
63
+
60
64
  private
65
+
61
66
  attr_reader :repository, :instrumentation
62
67
  end
63
68
  end
@@ -2,7 +2,6 @@
2
2
 
3
3
  module RubyEventStore
4
4
  class LinkByMetadata
5
-
6
5
  def initialize(event_store:, key:, prefix: nil)
7
6
  @event_store = event_store
8
7
  @key = key
@@ -12,31 +11,19 @@ module RubyEventStore
12
11
  def call(event)
13
12
  return unless event.metadata.has_key?(@key)
14
13
 
15
- @event_store.link(
16
- [event.event_id],
17
- stream_name: "#{@prefix}#{event.metadata.fetch(@key)}"
18
- )
14
+ @event_store.link([event.event_id], stream_name: "#{@prefix}#{event.metadata.fetch(@key)}")
19
15
  end
20
-
21
16
  end
22
17
 
23
18
  class LinkByCorrelationId < LinkByMetadata
24
19
  def initialize(event_store:, prefix: nil)
25
- super(
26
- event_store: event_store,
27
- prefix: prefix,
28
- key: :correlation_id,
29
- )
20
+ super(event_store: event_store, prefix: prefix, key: :correlation_id)
30
21
  end
31
22
  end
32
23
 
33
24
  class LinkByCausationId < LinkByMetadata
34
25
  def initialize(event_store:, prefix: nil)
35
- super(
36
- event_store: event_store,
37
- prefix: prefix,
38
- key: :causation_id,
39
- )
26
+ super(event_store: event_store, prefix: prefix, key: :causation_id)
40
27
  end
41
28
  end
42
29
 
@@ -47,11 +34,7 @@ module RubyEventStore
47
34
  end
48
35
 
49
36
  def call(event)
50
- @event_store.link(
51
- [event.event_id],
52
- stream_name: "#{@prefix}#{event.event_type}"
53
- )
37
+ @event_store.link([event.event_id], stream_name: "#{@prefix}#{event.event_type}")
54
38
  end
55
39
  end
56
-
57
40
  end
@@ -4,10 +4,12 @@ module RubyEventStore
4
4
  module Mappers
5
5
  class Default < PipelineMapper
6
6
  def initialize(events_class_remapping: {})
7
- super(Pipeline.new(
8
- Transformation::EventClassRemapper.new(events_class_remapping),
9
- Transformation::SymbolizeMetadataKeys.new,
10
- ))
7
+ super(
8
+ Pipeline.new(
9
+ Transformation::EventClassRemapper.new(events_class_remapping),
10
+ Transformation::SymbolizeMetadataKeys.new
11
+ )
12
+ )
11
13
  end
12
14
  end
13
15
  end
@@ -5,31 +5,22 @@ module RubyEventStore
5
5
  class EncryptionKey
6
6
  def initialize(cipher:, key:)
7
7
  @cipher = cipher
8
- @key = key
8
+ @key = key
9
9
  end
10
10
 
11
11
  def encrypt(message, iv)
12
- crypto = prepare_encrypt(cipher)
13
- crypto.iv = iv
12
+ crypto = prepare_encrypt(cipher)
13
+ crypto.iv = iv
14
14
  crypto.key = key
15
15
 
16
- if crypto.authenticated?
17
- encrypt_authenticated(crypto, message)
18
- else
19
- crypto.update(message) + crypto.final
20
- end
16
+ crypto.authenticated? ? encrypt_authenticated(crypto, message) : crypto.update(message) + crypto.final
21
17
  end
22
18
 
23
19
  def decrypt(message, iv)
24
- crypto = prepare_decrypt(cipher)
25
- crypto.iv = iv
20
+ crypto = prepare_decrypt(cipher)
21
+ crypto.iv = iv
26
22
  crypto.key = key
27
- ciphertext =
28
- if crypto.authenticated?
29
- ciphertext_from_authenticated(crypto, message)
30
- else
31
- message
32
- end
23
+ ciphertext = crypto.authenticated? ? ciphertext_from_authenticated(crypto, message) : message
33
24
  (crypto.update(ciphertext) + crypto.final).force_encoding("UTF-8")
34
25
  end
35
26
 
@@ -1,14 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'yaml'
4
-
5
3
  module RubyEventStore
6
4
  module Mappers
7
5
  class EncryptionMapper < PipelineMapper
8
- def initialize(key_repository, serializer: YAML, forgotten_data: ForgottenData.new)
9
- super(Pipeline.new(
10
- Transformation::Encryption.new(key_repository, serializer: serializer, forgotten_data: forgotten_data),
11
- ))
6
+ def initialize(key_repository, serializer: Serializers::YAML, forgotten_data: ForgottenData.new)
7
+ super(
8
+ Pipeline.new(
9
+ Transformation::Encryption.new(key_repository, serializer: serializer, forgotten_data: forgotten_data)
10
+ )
11
+ )
12
12
  end
13
13
  end
14
14
  end
@@ -3,7 +3,7 @@
3
3
  module RubyEventStore
4
4
  module Mappers
5
5
  class ForgottenData
6
- FORGOTTEN_DATA = 'FORGOTTEN_DATA'.freeze
6
+ FORGOTTEN_DATA = "FORGOTTEN_DATA".freeze
7
7
 
8
8
  def initialize(string = FORGOTTEN_DATA)
9
9
  @string = string
@@ -3,7 +3,7 @@
3
3
  module RubyEventStore
4
4
  module Mappers
5
5
  class InMemoryEncryptionKeyRepository
6
- DEFAULT_CIPHER = 'aes-256-gcm'.freeze
6
+ DEFAULT_CIPHER = "aes-256-gcm".freeze
7
7
 
8
8
  def initialize
9
9
  @keys = {}
@@ -3,7 +3,6 @@
3
3
  module RubyEventStore
4
4
  module Mappers
5
5
  class NullMapper < PipelineMapper
6
-
7
6
  def initialize
8
7
  super(Pipeline.new)
9
8
  end
@@ -4,22 +4,15 @@ module RubyEventStore
4
4
  module Mappers
5
5
  class Pipeline
6
6
  def initialize(*transformations, to_domain_event: Transformation::DomainEvent.new)
7
- @transformations = [
8
- to_domain_event,
9
- transformations,
10
- ].flatten.freeze
7
+ @transformations = [to_domain_event, transformations].flatten.freeze
11
8
  end
12
9
 
13
10
  def dump(domain_event)
14
- transformations.reduce(domain_event) do |item, transform|
15
- transform.dump(item)
16
- end
11
+ transformations.reduce(domain_event) { |item, transform| transform.dump(item) }
17
12
  end
18
13
 
19
14
  def load(record)
20
- transformations.reverse.reduce(record) do |item, transform|
21
- transform.load(item)
22
- end
15
+ transformations.reverse.reduce(record) { |item, transform| transform.load(item) }
23
16
  end
24
17
 
25
18
  attr_reader :transformations
@@ -16,6 +16,7 @@ module RubyEventStore
16
16
  end
17
17
 
18
18
  private
19
+
19
20
  attr_reader :pipeline
20
21
  end
21
22
  end
@@ -5,27 +5,37 @@ module RubyEventStore
5
5
  module Transformation
6
6
  class DomainEvent
7
7
  def dump(domain_event)
8
- metadata = domain_event.metadata.to_h
8
+ metadata = domain_event.metadata.dup.to_h
9
9
  timestamp = metadata.delete(:timestamp)
10
10
  valid_at = metadata.delete(:valid_at)
11
11
  Record.new(
12
- event_id: domain_event.event_id,
13
- metadata: metadata,
14
- data: domain_event.data,
12
+ event_id: domain_event.event_id,
13
+ metadata: metadata,
14
+ data: domain_event.data,
15
15
  event_type: domain_event.event_type,
16
- timestamp: timestamp,
17
- valid_at: valid_at,
16
+ timestamp: timestamp,
17
+ valid_at: valid_at
18
18
  )
19
19
  end
20
20
 
21
21
  def load(record)
22
- Object.const_get(record.event_type).new(
22
+ Object
23
+ .const_get(record.event_type)
24
+ .new(
25
+ event_id: record.event_id,
26
+ data: record.data,
27
+ metadata: record.metadata.merge(timestamp: record.timestamp, valid_at: record.valid_at)
28
+ )
29
+ rescue NameError
30
+ Event.new(
23
31
  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,
32
+ data: record.data,
33
+ metadata:
34
+ record.metadata.merge(
35
+ timestamp: record.timestamp,
36
+ valid_at: record.valid_at,
37
+ event_type: record.event_type
38
+ )
29
39
  )
30
40
  end
31
41
  end
@@ -6,38 +6,38 @@ module RubyEventStore
6
6
  class Encryption
7
7
  class Leaf
8
8
  def self.===(hash)
9
- hash.keys.sort.eql? %i(cipher identifier iv)
9
+ hash.keys.sort.eql? %i[cipher identifier iv]
10
10
  end
11
11
  end
12
12
  private_constant :Leaf
13
13
 
14
14
  class MissingEncryptionKey < StandardError
15
15
  def initialize(key_identifier)
16
- super %Q|Could not find encryption key for '#{key_identifier}'|
16
+ super "Could not find encryption key for '#{key_identifier}'"
17
17
  end
18
18
  end
19
19
 
20
- def initialize(key_repository, serializer: YAML, forgotten_data: ForgottenData.new)
20
+ def initialize(key_repository, serializer: Serializers::YAML, forgotten_data: ForgottenData.new)
21
21
  @key_repository = key_repository
22
22
  @serializer = serializer
23
23
  @forgotten_data = forgotten_data
24
24
  end
25
25
 
26
26
  def dump(record)
27
- data = record.data
28
- metadata = record.metadata.dup
27
+ data = record.data
28
+ metadata = record.metadata.dup
29
29
  event_class = Object.const_get(record.event_type)
30
30
 
31
- crypto_description = encryption_metadata(data, encryption_schema(event_class))
31
+ crypto_description = encryption_metadata(data, encryption_schema(event_class))
32
32
  metadata[:encryption] = crypto_description unless crypto_description.empty?
33
33
 
34
34
  Record.new(
35
- event_id: record.event_id,
35
+ event_id: record.event_id,
36
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
+ data: encrypt_data(deep_dup(data), crypto_description),
38
+ metadata: metadata,
39
+ timestamp: record.timestamp,
40
+ valid_at: record.valid_at
41
41
  )
42
42
  end
43
43
 
@@ -46,16 +46,17 @@ module RubyEventStore
46
46
  crypto_description = Hash(metadata.delete(:encryption))
47
47
 
48
48
  Record.new(
49
- event_id: record.event_id,
49
+ event_id: record.event_id,
50
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,
51
+ data: decrypt_data(record.data, crypto_description),
52
+ metadata: metadata,
53
+ timestamp: record.timestamp,
54
+ valid_at: record.valid_at
55
55
  )
56
56
  end
57
57
 
58
58
  private
59
+
59
60
  attr_reader :key_repository, :serializer, :forgotten_data
60
61
 
61
62
  def encryption_schema(event_class)
@@ -64,9 +65,7 @@ module RubyEventStore
64
65
 
65
66
  def deep_dup(hash)
66
67
  duplicate = hash.dup
67
- duplicate.each do |k, v|
68
- duplicate[k] = v.instance_of?(Hash) ? deep_dup(v) : v
69
- end
68
+ duplicate.each { |k, v| duplicate[k] = v.instance_of?(Hash) ? deep_dup(v) : v }
70
69
  duplicate
71
70
  end
72
71
 
@@ -79,11 +78,7 @@ module RubyEventStore
79
78
  key_identifier = value.call(data)
80
79
  encryption_key = key_repository.key_of(key_identifier)
81
80
  raise MissingEncryptionKey.new(key_identifier) unless encryption_key
82
- acc[key] = {
83
- cipher: encryption_key.cipher,
84
- iv: encryption_key.random_iv,
85
- identifier: key_identifier,
86
- }
81
+ acc[key] = { cipher: encryption_key.cipher, iv: encryption_key.random_iv, identifier: key_identifier }
87
82
  end
88
83
  acc
89
84
  end
@@ -122,7 +117,8 @@ module RubyEventStore
122
117
  cryptogram = data.fetch(attribute)
123
118
  return unless cryptogram
124
119
 
125
- encryption_key = key_repository.key_of(meta.fetch(:identifier), cipher: meta.fetch(:cipher)) or return forgotten_data
120
+ encryption_key = key_repository.key_of(meta.fetch(:identifier), cipher: meta.fetch(:cipher)) or
121
+ return forgotten_data
126
122
  serializer.load(encryption_key.decrypt(cryptogram, meta.fetch(:iv)))
127
123
  when Hash
128
124
  decrypt_data(data.fetch(attribute), meta)
@@ -14,16 +14,17 @@ module RubyEventStore
14
14
 
15
15
  def load(record)
16
16
  Record.new(
17
- event_id: record.event_id,
17
+ event_id: record.event_id,
18
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,
19
+ data: record.data,
20
+ metadata: record.metadata,
21
+ timestamp: record.timestamp,
22
+ valid_at: record.valid_at
23
23
  )
24
24
  end
25
25
 
26
26
  private
27
+
27
28
  attr_reader :class_map
28
29
  end
29
30
  end