ruby_event_store 1.2.2 → 2.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.
- checksums.yaml +4 -4
- data/README.md +3 -1
- data/lib/ruby_event_store.rb +3 -7
- 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/instrumented_repository.rb +3 -3
- data/lib/ruby_event_store/mappers/default.rb +3 -8
- data/lib/ruby_event_store/mappers/encryption_mapper.rb +3 -4
- data/lib/ruby_event_store/mappers/instrumented_mapper.rb +4 -4
- data/lib/ruby_event_store/mappers/json_mapper.rb +7 -7
- data/lib/ruby_event_store/mappers/pipeline.rb +2 -5
- data/lib/ruby_event_store/mappers/pipeline_mapper.rb +2 -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/stringify_metadata_keys.rb +12 -7
- data/lib/ruby_event_store/mappers/transformation/symbolize_metadata_keys.rb +12 -7
- data/lib/ruby_event_store/mappers/transformation/upcast.rb +37 -0
- data/lib/ruby_event_store/null.rb +13 -0
- data/lib/ruby_event_store/projection.rb +2 -1
- 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 +267 -105
- data/lib/ruby_event_store/spec/mapper_lint.rb +6 -6
- data/lib/ruby_event_store/spec/subscriptions_lint.rb +25 -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/subscriptions.rb +23 -9
- data/lib/ruby_event_store/transform_keys.rb +5 -5
- data/lib/ruby_event_store/version.rb +1 -1
- metadata +15 -21
- data/CHANGELOG.md +0 -93
- data/Gemfile +0 -11
- data/Makefile +0 -22
- 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/serialization.rb +0 -34
- data/lib/ruby_event_store/mappers/transformation/serialized_record.rb +0 -27
- data/ruby_event_store.gemspec +0 -29
@@ -7,9 +7,9 @@ module RubyEventStore
|
|
7
7
|
@instrumentation = instrumentation
|
8
8
|
end
|
9
9
|
|
10
|
-
def call(subscriber, 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,
|
12
|
+
dispatcher.call(subscriber, event, record)
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
@@ -7,9 +7,9 @@ module RubyEventStore
|
|
7
7
|
@instrumentation = instrumentation
|
8
8
|
end
|
9
9
|
|
10
|
-
def append_to_stream(
|
11
|
-
instrumentation.instrument("append_to_stream.repository.rails_event_store", events:
|
12
|
-
repository.append_to_stream(
|
10
|
+
def append_to_stream(records, stream, expected_version)
|
11
|
+
instrumentation.instrument("append_to_stream.repository.rails_event_store", events: records, stream: stream) do
|
12
|
+
repository.append_to_stream(records, stream, expected_version)
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
@@ -1,17 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'yaml'
|
4
|
-
|
5
3
|
module RubyEventStore
|
6
4
|
module Mappers
|
7
5
|
class Default < PipelineMapper
|
8
|
-
def initialize(
|
6
|
+
def initialize(events_class_remapping: {})
|
9
7
|
super(Pipeline.new(
|
10
|
-
|
11
|
-
|
12
|
-
Transformation::SymbolizeMetadataKeys.new,
|
13
|
-
Transformation::Serialization.new(serializer: serializer),
|
14
|
-
]
|
8
|
+
Transformation::EventClassRemapper.new(events_class_remapping),
|
9
|
+
Transformation::SymbolizeMetadataKeys.new,
|
15
10
|
))
|
16
11
|
end
|
17
12
|
end
|
@@ -1,14 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'yaml'
|
4
|
+
|
3
5
|
module RubyEventStore
|
4
6
|
module Mappers
|
5
7
|
class EncryptionMapper < PipelineMapper
|
6
8
|
def initialize(key_repository, serializer: YAML, forgotten_data: ForgottenData.new)
|
7
9
|
super(Pipeline.new(
|
8
|
-
|
9
|
-
Transformation::Encryption.new(key_repository, serializer: serializer, forgotten_data: forgotten_data),
|
10
|
-
Transformation::Serialization.new(serializer: serializer),
|
11
|
-
]
|
10
|
+
Transformation::Encryption.new(key_repository, serializer: serializer, forgotten_data: forgotten_data),
|
12
11
|
))
|
13
12
|
end
|
14
13
|
end
|
@@ -8,15 +8,15 @@ 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
|
|
@@ -2,14 +2,14 @@
|
|
2
2
|
|
3
3
|
module RubyEventStore
|
4
4
|
module Mappers
|
5
|
-
class JSONMapper <
|
5
|
+
class JSONMapper < Default
|
6
6
|
def initialize(events_class_remapping: {})
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
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
13
|
end
|
14
14
|
end
|
15
15
|
end
|
@@ -3,13 +3,10 @@
|
|
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
|
+
def initialize(*transformations, to_domain_event: Transformation::DomainEvent.new)
|
9
7
|
@transformations = [
|
10
8
|
to_domain_event,
|
11
|
-
|
12
|
-
to_serialized_record
|
9
|
+
transformations,
|
13
10
|
].flatten.freeze
|
14
11
|
end
|
15
12
|
|
@@ -7,11 +7,11 @@ 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
|
|
@@ -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
|
@@ -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
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RubyEventStore
|
4
|
+
module Mappers
|
5
|
+
module Transformation
|
6
|
+
class Upcast
|
7
|
+
class RecordUpcaster
|
8
|
+
def initialize(upcast_map)
|
9
|
+
@upcast_map = upcast_map
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(record)
|
13
|
+
identity = lambda { |r| r }
|
14
|
+
new_record = @upcast_map.fetch(record.event_type, identity)[record]
|
15
|
+
if new_record.equal?(record)
|
16
|
+
record
|
17
|
+
else
|
18
|
+
call(new_record)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize(upcast_map)
|
24
|
+
@record_upcaster = RecordUpcaster.new(upcast_map)
|
25
|
+
end
|
26
|
+
|
27
|
+
def dump(record)
|
28
|
+
record
|
29
|
+
end
|
30
|
+
|
31
|
+
def load(record)
|
32
|
+
@record_upcaster.call(record)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -4,7 +4,8 @@ module RubyEventStore
|
|
4
4
|
class Projection
|
5
5
|
private_class_method :new
|
6
6
|
|
7
|
-
def self.from_stream(
|
7
|
+
def self.from_stream(stream_or_streams)
|
8
|
+
streams = Array(stream_or_streams)
|
8
9
|
raise(ArgumentError, "At least one stream must be given") if streams.empty?
|
9
10
|
new(streams: streams)
|
10
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
|