ruby_event_store 1.3.1 → 2.0.3
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.
- checksums.yaml +4 -4
- data/Gemfile +2 -4
- data/Gemfile.lock +121 -0
- data/Makefile +13 -3
- data/lib/ruby_event_store/broker.rb +3 -3
- data/lib/ruby_event_store/client.rb +47 -23
- data/lib/ruby_event_store/composed_dispatcher.rb +2 -2
- data/lib/ruby_event_store/constants.rb +1 -0
- data/lib/ruby_event_store/errors.rb +0 -1
- data/lib/ruby_event_store/event.rb +8 -1
- data/lib/ruby_event_store/immediate_async_dispatcher.rb +2 -2
- data/lib/ruby_event_store/in_memory_repository.rb +98 -59
- data/lib/ruby_event_store/instrumented_dispatcher.rb +2 -2
- data/lib/ruby_event_store/mappers/default.rb +28 -6
- data/lib/ruby_event_store/mappers/deprecated_wrapper.rb +33 -0
- data/lib/ruby_event_store/mappers/encryption_mapper.rb +1 -4
- data/lib/ruby_event_store/mappers/instrumented_mapper.rb +8 -4
- data/lib/ruby_event_store/mappers/json_mapper.rb +2 -4
- data/lib/ruby_event_store/mappers/pipeline.rb +26 -5
- data/lib/ruby_event_store/mappers/pipeline_mapper.rb +6 -2
- data/lib/ruby_event_store/mappers/transformation/domain_event.rb +16 -8
- data/lib/ruby_event_store/mappers/transformation/encryption.rb +20 -12
- data/lib/ruby_event_store/mappers/transformation/event_class_remapper.rb +11 -4
- data/lib/ruby_event_store/mappers/transformation/serialization.rb +16 -14
- data/lib/ruby_event_store/mappers/transformation/stringify_metadata_keys.rb +12 -7
- data/lib/ruby_event_store/mappers/transformation/symbolize_metadata_keys.rb +12 -7
- data/lib/ruby_event_store/null.rb +13 -0
- data/lib/ruby_event_store/projection.rb +2 -13
- data/lib/ruby_event_store/record.rb +68 -0
- data/lib/ruby_event_store/serialized_record.rb +23 -4
- data/lib/ruby_event_store/spec/broker_lint.rb +9 -9
- data/lib/ruby_event_store/spec/event_repository_lint.rb +200 -36
- data/lib/ruby_event_store/spec/mapper_lint.rb +6 -6
- data/lib/ruby_event_store/spec/subscriptions_lint.rb +6 -0
- data/lib/ruby_event_store/specification.rb +100 -7
- data/lib/ruby_event_store/specification_reader.rb +2 -2
- data/lib/ruby_event_store/specification_result.rb +86 -2
- data/lib/ruby_event_store/version.rb +1 -1
- data/lib/ruby_event_store.rb +4 -7
- data/ruby_event_store.gemspec +1 -3
- metadata +7 -9
- data/lib/ruby_event_store/mappers/protobuf.rb +0 -24
- data/lib/ruby_event_store/mappers/transformation/item.rb +0 -56
- data/lib/ruby_event_store/mappers/transformation/proto_event.rb +0 -17
- data/lib/ruby_event_store/mappers/transformation/protobuf_encoder.rb +0 -30
- data/lib/ruby_event_store/mappers/transformation/protobuf_nested_struct_metadata.rb +0 -30
- data/lib/ruby_event_store/mappers/transformation/serialized_record.rb +0 -27
@@ -5,13 +5,35 @@ require 'yaml'
|
|
5
5
|
module RubyEventStore
|
6
6
|
module Mappers
|
7
7
|
class Default < PipelineMapper
|
8
|
-
|
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
|
-
|
11
|
-
|
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
|
-
|
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
|
11
|
+
def event_to_record(domain_event)
|
12
12
|
instrumentation.instrument("serialize.mapper.rails_event_store", domain_event: domain_event) do
|
13
|
-
mapper.
|
13
|
+
mapper.event_to_record(domain_event)
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
-
def
|
17
|
+
def record_to_event(record)
|
18
18
|
instrumentation.instrument("deserialize.mapper.rails_event_store", record: record) do
|
19
|
-
mapper.
|
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
|
-
|
9
|
-
|
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
|
-
|
7
|
-
|
8
|
-
|
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
|
-
|
12
|
-
|
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
|
10
|
+
def event_to_record(domain_event)
|
11
11
|
pipeline.dump(domain_event)
|
12
12
|
end
|
13
13
|
|
14
|
-
def
|
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
|
-
|
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:
|
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(
|
17
|
-
Object.const_get(
|
18
|
-
event_id:
|
19
|
-
metadata:
|
20
|
-
|
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(
|
27
|
-
data =
|
28
|
-
metadata =
|
29
|
-
event_class = Object.const_get(
|
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
|
-
|
35
|
-
|
36
|
-
|
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(
|
41
|
-
metadata =
|
44
|
+
def load(record)
|
45
|
+
metadata = record.metadata.dup
|
42
46
|
crypto_description = Hash(metadata.delete(:encryption))
|
43
47
|
|
44
|
-
|
45
|
-
|
46
|
-
|
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(
|
12
|
-
|
11
|
+
def dump(record)
|
12
|
+
record
|
13
13
|
end
|
14
14
|
|
15
|
-
def load(
|
16
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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(
|
8
|
-
stringify(
|
7
|
+
def dump(record)
|
8
|
+
stringify(record)
|
9
9
|
end
|
10
10
|
|
11
|
-
def load(
|
12
|
-
stringify(
|
11
|
+
def load(record)
|
12
|
+
stringify(record)
|
13
13
|
end
|
14
14
|
|
15
15
|
private
|
16
|
-
def stringify(
|
17
|
-
|
18
|
-
|
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(
|
8
|
-
symbolize(
|
7
|
+
def dump(record)
|
8
|
+
symbolize(record)
|
9
9
|
end
|
10
10
|
|
11
|
-
def load(
|
12
|
-
symbolize(
|
11
|
+
def load(record)
|
12
|
+
symbolize(record)
|
13
13
|
end
|
14
14
|
|
15
15
|
private
|
16
|
-
def symbolize(
|
17
|
-
|
18
|
-
|
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
|
@@ -4,19 +4,8 @@ module RubyEventStore
|
|
4
4
|
class Projection
|
5
5
|
private_class_method :new
|
6
6
|
|
7
|
-
def self.from_stream(
|
8
|
-
|
9
|
-
if first_of_streams.respond_to?(:flatten)
|
10
|
-
warn <<~EOW
|
11
|
-
Passing array to .from_stream is not supported. This method expects undefined number
|
12
|
-
of positional arguments (splat) rather than an array.
|
13
|
-
|
14
|
-
Expected: .from_stream(#{first_of_streams.map(&:inspect).join(", ")})
|
15
|
-
Received: .from_stream(#{first_of_streams})
|
16
|
-
EOW
|
17
|
-
streams = first_of_streams
|
18
|
-
end
|
19
|
-
|
7
|
+
def self.from_stream(stream_or_streams)
|
8
|
+
streams = Array(stream_or_streams)
|
20
9
|
raise(ArgumentError, "At least one stream must be given") if streams.empty?
|
21
10
|
new(streams: streams)
|
22
11
|
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RubyEventStore
|
4
|
+
class Record
|
5
|
+
StringsRequired = Class.new(StandardError)
|
6
|
+
def initialize(event_id:, data:, metadata:, event_type:, timestamp:, valid_at:)
|
7
|
+
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
|
+
@serialized_records = {}
|
15
|
+
freeze
|
16
|
+
end
|
17
|
+
|
18
|
+
attr_reader :event_id, :data, :metadata, :event_type, :timestamp, :valid_at
|
19
|
+
|
20
|
+
BIG_VALUE = 0b110011100100000010010010110011101011110101010101001100111110011
|
21
|
+
def hash
|
22
|
+
[
|
23
|
+
self.class,
|
24
|
+
event_id,
|
25
|
+
data,
|
26
|
+
metadata,
|
27
|
+
event_type,
|
28
|
+
timestamp,
|
29
|
+
valid_at,
|
30
|
+
].hash ^ BIG_VALUE
|
31
|
+
end
|
32
|
+
|
33
|
+
def ==(other)
|
34
|
+
other.instance_of?(self.class) &&
|
35
|
+
other.event_id.eql?(event_id) &&
|
36
|
+
other.data.eql?(data) &&
|
37
|
+
other.metadata.eql?(metadata) &&
|
38
|
+
other.event_type.eql?(event_type) &&
|
39
|
+
other.timestamp.eql?(timestamp) &&
|
40
|
+
other.valid_at.eql?(valid_at)
|
41
|
+
end
|
42
|
+
|
43
|
+
def to_h
|
44
|
+
{
|
45
|
+
event_id: event_id,
|
46
|
+
data: data,
|
47
|
+
metadata: metadata,
|
48
|
+
event_type: event_type,
|
49
|
+
timestamp: timestamp,
|
50
|
+
valid_at: valid_at,
|
51
|
+
}
|
52
|
+
end
|
53
|
+
|
54
|
+
def serialize(serializer)
|
55
|
+
@serialized_records[serializer] ||=
|
56
|
+
SerializedRecord.new(
|
57
|
+
event_id: event_id,
|
58
|
+
event_type: event_type,
|
59
|
+
data: serializer.dump(data),
|
60
|
+
metadata: serializer.dump(metadata),
|
61
|
+
timestamp: timestamp.iso8601(TIMESTAMP_PRECISION),
|
62
|
+
valid_at: valid_at.iso8601(TIMESTAMP_PRECISION),
|
63
|
+
)
|
64
|
+
end
|
65
|
+
|
66
|
+
alias_method :eql?, :==
|
67
|
+
end
|
68
|
+
end
|
@@ -3,18 +3,20 @@
|
|
3
3
|
module RubyEventStore
|
4
4
|
class SerializedRecord
|
5
5
|
StringsRequired = Class.new(StandardError)
|
6
|
-
def initialize(event_id:, data:, metadata:, event_type:)
|
6
|
+
def initialize(event_id:, data:, metadata:, event_type:, timestamp:, valid_at:)
|
7
7
|
raise StringsRequired unless [event_id, event_type].all? { |v| v.instance_of?(String) }
|
8
8
|
@event_id = event_id
|
9
9
|
@data = data
|
10
10
|
@metadata = metadata
|
11
11
|
@event_type = event_type
|
12
|
+
@timestamp = timestamp
|
13
|
+
@valid_at = valid_at
|
12
14
|
freeze
|
13
15
|
end
|
14
16
|
|
15
|
-
attr_reader :event_id, :data, :metadata, :event_type
|
17
|
+
attr_reader :event_id, :data, :metadata, :event_type, :timestamp, :valid_at
|
16
18
|
|
17
|
-
BIG_VALUE =
|
19
|
+
BIG_VALUE = 0b110011100100000010010010110011101011110101010101001100111110111
|
18
20
|
def hash
|
19
21
|
[
|
20
22
|
self.class,
|
@@ -22,6 +24,8 @@ module RubyEventStore
|
|
22
24
|
data,
|
23
25
|
metadata,
|
24
26
|
event_type,
|
27
|
+
timestamp,
|
28
|
+
valid_at,
|
25
29
|
].hash ^ BIG_VALUE
|
26
30
|
end
|
27
31
|
|
@@ -30,7 +34,9 @@ module RubyEventStore
|
|
30
34
|
other.event_id.eql?(event_id) &&
|
31
35
|
other.data.eql?(data) &&
|
32
36
|
other.metadata.eql?(metadata) &&
|
33
|
-
other.event_type.eql?(event_type)
|
37
|
+
other.event_type.eql?(event_type) &&
|
38
|
+
other.timestamp.eql?(timestamp) &&
|
39
|
+
other.valid_at.eql?(valid_at)
|
34
40
|
end
|
35
41
|
|
36
42
|
def to_h
|
@@ -39,9 +45,22 @@ module RubyEventStore
|
|
39
45
|
data: data,
|
40
46
|
metadata: metadata,
|
41
47
|
event_type: event_type,
|
48
|
+
timestamp: timestamp,
|
49
|
+
valid_at: valid_at,
|
42
50
|
}
|
43
51
|
end
|
44
52
|
|
53
|
+
def deserialize(serializer)
|
54
|
+
Record.new(
|
55
|
+
event_id: event_id,
|
56
|
+
event_type: event_type,
|
57
|
+
data: serializer.load(data),
|
58
|
+
metadata: serializer.load(metadata),
|
59
|
+
timestamp: Time.iso8601(timestamp),
|
60
|
+
valid_at: Time.iso8601(valid_at),
|
61
|
+
)
|
62
|
+
end
|
63
|
+
|
45
64
|
alias_method :eql?, :==
|
46
65
|
end
|
47
66
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
RSpec.shared_examples :broker do |broker_klass|
|
2
2
|
let(:event) { instance_double(::RubyEventStore::Event, event_type: 'EventType') }
|
3
|
-
let(:
|
3
|
+
let(:record) { instance_double(::RubyEventStore::Record) }
|
4
4
|
let(:handler) { HandlerClass.new }
|
5
5
|
let(:subscriptions) { ::RubyEventStore::Subscriptions.new }
|
6
6
|
let(:dispatcher) { ::RubyEventStore::Dispatcher.new }
|
@@ -9,26 +9,26 @@ RSpec.shared_examples :broker do |broker_klass|
|
|
9
9
|
specify "no dispatch when no subscriptions" do
|
10
10
|
expect(subscriptions).to receive(:all_for).with('EventType').and_return([])
|
11
11
|
expect(dispatcher).not_to receive(:call)
|
12
|
-
broker.call(event,
|
12
|
+
broker.call(event, record)
|
13
13
|
end
|
14
14
|
|
15
15
|
specify "calls subscription" do
|
16
16
|
expect(subscriptions).to receive(:all_for).with('EventType').and_return([handler])
|
17
|
-
expect(dispatcher).to receive(:call).with(handler, event,
|
18
|
-
broker.call(event,
|
17
|
+
expect(dispatcher).to receive(:call).with(handler, event, record)
|
18
|
+
broker.call(event, record)
|
19
19
|
end
|
20
20
|
|
21
21
|
specify "calls subscribed class" do
|
22
22
|
expect(subscriptions).to receive(:all_for).with('EventType').and_return([HandlerClass])
|
23
|
-
expect(dispatcher).to receive(:call).with(HandlerClass, event,
|
24
|
-
broker.call(event,
|
23
|
+
expect(dispatcher).to receive(:call).with(HandlerClass, event, record)
|
24
|
+
broker.call(event, record)
|
25
25
|
end
|
26
26
|
|
27
27
|
specify "calls all subscriptions" do
|
28
28
|
expect(subscriptions).to receive(:all_for).with('EventType').and_return([handler, HandlerClass])
|
29
|
-
expect(dispatcher).to receive(:call).with(handler, event,
|
30
|
-
expect(dispatcher).to receive(:call).with(HandlerClass, event,
|
31
|
-
broker.call(event,
|
29
|
+
expect(dispatcher).to receive(:call).with(handler, event, record)
|
30
|
+
expect(dispatcher).to receive(:call).with(HandlerClass, event, record)
|
31
|
+
broker.call(event, record)
|
32
32
|
end
|
33
33
|
|
34
34
|
specify 'raise error when no subscriber' do
|