ruby_event_store 0.27.1 → 0.28.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 +5 -5
- data/Gemfile +2 -1
- data/Makefile +15 -1
- data/lib/ruby_event_store/client.rb +47 -55
- data/lib/ruby_event_store/constants.rb +1 -1
- data/lib/ruby_event_store/errors.rb +1 -0
- data/lib/ruby_event_store/event.rb +8 -3
- data/lib/ruby_event_store/expected_version.rb +73 -0
- data/lib/ruby_event_store/in_memory_repository.rb +48 -76
- data/lib/ruby_event_store/mappers/default.rb +8 -8
- data/lib/ruby_event_store/mappers/null_mapper.rb +15 -0
- data/lib/ruby_event_store/mappers/protobuf.rb +56 -13
- data/lib/ruby_event_store/metadata.rb +51 -0
- data/lib/ruby_event_store/pub_sub/broker.rb +17 -15
- data/lib/ruby_event_store/serialized_record.rb +30 -0
- data/lib/ruby_event_store/spec/event_broker_lint.rb +11 -0
- data/lib/ruby_event_store/spec/event_repository_lint.rb +474 -413
- data/lib/ruby_event_store/specification.rb +76 -0
- data/lib/ruby_event_store/stream.rb +29 -1
- data/lib/ruby_event_store/version.rb +1 -1
- data/lib/ruby_event_store.rb +4 -0
- data/ruby_event_store.gemspec +7 -1
- metadata +13 -5
@@ -11,24 +11,24 @@ module RubyEventStore
|
|
11
11
|
def event_to_serialized_record(domain_event)
|
12
12
|
SerializedRecord.new(
|
13
13
|
event_id: domain_event.event_id,
|
14
|
-
metadata:
|
15
|
-
data:
|
14
|
+
metadata: serializer.dump(domain_event.metadata.to_h),
|
15
|
+
data: serializer.dump(domain_event.data),
|
16
16
|
event_type: domain_event.class.name
|
17
17
|
)
|
18
18
|
end
|
19
19
|
|
20
20
|
def serialized_record_to_event(record)
|
21
|
-
event_type =
|
21
|
+
event_type = events_class_remapping.fetch(record.event_type) { record.event_type }
|
22
22
|
Object.const_get(event_type).new(
|
23
23
|
event_id: record.event_id,
|
24
|
-
metadata:
|
25
|
-
data:
|
24
|
+
metadata: serializer.load(record.metadata),
|
25
|
+
data: serializer.load(record.data)
|
26
26
|
)
|
27
27
|
end
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
|
29
|
+
private
|
30
|
+
|
31
|
+
attr_reader :serializer, :events_class_remapping
|
32
32
|
|
33
33
|
end
|
34
34
|
end
|
@@ -1,35 +1,78 @@
|
|
1
1
|
module RubyEventStore
|
2
|
+
class Proto < RubyEventStore::Event
|
3
|
+
def initialize(event_id: SecureRandom.uuid, metadata: nil, data:)
|
4
|
+
@event_id = event_id
|
5
|
+
@metadata = Metadata.new(metadata.to_h)
|
6
|
+
@data = data
|
7
|
+
end
|
8
|
+
|
9
|
+
def type
|
10
|
+
data.class.descriptor.name
|
11
|
+
end
|
12
|
+
|
13
|
+
def encode_with(coder)
|
14
|
+
coder['event_id'] = event_id
|
15
|
+
coder['metadata'] = ProtobufNestedStruct::HashMapStringValue.dump(metadata.each_with_object({}){|(k,v),h| h[k.to_s] =v })
|
16
|
+
coder['data.proto'] = data.class.encode(data)
|
17
|
+
coder['data.type'] = type
|
18
|
+
end
|
19
|
+
|
20
|
+
def init_with(coder)
|
21
|
+
@event_id = coder['event_id']
|
22
|
+
@metadata = Metadata.new
|
23
|
+
ProtobufNestedStruct::HashMapStringValue.load(coder['metadata']).each_with_object(metadata){|(k,v),meta| meta[k.to_sym] = v }
|
24
|
+
@data = pool.lookup(coder['data.type']).msgclass.decode(coder['data.proto'])
|
25
|
+
end
|
26
|
+
|
27
|
+
def ==(other_event)
|
28
|
+
other_event.instance_of?(self.class) &&
|
29
|
+
other_event.event_id.eql?(event_id) &&
|
30
|
+
other_event.data == data # https://github.com/google/protobuf/issues/4455
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def pool
|
36
|
+
Google::Protobuf::DescriptorPool.generated_pool
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
2
40
|
module Mappers
|
3
41
|
class Protobuf
|
4
|
-
def initialize(
|
5
|
-
|
42
|
+
def initialize(events_class_remapping: {})
|
43
|
+
require_optional_dependency
|
6
44
|
@events_class_remapping = events_class_remapping
|
7
45
|
end
|
8
46
|
|
9
47
|
def event_to_serialized_record(domain_event)
|
10
48
|
SerializedRecord.new(
|
11
|
-
event_id: domain_event.
|
12
|
-
metadata:
|
13
|
-
data: domain_event.class.encode(domain_event),
|
14
|
-
event_type: domain_event.
|
49
|
+
event_id: domain_event.event_id,
|
50
|
+
metadata: ProtobufNestedStruct::HashMapStringValue.dump(domain_event.metadata.each_with_object({}){|(k,v),h| h[k.to_s] =v }),
|
51
|
+
data: domain_event.data.class.encode(domain_event.data),
|
52
|
+
event_type: domain_event.type
|
15
53
|
)
|
16
54
|
end
|
17
55
|
|
18
56
|
def serialized_record_to_event(record)
|
19
57
|
event_type = events_class_remapping.fetch(record.event_type) { record.event_type }
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
event.public_send(setter, value)
|
58
|
+
data = Google::Protobuf::DescriptorPool.generated_pool.lookup(event_type).msgclass.decode(record.data)
|
59
|
+
Proto.new(
|
60
|
+
event_id: record.event_id,
|
61
|
+
data: data,
|
62
|
+
).tap do |p|
|
63
|
+
ProtobufNestedStruct::HashMapStringValue.load(record.metadata).each_with_object(p.metadata) {|(k, v), meta| meta[k.to_sym] = v}
|
27
64
|
end
|
28
65
|
end
|
29
66
|
|
30
67
|
private
|
31
68
|
|
32
69
|
attr_reader :event_id_getter, :events_class_remapping
|
70
|
+
|
71
|
+
def require_optional_dependency
|
72
|
+
require 'protobuf_nested_struct'
|
73
|
+
rescue LoadError
|
74
|
+
raise LoadError, "cannot load such file -- protobuf_nested_struct. Add protobuf_nested_struct gem to Gemfile"
|
75
|
+
end
|
33
76
|
end
|
34
77
|
end
|
35
78
|
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'date'
|
2
|
+
require 'time'
|
3
|
+
require 'forwardable'
|
4
|
+
|
5
|
+
module RubyEventStore
|
6
|
+
class Metadata
|
7
|
+
include Enumerable
|
8
|
+
extend Forwardable
|
9
|
+
|
10
|
+
def initialize(h = self)
|
11
|
+
@h = {}
|
12
|
+
h.each do |k, v|
|
13
|
+
self[k] = (v)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def [](key)
|
18
|
+
raise ArgumentError unless Symbol === key
|
19
|
+
@h[key]
|
20
|
+
end
|
21
|
+
|
22
|
+
def []=(key, val)
|
23
|
+
raise ArgumentError unless allowed_types.any?{|klass| klass === val }
|
24
|
+
raise ArgumentError unless Symbol === key
|
25
|
+
@h[key]=val
|
26
|
+
end
|
27
|
+
|
28
|
+
def each(&block)
|
29
|
+
@h.each(&block)
|
30
|
+
end
|
31
|
+
|
32
|
+
SAFE_HASH_METHODS = [:<, :<=, :>, :>=, :assoc, :clear, :compact, :compact!,
|
33
|
+
:delete, :delete_if, :dig, :each_key, :each_pair,
|
34
|
+
:each_value, :empty?, :fetch, :fetch_values,
|
35
|
+
:flatten, :has_key?, :has_value?,
|
36
|
+
:keep_if, :key, :key?, :keys, :length,
|
37
|
+
:rassoc, :reject!, :select!, :shift, :size, :slice,
|
38
|
+
:to_proc, :transform_keys, :transform_values,
|
39
|
+
:value?, :values, :values_at]
|
40
|
+
|
41
|
+
delegate SAFE_HASH_METHODS => :@h
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def allowed_types
|
46
|
+
[String, Integer, Float, Date, Time, TrueClass, FalseClass]
|
47
|
+
end
|
48
|
+
|
49
|
+
private_constant :SAFE_HASH_METHODS
|
50
|
+
end
|
51
|
+
end
|
@@ -24,27 +24,27 @@ module RubyEventStore
|
|
24
24
|
|
25
25
|
def add_global_subscriber(subscriber)
|
26
26
|
verify_subscriber(subscriber)
|
27
|
-
|
27
|
+
global_subscribers << subscriber
|
28
28
|
|
29
|
-
->() {
|
29
|
+
->() { global_subscribers.delete(subscriber) }
|
30
30
|
end
|
31
31
|
|
32
32
|
def add_thread_global_subscriber(subscriber)
|
33
33
|
verify_subscriber(subscriber)
|
34
|
-
|
34
|
+
thread_global_subscribers.value += [subscriber]
|
35
35
|
|
36
|
-
->() {
|
36
|
+
->() { thread_global_subscribers.value -= [subscriber] }
|
37
37
|
end
|
38
38
|
|
39
39
|
def add_thread_subscriber(subscriber, event_types)
|
40
40
|
verify_subscriber(subscriber)
|
41
|
-
event_types.each{ |type|
|
42
|
-
->() {event_types.each{ |type|
|
41
|
+
event_types.each{ |type| thread_subscribers.value[type.to_s] << subscriber }
|
42
|
+
->() {event_types.each{ |type| thread_subscribers.value.fetch(type.to_s).delete(subscriber) } }
|
43
43
|
end
|
44
44
|
|
45
45
|
def notify_subscribers(event)
|
46
|
-
all_subscribers_for(event.
|
47
|
-
|
46
|
+
all_subscribers_for(event.type).each do |subscriber|
|
47
|
+
dispatcher.call(subscriber, event)
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
@@ -52,20 +52,22 @@ module RubyEventStore
|
|
52
52
|
|
53
53
|
def verify_subscriber(subscriber)
|
54
54
|
raise SubscriberNotExist if subscriber.nil?
|
55
|
-
|
55
|
+
dispatcher.verify(subscriber)
|
56
56
|
end
|
57
57
|
|
58
58
|
def subscribe(subscriber, event_types)
|
59
|
-
event_types.each{ |type|
|
60
|
-
->() {event_types.each{ |type|
|
59
|
+
event_types.each{ |type| subscribers[type.to_s] << subscriber }
|
60
|
+
->() {event_types.each{ |type| subscribers.fetch(type.to_s).delete(subscriber) } }
|
61
61
|
end
|
62
62
|
|
63
63
|
def all_subscribers_for(event_type)
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
64
|
+
subscribers[event_type] +
|
65
|
+
global_subscribers +
|
66
|
+
thread_global_subscribers.value +
|
67
|
+
thread_subscribers.value[event_type]
|
68
68
|
end
|
69
|
+
|
70
|
+
attr_reader :dispatcher, :subscribers, :global_subscribers, :thread_global_subscribers, :thread_subscribers
|
69
71
|
end
|
70
72
|
end
|
71
73
|
end
|
@@ -11,5 +11,35 @@ module RubyEventStore
|
|
11
11
|
end
|
12
12
|
|
13
13
|
attr_reader :event_id, :data, :metadata, :event_type
|
14
|
+
|
15
|
+
BIG_VALUE = 0b110011100100000010010010110011101011110101010101001100111110011
|
16
|
+
def hash
|
17
|
+
[
|
18
|
+
self.class,
|
19
|
+
event_id,
|
20
|
+
data,
|
21
|
+
metadata,
|
22
|
+
event_type,
|
23
|
+
].hash ^ BIG_VALUE
|
24
|
+
end
|
25
|
+
|
26
|
+
def ==(other)
|
27
|
+
other.instance_of?(self.class) &&
|
28
|
+
other.event_id.eql?(event_id) &&
|
29
|
+
other.data.eql?(data) &&
|
30
|
+
other.metadata.eql?(metadata) &&
|
31
|
+
other.event_type.eql?(event_type)
|
32
|
+
end
|
33
|
+
|
34
|
+
def to_h
|
35
|
+
{
|
36
|
+
event_id: event_id,
|
37
|
+
data: data,
|
38
|
+
metadata: metadata,
|
39
|
+
event_type: event_type,
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
alias_method :eql?, :==
|
14
44
|
end
|
15
45
|
end
|
@@ -186,6 +186,17 @@ RSpec.shared_examples :event_broker do |broker_class|
|
|
186
186
|
expect(dispatcher.dispatched).to eq([{subscriber: handler, event: event1}])
|
187
187
|
end
|
188
188
|
|
189
|
+
it 'subscribes by type of event which is a String' do
|
190
|
+
handler = TestHandler.new
|
191
|
+
broker.add_subscriber(handler, ["Test1DomainEvent"])
|
192
|
+
broker.add_thread_subscriber(handler, ["Test1DomainEvent"])
|
193
|
+
|
194
|
+
event1 = Test1DomainEvent.new
|
195
|
+
broker.notify_subscribers(event1)
|
196
|
+
|
197
|
+
expect(handler.events).to eq([event1,event1])
|
198
|
+
end
|
199
|
+
|
189
200
|
private
|
190
201
|
|
191
202
|
class HandlerClass
|
@@ -1,256 +1,319 @@
|
|
1
|
-
|
1
|
+
class SRecord
|
2
|
+
def self.new(
|
3
|
+
event_id: SecureRandom.uuid,
|
4
|
+
data: SecureRandom.uuid,
|
5
|
+
metadata: SecureRandom.uuid,
|
6
|
+
event_type: SecureRandom.uuid
|
7
|
+
)
|
8
|
+
RubyEventStore::SerializedRecord.new(
|
9
|
+
event_id: event_id,
|
10
|
+
data: data,
|
11
|
+
metadata: metadata,
|
12
|
+
event_type: event_type,
|
13
|
+
)
|
14
|
+
end
|
15
|
+
end
|
2
16
|
|
3
17
|
RSpec.shared_examples :event_repository do |repository_class|
|
4
18
|
let(:repository) { subject || repository_class.new }
|
5
19
|
|
6
|
-
|
7
|
-
|
20
|
+
def read_stream_events_forward(repository, stream)
|
21
|
+
specification = RubyEventStore::Specification.new(repository)
|
22
|
+
repository.read(
|
23
|
+
specification
|
24
|
+
.stream(stream.name)
|
25
|
+
.result
|
26
|
+
).to_a
|
27
|
+
end
|
28
|
+
|
29
|
+
def read_stream_events_backward(repository, stream)
|
30
|
+
specification = RubyEventStore::Specification.new(repository)
|
31
|
+
repository.read(
|
32
|
+
specification
|
33
|
+
.stream(stream.name)
|
34
|
+
.backward
|
35
|
+
.result
|
36
|
+
).to_a
|
37
|
+
end
|
38
|
+
|
39
|
+
def read_events_forward(repository, stream, start, count)
|
40
|
+
specification = RubyEventStore::Specification.new(repository)
|
41
|
+
repository.read(
|
42
|
+
specification
|
43
|
+
.stream(stream.name)
|
44
|
+
.from(start)
|
45
|
+
.limit(count)
|
46
|
+
.result
|
47
|
+
).to_a
|
48
|
+
end
|
49
|
+
|
50
|
+
def read_events_backward(repository, stream, start, count)
|
51
|
+
specification = RubyEventStore::Specification.new(repository)
|
52
|
+
repository.read(
|
53
|
+
specification
|
54
|
+
.stream(stream.name)
|
55
|
+
.from(start)
|
56
|
+
.limit(count)
|
57
|
+
.backward
|
58
|
+
.result
|
59
|
+
).to_a
|
60
|
+
end
|
61
|
+
|
62
|
+
def read_all_streams_forward(repository, start, count)
|
63
|
+
specification = RubyEventStore::Specification.new(repository)
|
64
|
+
repository.read(
|
65
|
+
specification
|
66
|
+
.from(start)
|
67
|
+
.limit(count)
|
68
|
+
.result
|
69
|
+
).to_a
|
70
|
+
end
|
71
|
+
|
72
|
+
def read_all_streams_backward(repository, start, count)
|
73
|
+
specification = RubyEventStore::Specification.new(repository)
|
74
|
+
repository.read(
|
75
|
+
specification
|
76
|
+
.from(start)
|
77
|
+
.limit(count)
|
78
|
+
.backward
|
79
|
+
.result
|
80
|
+
).to_a
|
8
81
|
end
|
9
82
|
|
10
|
-
|
11
|
-
expect
|
12
|
-
repository.append_to_stream(event = TestDomainEvent.new, 'stream', nil)
|
13
|
-
end.to raise_error(RubyEventStore::InvalidExpectedVersion)
|
14
|
-
end
|
15
|
-
|
16
|
-
specify 'link_to_stream fail if expected version is nil' do
|
17
|
-
skip unless test_link_events_to_stream
|
18
|
-
repository.append_to_stream(event = TestDomainEvent.new, 'stream', :any)
|
19
|
-
expect do
|
20
|
-
repository.link_to_stream(event.event_id, 'stream', nil)
|
21
|
-
end.to raise_error(RubyEventStore::InvalidExpectedVersion)
|
83
|
+
it 'just created is empty' do
|
84
|
+
expect(read_all_streams_forward(repository, :head, 1)).to be_empty
|
22
85
|
end
|
23
86
|
|
24
87
|
specify 'append_to_stream returns self' do
|
25
88
|
repository.
|
26
|
-
append_to_stream(event =
|
27
|
-
append_to_stream(event =
|
89
|
+
append_to_stream(event = SRecord.new, RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.none).
|
90
|
+
append_to_stream(event = SRecord.new, RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.new(0))
|
28
91
|
end
|
29
92
|
|
30
93
|
specify 'link_to_stream returns self' do
|
31
94
|
skip unless test_link_events_to_stream
|
32
|
-
event0 =
|
33
|
-
event1 =
|
95
|
+
event0 = SRecord.new
|
96
|
+
event1 = SRecord.new
|
34
97
|
repository.
|
35
|
-
append_to_stream([event0, event1],
|
36
|
-
link_to_stream(event0.event_id,
|
37
|
-
link_to_stream(event1.event_id,
|
98
|
+
append_to_stream([event0, event1], RubyEventStore::Stream.new("stream0"), RubyEventStore::ExpectedVersion.none).
|
99
|
+
link_to_stream(event0.event_id, RubyEventStore::Stream.new("flow"), RubyEventStore::ExpectedVersion.none).
|
100
|
+
link_to_stream(event1.event_id, RubyEventStore::Stream.new("flow"), RubyEventStore::ExpectedVersion.new(0))
|
38
101
|
end
|
39
102
|
|
40
103
|
specify 'adds an initial event to a new stream' do
|
41
|
-
repository.append_to_stream(event =
|
42
|
-
expect(
|
43
|
-
expect(repository.
|
44
|
-
expect(repository.
|
104
|
+
repository.append_to_stream(event = SRecord.new, RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.none)
|
105
|
+
expect(read_all_streams_forward(repository, :head, 1).first).to eq(event)
|
106
|
+
expect(read_stream_events_forward(repository, RubyEventStore::Stream.new('stream')).first).to eq(event)
|
107
|
+
expect(read_stream_events_forward(repository, RubyEventStore::Stream.new("other_stream"))).to be_empty
|
45
108
|
end
|
46
109
|
|
47
110
|
specify 'links an initial event to a new stream' do
|
48
111
|
skip unless test_link_events_to_stream
|
49
112
|
repository.
|
50
|
-
append_to_stream(event =
|
51
|
-
link_to_stream(event.event_id,
|
113
|
+
append_to_stream(event = SRecord.new, RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.none).
|
114
|
+
link_to_stream(event.event_id, RubyEventStore::Stream.new("flow"), RubyEventStore::ExpectedVersion.none)
|
52
115
|
|
53
|
-
expect(
|
54
|
-
expect(repository.
|
55
|
-
expect(repository.
|
56
|
-
expect(repository.
|
116
|
+
expect(read_all_streams_forward(repository, :head, 1).first).to eq(event)
|
117
|
+
expect(read_stream_events_forward(repository, RubyEventStore::Stream.new('stream')).first).to eq(event)
|
118
|
+
expect(read_stream_events_forward(repository, RubyEventStore::Stream.new("flow"))).to eq([event])
|
119
|
+
expect(read_stream_events_forward(repository, RubyEventStore::Stream.new("other"))).to be_empty
|
57
120
|
end
|
58
121
|
|
59
122
|
specify 'adds multiple initial events to a new stream' do
|
60
123
|
repository.append_to_stream([
|
61
|
-
event0 =
|
62
|
-
event1 =
|
63
|
-
], 'stream',
|
64
|
-
expect(
|
65
|
-
expect(repository.
|
124
|
+
event0 = SRecord.new(event_id: SecureRandom.uuid),
|
125
|
+
event1 = SRecord.new(event_id: SecureRandom.uuid),
|
126
|
+
], RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.none)
|
127
|
+
expect(read_all_streams_forward(repository, :head, 2)).to eq([event0, event1])
|
128
|
+
expect(read_stream_events_forward(repository, RubyEventStore::Stream.new('stream'))).to eq([event0, event1])
|
66
129
|
end
|
67
130
|
|
68
131
|
specify 'links multiple initial events to a new stream' do
|
69
132
|
skip unless test_link_events_to_stream
|
70
133
|
repository.append_to_stream([
|
71
|
-
event0 =
|
72
|
-
event1 =
|
73
|
-
], 'stream',
|
134
|
+
event0 = SRecord.new(event_id: SecureRandom.uuid),
|
135
|
+
event1 = SRecord.new(event_id: SecureRandom.uuid),
|
136
|
+
], RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.none).link_to_stream([
|
74
137
|
event0.event_id,
|
75
138
|
event1.event_id,
|
76
|
-
],
|
77
|
-
expect(
|
78
|
-
expect(repository.
|
139
|
+
], RubyEventStore::Stream.new("flow"), RubyEventStore::ExpectedVersion.none)
|
140
|
+
expect(read_all_streams_forward(repository, :head, 2)).to eq([event0, event1])
|
141
|
+
expect(read_stream_events_forward(repository, RubyEventStore::Stream.new("flow"))).to eq([event0, event1])
|
79
142
|
end
|
80
143
|
|
81
144
|
specify 'correct expected version on second write' do
|
82
145
|
repository.append_to_stream([
|
83
|
-
event0 =
|
84
|
-
event1 =
|
85
|
-
], 'stream',
|
146
|
+
event0 = SRecord.new(event_id: SecureRandom.uuid),
|
147
|
+
event1 = SRecord.new(event_id: SecureRandom.uuid),
|
148
|
+
], RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.none)
|
86
149
|
repository.append_to_stream([
|
87
|
-
event2 =
|
88
|
-
event3 =
|
89
|
-
], 'stream', 1)
|
90
|
-
expect(
|
91
|
-
expect(repository.
|
150
|
+
event2 = SRecord.new(event_id: SecureRandom.uuid),
|
151
|
+
event3 = SRecord.new(event_id: SecureRandom.uuid),
|
152
|
+
], RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.new(1))
|
153
|
+
expect(read_all_streams_forward(repository, :head, 4)).to eq([event0, event1, event2, event3])
|
154
|
+
expect(read_stream_events_forward(repository, RubyEventStore::Stream.new('stream'))).to eq([event0, event1, event2, event3])
|
92
155
|
end
|
93
156
|
|
94
157
|
specify 'correct expected version on second link' do
|
95
158
|
skip unless test_link_events_to_stream
|
96
159
|
repository.append_to_stream([
|
97
|
-
event0 =
|
98
|
-
event1 =
|
99
|
-
], 'stream',
|
100
|
-
event2 =
|
101
|
-
event3 =
|
102
|
-
],
|
160
|
+
event0 = SRecord.new(event_id: SecureRandom.uuid),
|
161
|
+
event1 = SRecord.new(event_id: SecureRandom.uuid),
|
162
|
+
], RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.none).append_to_stream([
|
163
|
+
event2 = SRecord.new(event_id: SecureRandom.uuid),
|
164
|
+
event3 = SRecord.new(event_id: SecureRandom.uuid),
|
165
|
+
], RubyEventStore::Stream.new("flow"), RubyEventStore::ExpectedVersion.none).link_to_stream([
|
103
166
|
event0.event_id,
|
104
167
|
event1.event_id,
|
105
|
-
],
|
106
|
-
expect(
|
107
|
-
expect(repository.
|
168
|
+
], RubyEventStore::Stream.new("flow"), RubyEventStore::ExpectedVersion.new(1))
|
169
|
+
expect(read_all_streams_forward(repository, :head, 4)).to eq([event0, event1, event2, event3])
|
170
|
+
expect(read_stream_events_forward(repository, RubyEventStore::Stream.new("flow"))).to eq([event2, event3, event0, event1])
|
108
171
|
end
|
109
172
|
|
110
173
|
specify 'incorrect expected version on second write' do
|
111
174
|
repository.append_to_stream([
|
112
|
-
event0 =
|
113
|
-
event1 =
|
114
|
-
], 'stream',
|
175
|
+
event0 = SRecord.new(event_id: SecureRandom.uuid),
|
176
|
+
event1 = SRecord.new(event_id: SecureRandom.uuid),
|
177
|
+
], RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.none)
|
115
178
|
expect do
|
116
179
|
repository.append_to_stream([
|
117
|
-
event2 =
|
118
|
-
event3 =
|
119
|
-
], 'stream', 0)
|
180
|
+
event2 = SRecord.new(event_id: SecureRandom.uuid),
|
181
|
+
event3 = SRecord.new(event_id: SecureRandom.uuid),
|
182
|
+
], RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.new(0))
|
120
183
|
end.to raise_error(RubyEventStore::WrongExpectedEventVersion)
|
121
184
|
|
122
|
-
expect(
|
123
|
-
expect(repository.
|
185
|
+
expect(read_all_streams_forward(repository, :head, 4)).to eq([event0, event1])
|
186
|
+
expect(read_stream_events_forward(repository, RubyEventStore::Stream.new('stream'))).to eq([event0, event1])
|
124
187
|
end
|
125
188
|
|
126
189
|
specify 'incorrect expected version on second link' do
|
127
190
|
skip unless test_link_events_to_stream
|
128
191
|
repository.append_to_stream([
|
129
|
-
event0 =
|
130
|
-
event1 =
|
131
|
-
], 'stream',
|
192
|
+
event0 = SRecord.new(event_id: SecureRandom.uuid),
|
193
|
+
event1 = SRecord.new(event_id: SecureRandom.uuid),
|
194
|
+
], RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.none)
|
132
195
|
repository.append_to_stream([
|
133
|
-
event2 =
|
134
|
-
event3 =
|
135
|
-
],
|
196
|
+
event2 = SRecord.new(event_id: SecureRandom.uuid),
|
197
|
+
event3 = SRecord.new(event_id: SecureRandom.uuid),
|
198
|
+
], RubyEventStore::Stream.new("other"), RubyEventStore::ExpectedVersion.none)
|
136
199
|
expect do
|
137
200
|
repository.link_to_stream([
|
138
201
|
event2.event_id,
|
139
202
|
event3.event_id,
|
140
|
-
], 'stream', 0)
|
203
|
+
], RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.new(0))
|
141
204
|
end.to raise_error(RubyEventStore::WrongExpectedEventVersion)
|
142
205
|
|
143
|
-
expect(
|
144
|
-
expect(repository.
|
206
|
+
expect(read_all_streams_forward(repository, :head, 4)).to eq([event0, event1, event2, event3])
|
207
|
+
expect(read_stream_events_forward(repository, RubyEventStore::Stream.new('stream'))).to eq([event0, event1])
|
145
208
|
end
|
146
209
|
|
147
210
|
specify ':none on first and subsequent write' do
|
148
211
|
repository.append_to_stream([
|
149
|
-
eventA =
|
150
|
-
], 'stream',
|
212
|
+
eventA = SRecord.new(event_id: SecureRandom.uuid),
|
213
|
+
], RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.none)
|
151
214
|
expect do
|
152
215
|
repository.append_to_stream([
|
153
|
-
eventB =
|
154
|
-
], 'stream',
|
216
|
+
eventB = SRecord.new(event_id: SecureRandom.uuid),
|
217
|
+
], RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.none)
|
155
218
|
end.to raise_error(RubyEventStore::WrongExpectedEventVersion)
|
156
|
-
expect(
|
157
|
-
expect(repository.
|
219
|
+
expect(read_all_streams_forward(repository, :head, 1)).to eq([eventA])
|
220
|
+
expect(read_stream_events_forward(repository, RubyEventStore::Stream.new('stream'))).to eq([eventA])
|
158
221
|
end
|
159
222
|
|
160
223
|
specify ':none on first and subsequent link' do
|
161
224
|
skip unless test_link_events_to_stream
|
162
225
|
repository.append_to_stream([
|
163
|
-
eventA =
|
164
|
-
eventB =
|
165
|
-
], 'stream',
|
226
|
+
eventA = SRecord.new(event_id: SecureRandom.uuid),
|
227
|
+
eventB = SRecord.new(event_id: SecureRandom.uuid),
|
228
|
+
], RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.none)
|
166
229
|
|
167
|
-
repository.link_to_stream([eventA.event_id],
|
230
|
+
repository.link_to_stream([eventA.event_id], RubyEventStore::Stream.new("flow"), RubyEventStore::ExpectedVersion.none)
|
168
231
|
expect do
|
169
|
-
repository.link_to_stream([eventB.event_id],
|
232
|
+
repository.link_to_stream([eventB.event_id], RubyEventStore::Stream.new("flow"), RubyEventStore::ExpectedVersion.none)
|
170
233
|
end.to raise_error(RubyEventStore::WrongExpectedEventVersion)
|
171
234
|
|
172
|
-
expect(
|
173
|
-
expect(repository.
|
235
|
+
expect(read_all_streams_forward(repository, :head, 1)).to eq([eventA])
|
236
|
+
expect(read_stream_events_forward(repository, RubyEventStore::Stream.new("flow"))).to eq([eventA])
|
174
237
|
end
|
175
238
|
|
176
239
|
specify ':any allows stream with best-effort order and no guarantee' do
|
177
240
|
repository.append_to_stream([
|
178
|
-
event0 =
|
179
|
-
event1 =
|
180
|
-
], 'stream',
|
241
|
+
event0 = SRecord.new(event_id: SecureRandom.uuid),
|
242
|
+
event1 = SRecord.new(event_id: SecureRandom.uuid),
|
243
|
+
], RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.any)
|
181
244
|
repository.append_to_stream([
|
182
|
-
event2 =
|
183
|
-
event3 =
|
184
|
-
], 'stream',
|
185
|
-
expect(
|
186
|
-
expect(repository.
|
245
|
+
event2 = SRecord.new(event_id: SecureRandom.uuid),
|
246
|
+
event3 = SRecord.new(event_id: SecureRandom.uuid),
|
247
|
+
], RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.any)
|
248
|
+
expect(read_all_streams_forward(repository, :head, 4).to_set).to eq(Set.new([event0, event1, event2, event3]))
|
249
|
+
expect(read_stream_events_forward(repository, RubyEventStore::Stream.new('stream')).to_set).to eq(Set.new([event0, event1, event2, event3]))
|
187
250
|
end
|
188
251
|
|
189
252
|
specify ':any allows linking in stream with best-effort order and no guarantee' do
|
190
253
|
skip unless test_link_events_to_stream
|
191
254
|
repository.append_to_stream([
|
192
|
-
event0 =
|
193
|
-
event1 =
|
194
|
-
event2 =
|
195
|
-
event3 =
|
196
|
-
], 'stream',
|
255
|
+
event0 = SRecord.new(event_id: SecureRandom.uuid),
|
256
|
+
event1 = SRecord.new(event_id: SecureRandom.uuid),
|
257
|
+
event2 = SRecord.new(event_id: SecureRandom.uuid),
|
258
|
+
event3 = SRecord.new(event_id: SecureRandom.uuid),
|
259
|
+
], RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.any)
|
197
260
|
|
198
261
|
repository.link_to_stream([
|
199
262
|
event0.event_id, event1.event_id,
|
200
|
-
],
|
263
|
+
], RubyEventStore::Stream.new("flow"), RubyEventStore::ExpectedVersion.any)
|
201
264
|
repository.link_to_stream([
|
202
265
|
event2.event_id, event3.event_id,
|
203
|
-
],
|
266
|
+
], RubyEventStore::Stream.new("flow"), RubyEventStore::ExpectedVersion.any)
|
204
267
|
|
205
|
-
expect(
|
206
|
-
expect(repository.
|
268
|
+
expect(read_all_streams_forward(repository, :head, 4).to_set).to eq(Set.new([event0, event1, event2, event3]))
|
269
|
+
expect(read_stream_events_forward(repository, RubyEventStore::Stream.new("flow")).to_set).to eq(Set.new([event0, event1, event2, event3]))
|
207
270
|
end
|
208
271
|
|
209
272
|
specify ':auto queries for last position in given stream' do
|
210
273
|
skip unless test_expected_version_auto
|
211
274
|
repository.append_to_stream([
|
212
|
-
eventA =
|
213
|
-
eventB =
|
214
|
-
eventC =
|
215
|
-
],
|
275
|
+
eventA = SRecord.new(event_id: SecureRandom.uuid),
|
276
|
+
eventB = SRecord.new(event_id: SecureRandom.uuid),
|
277
|
+
eventC = SRecord.new(event_id: SecureRandom.uuid),
|
278
|
+
], RubyEventStore::Stream.new("another"), RubyEventStore::ExpectedVersion.auto)
|
216
279
|
repository.append_to_stream([
|
217
|
-
event0 =
|
218
|
-
event1 =
|
219
|
-
], 'stream',
|
280
|
+
event0 = SRecord.new(event_id: SecureRandom.uuid),
|
281
|
+
event1 = SRecord.new(event_id: SecureRandom.uuid),
|
282
|
+
], RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.auto)
|
220
283
|
repository.append_to_stream([
|
221
|
-
event2 =
|
222
|
-
event3 =
|
223
|
-
], 'stream', 1)
|
284
|
+
event2 = SRecord.new(event_id: SecureRandom.uuid),
|
285
|
+
event3 = SRecord.new(event_id: SecureRandom.uuid),
|
286
|
+
], RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.new(1))
|
224
287
|
end
|
225
288
|
|
226
289
|
specify ':auto queries for last position in given stream when linking' do
|
227
290
|
skip unless test_expected_version_auto
|
228
291
|
skip unless test_link_events_to_stream
|
229
292
|
repository.append_to_stream([
|
230
|
-
eventA =
|
231
|
-
eventB =
|
232
|
-
eventC =
|
233
|
-
],
|
293
|
+
eventA = SRecord.new(event_id: SecureRandom.uuid),
|
294
|
+
eventB = SRecord.new(event_id: SecureRandom.uuid),
|
295
|
+
eventC = SRecord.new(event_id: SecureRandom.uuid),
|
296
|
+
], RubyEventStore::Stream.new("another"), RubyEventStore::ExpectedVersion.auto)
|
234
297
|
repository.append_to_stream([
|
235
|
-
event0 =
|
236
|
-
event1 =
|
237
|
-
], 'stream',
|
298
|
+
event0 = SRecord.new(event_id: SecureRandom.uuid),
|
299
|
+
event1 = SRecord.new(event_id: SecureRandom.uuid),
|
300
|
+
], RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.auto)
|
238
301
|
repository.link_to_stream([
|
239
302
|
eventA.event_id,
|
240
303
|
eventB.event_id,
|
241
304
|
eventC.event_id,
|
242
|
-
], 'stream', 1)
|
305
|
+
], RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.new(1))
|
243
306
|
end
|
244
307
|
|
245
308
|
specify ':auto starts from 0' do
|
246
309
|
skip unless test_expected_version_auto
|
247
310
|
repository.append_to_stream([
|
248
|
-
event0 =
|
249
|
-
], 'stream',
|
311
|
+
event0 = SRecord.new(event_id: SecureRandom.uuid),
|
312
|
+
], RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.auto)
|
250
313
|
expect do
|
251
314
|
repository.append_to_stream([
|
252
|
-
event1 =
|
253
|
-
], 'stream',
|
315
|
+
event1 = SRecord.new(event_id: SecureRandom.uuid),
|
316
|
+
], RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.none)
|
254
317
|
end.to raise_error(RubyEventStore::WrongExpectedEventVersion)
|
255
318
|
end
|
256
319
|
|
@@ -258,15 +321,15 @@ RSpec.shared_examples :event_repository do |repository_class|
|
|
258
321
|
skip unless test_expected_version_auto
|
259
322
|
skip unless test_link_events_to_stream
|
260
323
|
repository.append_to_stream([
|
261
|
-
event0 =
|
262
|
-
],
|
324
|
+
event0 = SRecord.new(event_id: SecureRandom.uuid),
|
325
|
+
], RubyEventStore::Stream.new("whatever"), RubyEventStore::ExpectedVersion.auto)
|
263
326
|
repository.link_to_stream([
|
264
327
|
event0.event_id,
|
265
|
-
], 'stream',
|
328
|
+
], RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.auto)
|
266
329
|
expect do
|
267
330
|
repository.append_to_stream([
|
268
|
-
event1 =
|
269
|
-
], 'stream',
|
331
|
+
event1 = SRecord.new(event_id: SecureRandom.uuid),
|
332
|
+
], RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.none)
|
270
333
|
end.to raise_error(RubyEventStore::WrongExpectedEventVersion)
|
271
334
|
end
|
272
335
|
|
@@ -275,105 +338,105 @@ RSpec.shared_examples :event_repository do |repository_class|
|
|
275
338
|
# It is expected that there is higher level lock
|
276
339
|
# So this query is safe from race conditions
|
277
340
|
repository.append_to_stream([
|
278
|
-
event0 =
|
279
|
-
event1 =
|
280
|
-
], 'stream',
|
341
|
+
event0 = SRecord.new(event_id: SecureRandom.uuid),
|
342
|
+
event1 = SRecord.new(event_id: SecureRandom.uuid),
|
343
|
+
], RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.auto)
|
281
344
|
repository.append_to_stream([
|
282
|
-
event2 =
|
283
|
-
event3 =
|
284
|
-
], 'stream',
|
285
|
-
expect(
|
345
|
+
event2 = SRecord.new(event_id: SecureRandom.uuid),
|
346
|
+
event3 = SRecord.new(event_id: SecureRandom.uuid),
|
347
|
+
], RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.auto)
|
348
|
+
expect(read_all_streams_forward(repository, :head, 4)).to eq([
|
286
349
|
event0, event1,
|
287
350
|
event2, event3
|
288
351
|
])
|
289
|
-
expect(repository.
|
352
|
+
expect(read_stream_events_forward(repository, RubyEventStore::Stream.new('stream'))).to eq([event0, event1, event2, event3])
|
290
353
|
end
|
291
354
|
|
292
355
|
specify ':auto queries for last position and follows in incremental way when linking' do
|
293
356
|
skip unless test_expected_version_auto
|
294
357
|
skip unless test_link_events_to_stream
|
295
358
|
repository.append_to_stream([
|
296
|
-
event0 =
|
297
|
-
event1 =
|
298
|
-
event2 =
|
299
|
-
event3 =
|
300
|
-
], 'stream',
|
359
|
+
event0 = SRecord.new(event_id: SecureRandom.uuid),
|
360
|
+
event1 = SRecord.new(event_id: SecureRandom.uuid),
|
361
|
+
event2 = SRecord.new(event_id: SecureRandom.uuid),
|
362
|
+
event3 = SRecord.new(event_id: SecureRandom.uuid),
|
363
|
+
], RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.auto)
|
301
364
|
repository.link_to_stream([
|
302
365
|
event0.event_id, event1.event_id,
|
303
|
-
],
|
366
|
+
], RubyEventStore::Stream.new("flow"), RubyEventStore::ExpectedVersion.auto)
|
304
367
|
repository.link_to_stream([
|
305
368
|
event2.event_id, event3.event_id,
|
306
|
-
],
|
307
|
-
expect(
|
369
|
+
], RubyEventStore::Stream.new("flow"), RubyEventStore::ExpectedVersion.auto)
|
370
|
+
expect(read_all_streams_forward(repository, :head, 4)).to eq([
|
308
371
|
event0, event1,
|
309
372
|
event2, event3
|
310
373
|
])
|
311
|
-
expect(repository.
|
374
|
+
expect(read_stream_events_forward(repository, RubyEventStore::Stream.new("flow"))).to eq([event0, event1, event2, event3])
|
312
375
|
end
|
313
376
|
|
314
377
|
specify ':auto is compatible with manual expectation' do
|
315
378
|
skip unless test_expected_version_auto
|
316
379
|
repository.append_to_stream([
|
317
|
-
event0 =
|
318
|
-
event1 =
|
319
|
-
], 'stream',
|
380
|
+
event0 = SRecord.new(event_id: SecureRandom.uuid),
|
381
|
+
event1 = SRecord.new(event_id: SecureRandom.uuid),
|
382
|
+
], RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.auto)
|
320
383
|
repository.append_to_stream([
|
321
|
-
event2 =
|
322
|
-
event3 =
|
323
|
-
], 'stream', 1)
|
324
|
-
expect(
|
325
|
-
expect(repository.
|
384
|
+
event2 = SRecord.new(event_id: SecureRandom.uuid),
|
385
|
+
event3 = SRecord.new(event_id: SecureRandom.uuid),
|
386
|
+
], RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.new(1))
|
387
|
+
expect(read_all_streams_forward(repository, :head, 4)).to eq([event0, event1, event2, event3])
|
388
|
+
expect(read_stream_events_forward(repository, RubyEventStore::Stream.new('stream'))).to eq([event0, event1, event2, event3])
|
326
389
|
end
|
327
390
|
|
328
391
|
specify ':auto is compatible with manual expectation when linking' do
|
329
392
|
skip unless test_expected_version_auto
|
330
393
|
skip unless test_link_events_to_stream
|
331
394
|
repository.append_to_stream([
|
332
|
-
event0 =
|
333
|
-
event1 =
|
334
|
-
], 'stream',
|
395
|
+
event0 = SRecord.new(event_id: SecureRandom.uuid),
|
396
|
+
event1 = SRecord.new(event_id: SecureRandom.uuid),
|
397
|
+
], RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.auto)
|
335
398
|
repository.link_to_stream([
|
336
399
|
event0.event_id,
|
337
|
-
],
|
400
|
+
], RubyEventStore::Stream.new("flow"), RubyEventStore::ExpectedVersion.auto)
|
338
401
|
repository.link_to_stream([
|
339
402
|
event1.event_id,
|
340
|
-
],
|
341
|
-
expect(
|
342
|
-
expect(repository.
|
403
|
+
], RubyEventStore::Stream.new("flow"), RubyEventStore::ExpectedVersion.new(0))
|
404
|
+
expect(read_all_streams_forward(repository, :head, 4)).to eq([event0, event1,])
|
405
|
+
expect(read_stream_events_forward(repository, RubyEventStore::Stream.new("flow"))).to eq([event0, event1,])
|
343
406
|
end
|
344
407
|
|
345
408
|
specify 'manual is compatible with auto expectation' do
|
346
409
|
skip unless test_expected_version_auto
|
347
410
|
repository.append_to_stream([
|
348
|
-
event0 =
|
349
|
-
event1 =
|
350
|
-
], 'stream',
|
411
|
+
event0 = SRecord.new(event_id: SecureRandom.uuid),
|
412
|
+
event1 = SRecord.new(event_id: SecureRandom.uuid),
|
413
|
+
], RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.none)
|
351
414
|
repository.append_to_stream([
|
352
|
-
event2 =
|
353
|
-
event3 =
|
354
|
-
], 'stream',
|
355
|
-
expect(
|
356
|
-
expect(repository.
|
415
|
+
event2 = SRecord.new(event_id: SecureRandom.uuid),
|
416
|
+
event3 = SRecord.new(event_id: SecureRandom.uuid),
|
417
|
+
], RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.auto)
|
418
|
+
expect(read_all_streams_forward(repository, :head, 4)).to eq([event0, event1, event2, event3])
|
419
|
+
expect(read_stream_events_forward(repository, RubyEventStore::Stream.new('stream'))).to eq([event0, event1, event2, event3])
|
357
420
|
end
|
358
421
|
|
359
422
|
specify 'manual is compatible with auto expectation when linking' do
|
360
423
|
skip unless test_expected_version_auto
|
361
424
|
skip unless test_link_events_to_stream
|
362
425
|
repository.append_to_stream([
|
363
|
-
event0 =
|
364
|
-
event1 =
|
365
|
-
], 'stream',
|
426
|
+
event0 = SRecord.new(event_id: SecureRandom.uuid),
|
427
|
+
event1 = SRecord.new(event_id: SecureRandom.uuid),
|
428
|
+
], RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.auto)
|
366
429
|
repository.link_to_stream([
|
367
430
|
event0.event_id,
|
368
|
-
],
|
431
|
+
], RubyEventStore::Stream.new("flow"), RubyEventStore::ExpectedVersion.none)
|
369
432
|
repository.link_to_stream([
|
370
433
|
event1.event_id,
|
371
|
-
],
|
372
|
-
expect(
|
373
|
-
expect(repository.
|
434
|
+
], RubyEventStore::Stream.new("flow"), RubyEventStore::ExpectedVersion.auto)
|
435
|
+
expect(read_all_streams_forward(repository, :head, 4)).to eq([event0, event1])
|
436
|
+
expect(read_stream_events_forward(repository, RubyEventStore::Stream.new("flow"))).to eq([event0, event1])
|
374
437
|
end
|
375
438
|
|
376
|
-
specify 'unlimited concurrency for :any - everything should succeed' do
|
439
|
+
specify 'unlimited concurrency for :any - everything should succeed', timeout: 10, mutant: false do
|
377
440
|
skip unless test_race_conditions_any
|
378
441
|
verify_conncurency_assumptions
|
379
442
|
begin
|
@@ -389,8 +452,8 @@ RSpec.shared_examples :event_repository do |repository_class|
|
|
389
452
|
100.times do |j|
|
390
453
|
eid = "0000000#{i}-#{sprintf("%04d", j)}-0000-0000-000000000000"
|
391
454
|
repository.append_to_stream([
|
392
|
-
|
393
|
-
], 'stream',
|
455
|
+
SRecord.new(event_id: eid),
|
456
|
+
], RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.any)
|
394
457
|
end
|
395
458
|
rescue RubyEventStore::WrongExpectedEventVersion
|
396
459
|
fail_occurred = true
|
@@ -400,8 +463,8 @@ RSpec.shared_examples :event_repository do |repository_class|
|
|
400
463
|
wait_for_it = false
|
401
464
|
threads.each(&:join)
|
402
465
|
expect(fail_occurred).to eq(false)
|
403
|
-
expect(repository.
|
404
|
-
events_in_stream = repository.
|
466
|
+
expect(read_stream_events_forward(repository, RubyEventStore::Stream.new('stream')).size).to eq(400)
|
467
|
+
events_in_stream = read_stream_events_forward(repository, RubyEventStore::Stream.new('stream'))
|
405
468
|
expect(events_in_stream.size).to eq(400)
|
406
469
|
events0 = events_in_stream.select do |ev|
|
407
470
|
ev.event_id.start_with?("0-")
|
@@ -412,7 +475,7 @@ RSpec.shared_examples :event_repository do |repository_class|
|
|
412
475
|
end
|
413
476
|
end
|
414
477
|
|
415
|
-
specify 'unlimited concurrency for :any - everything should succeed when linking' do
|
478
|
+
specify 'unlimited concurrency for :any - everything should succeed when linking', timeout: 10, mutant: false do
|
416
479
|
skip unless test_race_conditions_any
|
417
480
|
skip unless test_link_events_to_stream
|
418
481
|
verify_conncurency_assumptions
|
@@ -426,8 +489,8 @@ RSpec.shared_examples :event_repository do |repository_class|
|
|
426
489
|
100.times do |j|
|
427
490
|
eid = "0000000#{i}-#{sprintf("%04d", j)}-0000-0000-000000000000"
|
428
491
|
repository.append_to_stream([
|
429
|
-
|
430
|
-
], 'stream',
|
492
|
+
SRecord.new(event_id: eid),
|
493
|
+
], RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.any)
|
431
494
|
end
|
432
495
|
end
|
433
496
|
|
@@ -437,7 +500,7 @@ RSpec.shared_examples :event_repository do |repository_class|
|
|
437
500
|
begin
|
438
501
|
100.times do |j|
|
439
502
|
eid = "0000000#{i}-#{sprintf("%04d", j)}-0000-0000-000000000000"
|
440
|
-
repository.link_to_stream(eid,
|
503
|
+
repository.link_to_stream(eid, RubyEventStore::Stream.new("flow"), RubyEventStore::ExpectedVersion.any)
|
441
504
|
end
|
442
505
|
rescue RubyEventStore::WrongExpectedEventVersion
|
443
506
|
fail_occurred = true
|
@@ -447,8 +510,8 @@ RSpec.shared_examples :event_repository do |repository_class|
|
|
447
510
|
wait_for_it = false
|
448
511
|
threads.each(&:join)
|
449
512
|
expect(fail_occurred).to eq(false)
|
450
|
-
expect(repository.
|
451
|
-
events_in_stream = repository.
|
513
|
+
expect(read_stream_events_forward(repository, RubyEventStore::Stream.new("flow")).size).to eq(400)
|
514
|
+
events_in_stream = read_stream_events_forward(repository, RubyEventStore::Stream.new("flow"))
|
452
515
|
expect(events_in_stream.size).to eq(400)
|
453
516
|
events0 = events_in_stream.select do |ev|
|
454
517
|
ev.event_id.start_with?("0-")
|
@@ -476,8 +539,8 @@ RSpec.shared_examples :event_repository do |repository_class|
|
|
476
539
|
begin
|
477
540
|
eid = "0000000#{i}-#{sprintf("%04d", j)}-0000-0000-000000000000"
|
478
541
|
repository.append_to_stream([
|
479
|
-
|
480
|
-
], 'stream',
|
542
|
+
SRecord.new(event_id: eid),
|
543
|
+
], RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.auto)
|
481
544
|
sleep(rand(concurrency_level) / 1000.0)
|
482
545
|
rescue RubyEventStore::WrongExpectedEventVersion
|
483
546
|
fail_occurred +=1
|
@@ -488,7 +551,7 @@ RSpec.shared_examples :event_repository do |repository_class|
|
|
488
551
|
wait_for_it = false
|
489
552
|
threads.each(&:join)
|
490
553
|
expect(fail_occurred).to be > 0
|
491
|
-
events_in_stream = repository.
|
554
|
+
events_in_stream = read_stream_events_forward(repository, RubyEventStore::Stream.new('stream'))
|
492
555
|
expect(events_in_stream.size).to be < 400
|
493
556
|
expect(events_in_stream.size).to be >= 100
|
494
557
|
events0 = events_in_stream.select do |ev|
|
@@ -514,8 +577,8 @@ RSpec.shared_examples :event_repository do |repository_class|
|
|
514
577
|
100.times do |j|
|
515
578
|
eid = "0000000#{i}-#{sprintf("%04d", j)}-0000-0000-000000000000"
|
516
579
|
repository.append_to_stream([
|
517
|
-
|
518
|
-
],
|
580
|
+
SRecord.new(event_id: eid),
|
581
|
+
], RubyEventStore::Stream.new("whatever"), RubyEventStore::ExpectedVersion.any)
|
519
582
|
end
|
520
583
|
end
|
521
584
|
|
@@ -528,7 +591,7 @@ RSpec.shared_examples :event_repository do |repository_class|
|
|
528
591
|
100.times do |j|
|
529
592
|
begin
|
530
593
|
eid = "0000000#{i}-#{sprintf("%04d", j)}-0000-0000-000000000000"
|
531
|
-
repository.link_to_stream(eid, 'stream',
|
594
|
+
repository.link_to_stream(eid, RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.auto)
|
532
595
|
sleep(rand(concurrency_level) / 1000.0)
|
533
596
|
rescue RubyEventStore::WrongExpectedEventVersion
|
534
597
|
fail_occurred +=1
|
@@ -539,7 +602,7 @@ RSpec.shared_examples :event_repository do |repository_class|
|
|
539
602
|
wait_for_it = false
|
540
603
|
threads.each(&:join)
|
541
604
|
expect(fail_occurred).to be > 0
|
542
|
-
events_in_stream = repository.
|
605
|
+
events_in_stream = read_stream_events_forward(repository, RubyEventStore::Stream.new('stream'))
|
543
606
|
expect(events_in_stream.size).to be < 400
|
544
607
|
expect(events_in_stream.size).to be >= 100
|
545
608
|
events0 = events_in_stream.select do |ev|
|
@@ -553,253 +616,292 @@ RSpec.shared_examples :event_repository do |repository_class|
|
|
553
616
|
end
|
554
617
|
|
555
618
|
it 'appended event is stored in given stream' do
|
556
|
-
expected_event =
|
557
|
-
repository.append_to_stream(expected_event, 'stream',
|
558
|
-
expect(
|
559
|
-
expect(repository.
|
560
|
-
expect(repository.
|
619
|
+
expected_event = SRecord.new
|
620
|
+
repository.append_to_stream(expected_event, RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.any)
|
621
|
+
expect(read_all_streams_forward(repository, :head, 1).first).to eq(expected_event)
|
622
|
+
expect(read_stream_events_forward(repository, RubyEventStore::Stream.new('stream')).first).to eq(expected_event)
|
623
|
+
expect(read_stream_events_forward(repository, RubyEventStore::Stream.new("other_stream"))).to be_empty
|
561
624
|
end
|
562
625
|
|
563
626
|
it 'data attributes are retrieved' do
|
564
|
-
event =
|
565
|
-
repository.append_to_stream(event, 'stream',
|
566
|
-
retrieved_event =
|
567
|
-
expect(retrieved_event.data
|
627
|
+
event = SRecord.new(data: "{ order_id: 3 }")
|
628
|
+
repository.append_to_stream(event, RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.any)
|
629
|
+
retrieved_event = read_all_streams_forward(repository, :head, 1).first
|
630
|
+
expect(retrieved_event.data).to eq("{ order_id: 3 }")
|
568
631
|
end
|
569
632
|
|
570
633
|
it 'metadata attributes are retrieved' do
|
571
|
-
event =
|
572
|
-
repository.append_to_stream(event, 'stream',
|
573
|
-
retrieved_event =
|
574
|
-
expect(retrieved_event.metadata
|
634
|
+
event = SRecord.new(metadata: "{ request_id: 3 }")
|
635
|
+
repository.append_to_stream(event, RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.any)
|
636
|
+
retrieved_event = read_all_streams_forward(repository, :head, 1).first
|
637
|
+
expect(retrieved_event.metadata).to eq("{ request_id: 3 }")
|
575
638
|
end
|
576
639
|
|
577
640
|
it 'data and metadata attributes are retrieved when linking' do
|
578
641
|
skip unless test_link_events_to_stream
|
579
|
-
event =
|
580
|
-
data: { order_id: 3 },
|
581
|
-
metadata: { request_id: 4 }
|
642
|
+
event = SRecord.new(
|
643
|
+
data: "{ order_id: 3 }",
|
644
|
+
metadata: "{ request_id: 4 }",
|
582
645
|
)
|
583
646
|
repository.
|
584
|
-
append_to_stream(event, 'stream',
|
585
|
-
link_to_stream(event.event_id,
|
586
|
-
retrieved_event = repository.
|
587
|
-
expect(retrieved_event.metadata
|
588
|
-
expect(retrieved_event.data
|
647
|
+
append_to_stream(event, RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.any).
|
648
|
+
link_to_stream(event.event_id, RubyEventStore::Stream.new("flow"), RubyEventStore::ExpectedVersion.any)
|
649
|
+
retrieved_event = read_stream_events_forward(repository, RubyEventStore::Stream.new("flow")).first
|
650
|
+
expect(retrieved_event.metadata).to eq("{ request_id: 4 }")
|
651
|
+
expect(retrieved_event.data).to eq("{ order_id: 3 }")
|
589
652
|
expect(event).to eq(retrieved_event)
|
590
653
|
end
|
591
654
|
|
592
655
|
it 'does not have deleted streams' do
|
593
|
-
repository.append_to_stream(e1 =
|
594
|
-
repository.append_to_stream(e2 =
|
656
|
+
repository.append_to_stream(e1 = SRecord.new, RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.none)
|
657
|
+
repository.append_to_stream(e2 = SRecord.new, RubyEventStore::Stream.new("other_stream"), RubyEventStore::ExpectedVersion.none)
|
595
658
|
|
596
|
-
repository.delete_stream('stream')
|
597
|
-
expect(repository.
|
598
|
-
expect(repository.
|
599
|
-
expect(
|
659
|
+
repository.delete_stream(RubyEventStore::Stream.new('stream'))
|
660
|
+
expect(read_stream_events_forward(repository, RubyEventStore::Stream.new('stream'))).to be_empty
|
661
|
+
expect(read_stream_events_forward(repository, RubyEventStore::Stream.new("other_stream"))).to eq([e2])
|
662
|
+
expect(read_all_streams_forward(repository, :head, 10)).to eq([e1,e2])
|
600
663
|
end
|
601
664
|
|
602
665
|
it 'does not have deleted streams with linked events' do
|
603
666
|
skip unless test_link_events_to_stream
|
604
667
|
repository.
|
605
|
-
append_to_stream(e1 =
|
606
|
-
link_to_stream(e1.event_id,
|
668
|
+
append_to_stream(e1 = SRecord.new, RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.none).
|
669
|
+
link_to_stream(e1.event_id, RubyEventStore::Stream.new("flow"), RubyEventStore::ExpectedVersion.none)
|
607
670
|
|
608
|
-
repository.delete_stream(
|
609
|
-
expect(repository.
|
610
|
-
expect(
|
671
|
+
repository.delete_stream(RubyEventStore::Stream.new("flow"))
|
672
|
+
expect(read_stream_events_forward(repository, RubyEventStore::Stream.new("flow"))).to be_empty
|
673
|
+
expect(read_all_streams_forward(repository, :head, 10)).to eq([e1])
|
611
674
|
end
|
612
675
|
|
613
676
|
it 'has or has not domain event' do
|
614
677
|
just_an_id = 'd5c134c2-db65-4e87-b6ea-d196f8f1a292'
|
615
|
-
repository.append_to_stream(
|
678
|
+
repository.append_to_stream(SRecord.new(event_id: just_an_id), RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.none)
|
616
679
|
|
617
680
|
expect(repository.has_event?(just_an_id)).to be_truthy
|
618
681
|
expect(repository.has_event?(just_an_id.clone)).to be_truthy
|
619
682
|
expect(repository.has_event?('any other id')).to be_falsey
|
620
683
|
|
621
|
-
repository.delete_stream('stream')
|
684
|
+
repository.delete_stream(RubyEventStore::Stream.new('stream'))
|
622
685
|
expect(repository.has_event?(just_an_id)).to be_truthy
|
623
686
|
expect(repository.has_event?(just_an_id.clone)).to be_truthy
|
624
687
|
end
|
625
688
|
|
626
689
|
it 'knows last event in stream' do
|
627
|
-
repository.append_to_stream(
|
628
|
-
repository.append_to_stream(
|
690
|
+
repository.append_to_stream(a =SRecord.new(event_id: '00000000-0000-0000-0000-000000000001'), RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.none)
|
691
|
+
repository.append_to_stream(b = SRecord.new(event_id: '00000000-0000-0000-0000-000000000002'), RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.new(0))
|
629
692
|
|
630
|
-
expect(repository.last_stream_event('stream')).to eq(
|
631
|
-
expect(repository.last_stream_event(
|
693
|
+
expect(repository.last_stream_event(RubyEventStore::Stream.new('stream'))).to eq(b)
|
694
|
+
expect(repository.last_stream_event(RubyEventStore::Stream.new("other_stream"))).to be_nil
|
632
695
|
end
|
633
696
|
|
634
697
|
it 'knows last event in stream when linked' do
|
635
698
|
skip unless test_link_events_to_stream
|
636
699
|
repository.append_to_stream([
|
637
|
-
e0 =
|
638
|
-
e1 =
|
700
|
+
e0 = SRecord.new(event_id: '00000000-0000-0000-0000-000000000001'),
|
701
|
+
e1 = SRecord.new(event_id: '00000000-0000-0000-0000-000000000002'),
|
639
702
|
],
|
640
|
-
'stream',
|
641
|
-
|
642
|
-
).link_to_stream([e1.event_id, e0.event_id],
|
643
|
-
expect(repository.last_stream_event(
|
703
|
+
RubyEventStore::Stream.new('stream'),
|
704
|
+
RubyEventStore::ExpectedVersion.none
|
705
|
+
).link_to_stream([e1.event_id, e0.event_id], RubyEventStore::Stream.new("flow"), RubyEventStore::ExpectedVersion.none)
|
706
|
+
expect(repository.last_stream_event(RubyEventStore::Stream.new("flow"))).to eq(e0)
|
644
707
|
end
|
645
708
|
|
646
709
|
it 'reads batch of events from stream forward & backward' do
|
647
|
-
|
648
|
-
|
649
|
-
|
710
|
+
events = %w[
|
711
|
+
96c920b1-cdd0-40f4-907c-861b9fff7d02
|
712
|
+
56404f79-0ba0-4aa0-8524-dc3436368ca0
|
713
|
+
6a54dd21-f9d8-4857-a195-f5588d9e406c
|
714
|
+
0e50a9cd-f981-4e39-93d5-697fc7285b98
|
715
|
+
d85589bc-b993-41d4-812f-fc631d9185d5
|
716
|
+
96bdacda-77dd-4d7d-973d-cbdaa5842855
|
717
|
+
94688199-e6b7-4180-bf8e-825b6808e6cc
|
718
|
+
68fab040-741e-4bc2-9cca-5b8855b0ca19
|
719
|
+
ab60114c-011d-4d58-ab31-7ba65d99975e
|
720
|
+
868cac42-3d19-4b39-84e8-cd32d65c2445
|
721
|
+
].map { |id| SRecord.new(event_id: id) }
|
722
|
+
repository.append_to_stream(SRecord.new, RubyEventStore::Stream.new("other_stream"), RubyEventStore::ExpectedVersion.none)
|
650
723
|
events.each.with_index do |event, index|
|
651
|
-
repository.append_to_stream(event, 'stream', index - 1)
|
724
|
+
repository.append_to_stream(event, RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.new(index - 1))
|
652
725
|
end
|
653
|
-
repository.append_to_stream(
|
726
|
+
repository.append_to_stream(SRecord.new, RubyEventStore::Stream.new("other_stream"), RubyEventStore::ExpectedVersion.new(0))
|
654
727
|
|
655
|
-
expect(repository.
|
656
|
-
expect(repository.
|
657
|
-
expect(repository.
|
658
|
-
expect(repository.
|
728
|
+
expect(read_events_forward(repository, RubyEventStore::Stream.new('stream'), :head, 3)).to eq(events.first(3))
|
729
|
+
expect(read_events_forward(repository, RubyEventStore::Stream.new('stream'), :head, 100)).to eq(events)
|
730
|
+
expect(read_events_forward(repository, RubyEventStore::Stream.new('stream'), events[4].event_id, 4)).to eq(events[5..8])
|
731
|
+
expect(read_events_forward(repository, RubyEventStore::Stream.new('stream'), events[4].event_id, 100)).to eq(events[5..9])
|
659
732
|
|
660
|
-
expect(repository.
|
661
|
-
expect(repository.
|
662
|
-
expect(repository.
|
663
|
-
expect(repository.
|
733
|
+
expect(read_events_backward(repository, RubyEventStore::Stream.new('stream'), :head, 3)).to eq(events.last(3).reverse)
|
734
|
+
expect(read_events_backward(repository, RubyEventStore::Stream.new('stream'), :head, 100)).to eq(events.reverse)
|
735
|
+
expect(read_events_backward(repository, RubyEventStore::Stream.new('stream'), events[4].event_id, 4)).to eq(events.first(4).reverse)
|
736
|
+
expect(read_events_backward(repository, RubyEventStore::Stream.new('stream'), events[4].event_id, 100)).to eq(events.first(4).reverse)
|
664
737
|
end
|
665
738
|
|
666
739
|
it 'reads batch of linked events from stream forward & backward' do
|
667
740
|
skip unless test_link_events_to_stream
|
668
|
-
|
669
|
-
|
670
|
-
|
741
|
+
events = %w[
|
742
|
+
96c920b1-cdd0-40f4-907c-861b9fff7d02
|
743
|
+
56404f79-0ba0-4aa0-8524-dc3436368ca0
|
744
|
+
6a54dd21-f9d8-4857-a195-f5588d9e406c
|
745
|
+
0e50a9cd-f981-4e39-93d5-697fc7285b98
|
746
|
+
d85589bc-b993-41d4-812f-fc631d9185d5
|
747
|
+
96bdacda-77dd-4d7d-973d-cbdaa5842855
|
748
|
+
94688199-e6b7-4180-bf8e-825b6808e6cc
|
749
|
+
68fab040-741e-4bc2-9cca-5b8855b0ca19
|
750
|
+
ab60114c-011d-4d58-ab31-7ba65d99975e
|
751
|
+
868cac42-3d19-4b39-84e8-cd32d65c2445
|
752
|
+
].map { |id| SRecord.new(event_id: id) }
|
753
|
+
repository.append_to_stream(SRecord.new, RubyEventStore::Stream.new("other_stream"), RubyEventStore::ExpectedVersion.none)
|
671
754
|
events.each.with_index do |event, index|
|
672
755
|
repository.
|
673
|
-
append_to_stream(event, 'stream', index - 1).
|
674
|
-
link_to_stream(event.event_id,
|
756
|
+
append_to_stream(event, RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.new(index - 1)).
|
757
|
+
link_to_stream(event.event_id, RubyEventStore::Stream.new("flow"), RubyEventStore::ExpectedVersion.new(index - 1))
|
675
758
|
end
|
676
|
-
repository.append_to_stream(
|
759
|
+
repository.append_to_stream(SRecord.new, RubyEventStore::Stream.new("other_stream"), RubyEventStore::ExpectedVersion.new(0))
|
677
760
|
|
678
|
-
expect(repository.
|
679
|
-
expect(repository.
|
680
|
-
expect(repository.
|
681
|
-
expect(repository.
|
761
|
+
expect(read_events_forward(repository, RubyEventStore::Stream.new("flow"), :head, 3)).to eq(events.first(3))
|
762
|
+
expect(read_events_forward(repository, RubyEventStore::Stream.new("flow"), :head, 100)).to eq(events)
|
763
|
+
expect(read_events_forward(repository, RubyEventStore::Stream.new("flow"), events[4].event_id, 4)).to eq(events[5..8])
|
764
|
+
expect(read_events_forward(repository, RubyEventStore::Stream.new("flow"), events[4].event_id, 100)).to eq(events[5..9])
|
682
765
|
|
683
|
-
expect(repository.
|
684
|
-
expect(repository.
|
685
|
-
expect(repository.
|
686
|
-
expect(repository.
|
766
|
+
expect(read_events_backward(repository, RubyEventStore::Stream.new("flow"), :head, 3)).to eq(events.last(3).reverse)
|
767
|
+
expect(read_events_backward(repository, RubyEventStore::Stream.new("flow"), :head, 100)).to eq(events.reverse)
|
768
|
+
expect(read_events_backward(repository, RubyEventStore::Stream.new("flow"), events[4].event_id, 4)).to eq(events.first(4).reverse)
|
769
|
+
expect(read_events_backward(repository, RubyEventStore::Stream.new("flow"), events[4].event_id, 100)).to eq(events.first(4).reverse)
|
687
770
|
end
|
688
771
|
|
689
772
|
it 'reads all stream events forward & backward' do
|
690
|
-
s1 = 'stream'
|
691
|
-
s2 =
|
773
|
+
s1 = RubyEventStore::Stream.new('stream')
|
774
|
+
s2 = RubyEventStore::Stream.new("other_stream")
|
692
775
|
repository.
|
693
|
-
append_to_stream(a =
|
694
|
-
append_to_stream(b =
|
695
|
-
append_to_stream(c =
|
696
|
-
append_to_stream(d =
|
697
|
-
append_to_stream(e =
|
776
|
+
append_to_stream(a = SRecord.new(event_id: '7010d298-ab69-4bb1-9251-f3466b5d1282'), s1, RubyEventStore::ExpectedVersion.none).
|
777
|
+
append_to_stream(b = SRecord.new(event_id: '34f88aca-aaba-4ca0-9256-8017b47528c5'), s2, RubyEventStore::ExpectedVersion.none).
|
778
|
+
append_to_stream(c = SRecord.new(event_id: '8e61c864-ceae-4684-8726-97c34eb8fc4f'), s1, RubyEventStore::ExpectedVersion.new(0)).
|
779
|
+
append_to_stream(d = SRecord.new(event_id: '30963ed9-6349-450b-ac9b-8ea50115b3bd'), s2, RubyEventStore::ExpectedVersion.new(0)).
|
780
|
+
append_to_stream(e = SRecord.new(event_id: '5bdc58b7-e8a7-4621-afd6-ccb828d72457'), s2, RubyEventStore::ExpectedVersion.new(1))
|
698
781
|
|
699
|
-
expect(
|
700
|
-
expect(
|
782
|
+
expect(read_stream_events_forward(repository, s1)).to eq [a,c]
|
783
|
+
expect(read_stream_events_backward(repository, s1)).to eq [c,a]
|
701
784
|
end
|
702
785
|
|
703
786
|
it 'reads all stream linked events forward & backward' do
|
704
787
|
skip unless test_link_events_to_stream
|
705
|
-
s1, fs1, fs2 = 'stream',
|
788
|
+
s1, fs1, fs2 = RubyEventStore::Stream.new('stream'), RubyEventStore::Stream.new("flow"), RubyEventStore::Stream.new("other_flow")
|
706
789
|
repository.
|
707
|
-
append_to_stream(a =
|
708
|
-
append_to_stream(b =
|
709
|
-
append_to_stream(c =
|
710
|
-
append_to_stream(d =
|
711
|
-
append_to_stream(e =
|
712
|
-
link_to_stream('7010d298-ab69-4bb1-9251-f3466b5d1282', fs1,
|
713
|
-
link_to_stream('34f88aca-aaba-4ca0-9256-8017b47528c5', fs2,
|
714
|
-
link_to_stream('8e61c864-ceae-4684-8726-97c34eb8fc4f', fs1, 0).
|
715
|
-
link_to_stream('30963ed9-6349-450b-ac9b-8ea50115b3bd', fs2, 0).
|
716
|
-
link_to_stream('5bdc58b7-e8a7-4621-afd6-ccb828d72457', fs2, 1)
|
790
|
+
append_to_stream(a = SRecord.new(event_id: '7010d298-ab69-4bb1-9251-f3466b5d1282'), s1, RubyEventStore::ExpectedVersion.none).
|
791
|
+
append_to_stream(b = SRecord.new(event_id: '34f88aca-aaba-4ca0-9256-8017b47528c5'), s1, RubyEventStore::ExpectedVersion.new(0)).
|
792
|
+
append_to_stream(c = SRecord.new(event_id: '8e61c864-ceae-4684-8726-97c34eb8fc4f'), s1, RubyEventStore::ExpectedVersion.new(1)).
|
793
|
+
append_to_stream(d = SRecord.new(event_id: '30963ed9-6349-450b-ac9b-8ea50115b3bd'), s1, RubyEventStore::ExpectedVersion.new(2)).
|
794
|
+
append_to_stream(e = SRecord.new(event_id: '5bdc58b7-e8a7-4621-afd6-ccb828d72457'), s1, RubyEventStore::ExpectedVersion.new(3)).
|
795
|
+
link_to_stream('7010d298-ab69-4bb1-9251-f3466b5d1282', fs1, RubyEventStore::ExpectedVersion.none).
|
796
|
+
link_to_stream('34f88aca-aaba-4ca0-9256-8017b47528c5', fs2, RubyEventStore::ExpectedVersion.none).
|
797
|
+
link_to_stream('8e61c864-ceae-4684-8726-97c34eb8fc4f', fs1, RubyEventStore::ExpectedVersion.new(0)).
|
798
|
+
link_to_stream('30963ed9-6349-450b-ac9b-8ea50115b3bd', fs2, RubyEventStore::ExpectedVersion.new(0)).
|
799
|
+
link_to_stream('5bdc58b7-e8a7-4621-afd6-ccb828d72457', fs2, RubyEventStore::ExpectedVersion.new(1))
|
717
800
|
|
718
|
-
expect(
|
719
|
-
expect(
|
801
|
+
expect(read_stream_events_forward(repository, fs1)).to eq [a,c]
|
802
|
+
expect(read_stream_events_backward(repository, fs1)).to eq [c,a]
|
720
803
|
end
|
721
804
|
|
722
805
|
it 'reads batch of events from all streams forward & backward' do
|
723
|
-
|
724
|
-
|
806
|
+
events = %w[
|
807
|
+
96c920b1-cdd0-40f4-907c-861b9fff7d02
|
808
|
+
56404f79-0ba0-4aa0-8524-dc3436368ca0
|
809
|
+
6a54dd21-f9d8-4857-a195-f5588d9e406c
|
810
|
+
0e50a9cd-f981-4e39-93d5-697fc7285b98
|
811
|
+
d85589bc-b993-41d4-812f-fc631d9185d5
|
812
|
+
96bdacda-77dd-4d7d-973d-cbdaa5842855
|
813
|
+
94688199-e6b7-4180-bf8e-825b6808e6cc
|
814
|
+
68fab040-741e-4bc2-9cca-5b8855b0ca19
|
815
|
+
ab60114c-011d-4d58-ab31-7ba65d99975e
|
816
|
+
868cac42-3d19-4b39-84e8-cd32d65c2445
|
817
|
+
].map { |id| SRecord.new(event_id: id) }
|
725
818
|
events.each do |ev|
|
726
|
-
repository.append_to_stream(ev, SecureRandom.uuid,
|
819
|
+
repository.append_to_stream(ev, RubyEventStore::Stream.new(SecureRandom.uuid), RubyEventStore::ExpectedVersion.none)
|
727
820
|
end
|
728
821
|
|
729
|
-
expect(
|
730
|
-
expect(
|
731
|
-
expect(
|
732
|
-
expect(
|
822
|
+
expect(read_all_streams_forward(repository, :head, 3)).to eq(events.first(3))
|
823
|
+
expect(read_all_streams_forward(repository, :head, 100)).to eq(events)
|
824
|
+
expect(read_all_streams_forward(repository, events[4].event_id, 4)).to eq(events[5..8])
|
825
|
+
expect(read_all_streams_forward(repository, events[4].event_id, 100)).to eq(events[5..9])
|
733
826
|
|
734
|
-
expect(
|
735
|
-
expect(
|
736
|
-
expect(
|
737
|
-
expect(
|
827
|
+
expect(read_all_streams_backward(repository, :head, 3)).to eq(events.last(3).reverse)
|
828
|
+
expect(read_all_streams_backward(repository, :head, 100)).to eq(events.reverse)
|
829
|
+
expect(read_all_streams_backward(repository, events[4].event_id, 4)).to eq(events.first(4).reverse)
|
830
|
+
expect(read_all_streams_backward(repository, events[4].event_id, 100)).to eq(events.first(4).reverse)
|
738
831
|
end
|
739
832
|
|
740
833
|
it 'linked events do not affect reading from all streams - no duplicates' do
|
741
834
|
skip unless test_link_events_to_stream
|
742
|
-
|
743
|
-
|
835
|
+
events = %w[
|
836
|
+
96c920b1-cdd0-40f4-907c-861b9fff7d02
|
837
|
+
56404f79-0ba0-4aa0-8524-dc3436368ca0
|
838
|
+
6a54dd21-f9d8-4857-a195-f5588d9e406c
|
839
|
+
0e50a9cd-f981-4e39-93d5-697fc7285b98
|
840
|
+
d85589bc-b993-41d4-812f-fc631d9185d5
|
841
|
+
96bdacda-77dd-4d7d-973d-cbdaa5842855
|
842
|
+
94688199-e6b7-4180-bf8e-825b6808e6cc
|
843
|
+
68fab040-741e-4bc2-9cca-5b8855b0ca19
|
844
|
+
ab60114c-011d-4d58-ab31-7ba65d99975e
|
845
|
+
868cac42-3d19-4b39-84e8-cd32d65c2445
|
846
|
+
].map { |id| SRecord.new(event_id: id) }
|
744
847
|
events.each do |ev|
|
745
848
|
repository.
|
746
|
-
append_to_stream(ev, SecureRandom.uuid,
|
747
|
-
link_to_stream(ev.event_id, SecureRandom.uuid,
|
849
|
+
append_to_stream(ev, RubyEventStore::Stream.new(SecureRandom.uuid), RubyEventStore::ExpectedVersion.none).
|
850
|
+
link_to_stream(ev.event_id, RubyEventStore::Stream.new(SecureRandom.uuid), RubyEventStore::ExpectedVersion.none)
|
748
851
|
end
|
749
852
|
|
750
|
-
expect(
|
751
|
-
expect(
|
752
|
-
expect(
|
753
|
-
expect(
|
853
|
+
expect(read_all_streams_forward(repository, :head, 3)).to eq(events.first(3))
|
854
|
+
expect(read_all_streams_forward(repository, :head, 100)).to eq(events)
|
855
|
+
expect(read_all_streams_forward(repository, events[4].event_id, 4)).to eq(events[5..8])
|
856
|
+
expect(read_all_streams_forward(repository, events[4].event_id, 100)).to eq(events[5..9])
|
754
857
|
|
755
|
-
expect(
|
756
|
-
expect(
|
757
|
-
expect(
|
758
|
-
expect(
|
858
|
+
expect(read_all_streams_backward(repository, :head, 3)).to eq(events.last(3).reverse)
|
859
|
+
expect(read_all_streams_backward(repository, :head, 100)).to eq(events.reverse)
|
860
|
+
expect(read_all_streams_backward(repository, events[4].event_id, 4)).to eq(events.first(4).reverse)
|
861
|
+
expect(read_all_streams_backward(repository, events[4].event_id, 100)).to eq(events.first(4).reverse)
|
759
862
|
end
|
760
863
|
|
761
864
|
it 'reads events different uuid object but same content' do
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
]
|
766
|
-
events
|
767
|
-
repository.append_to_stream(events.
|
768
|
-
repository.append_to_stream(events.last, 'stream', 0)
|
865
|
+
events = %w[
|
866
|
+
96c920b1-cdd0-40f4-907c-861b9fff7d02
|
867
|
+
56404f79-0ba0-4aa0-8524-dc3436368ca0
|
868
|
+
].map{|id| SRecord.new(event_id: id) }
|
869
|
+
repository.append_to_stream(events.first, RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.none)
|
870
|
+
repository.append_to_stream(events.last, RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.new(0))
|
769
871
|
|
770
|
-
expect(
|
771
|
-
expect(
|
872
|
+
expect(read_all_streams_forward(repository, "96c920b1-cdd0-40f4-907c-861b9fff7d02", 1)).to eq([events.last])
|
873
|
+
expect(read_all_streams_backward(repository, "56404f79-0ba0-4aa0-8524-dc3436368ca0", 1)).to eq([events.first])
|
772
874
|
|
773
|
-
expect(repository.
|
774
|
-
expect(repository.
|
875
|
+
expect(read_events_forward(repository, RubyEventStore::Stream.new('stream'), "96c920b1-cdd0-40f4-907c-861b9fff7d02", 1)).to eq([events.last])
|
876
|
+
expect(read_events_backward(repository, RubyEventStore::Stream.new('stream'), "56404f79-0ba0-4aa0-8524-dc3436368ca0", 1)).to eq([events.first])
|
775
877
|
end
|
776
878
|
|
777
879
|
it 'does not allow same event twice in a stream' do
|
778
880
|
repository.append_to_stream(
|
779
|
-
|
780
|
-
'stream',
|
781
|
-
|
881
|
+
SRecord.new(event_id: "a1b49edb-7636-416f-874a-88f94b859bef"),
|
882
|
+
RubyEventStore::Stream.new('stream'),
|
883
|
+
RubyEventStore::ExpectedVersion.none
|
782
884
|
)
|
783
885
|
expect do
|
784
886
|
repository.append_to_stream(
|
785
|
-
|
786
|
-
'stream',
|
787
|
-
0
|
887
|
+
SRecord.new(event_id: "a1b49edb-7636-416f-874a-88f94b859bef"),
|
888
|
+
RubyEventStore::Stream.new('stream'),
|
889
|
+
RubyEventStore::ExpectedVersion.new(0)
|
788
890
|
)
|
789
891
|
end.to raise_error(RubyEventStore::EventDuplicatedInStream)
|
790
892
|
end
|
791
893
|
|
792
894
|
it 'does not allow same event twice' do
|
793
895
|
repository.append_to_stream(
|
794
|
-
|
795
|
-
'stream',
|
796
|
-
|
896
|
+
SRecord.new(event_id: "a1b49edb-7636-416f-874a-88f94b859bef"),
|
897
|
+
RubyEventStore::Stream.new('stream'),
|
898
|
+
RubyEventStore::ExpectedVersion.none
|
797
899
|
)
|
798
900
|
expect do
|
799
901
|
repository.append_to_stream(
|
800
|
-
|
801
|
-
|
802
|
-
|
902
|
+
SRecord.new(event_id: "a1b49edb-7636-416f-874a-88f94b859bef"),
|
903
|
+
RubyEventStore::Stream.new("another"),
|
904
|
+
RubyEventStore::ExpectedVersion.none
|
803
905
|
)
|
804
906
|
end.to raise_error(RubyEventStore::EventDuplicatedInStream)
|
805
907
|
end
|
@@ -807,99 +909,42 @@ RSpec.shared_examples :event_repository do |repository_class|
|
|
807
909
|
it 'does not allow linking same event twice in a stream' do
|
808
910
|
skip unless test_link_events_to_stream
|
809
911
|
repository.append_to_stream([
|
810
|
-
|
811
|
-
], 'stream',
|
812
|
-
|
813
|
-
).link_to_stream("a1b49edb-7636-416f-874a-88f94b859bef",
|
912
|
+
SRecord.new(event_id: "a1b49edb-7636-416f-874a-88f94b859bef"),
|
913
|
+
], RubyEventStore::Stream.new('stream'),
|
914
|
+
RubyEventStore::ExpectedVersion.none
|
915
|
+
).link_to_stream("a1b49edb-7636-416f-874a-88f94b859bef", RubyEventStore::Stream.new("flow"), RubyEventStore::ExpectedVersion.none)
|
814
916
|
expect do
|
815
|
-
repository.link_to_stream("a1b49edb-7636-416f-874a-88f94b859bef",
|
917
|
+
repository.link_to_stream("a1b49edb-7636-416f-874a-88f94b859bef", RubyEventStore::Stream.new("flow"), RubyEventStore::ExpectedVersion.new(0))
|
816
918
|
end.to raise_error(RubyEventStore::EventDuplicatedInStream)
|
817
919
|
end
|
818
920
|
|
819
921
|
it 'allows appending to GLOBAL_STREAM explicitly' do
|
820
|
-
event =
|
821
|
-
repository.append_to_stream(event,
|
822
|
-
|
823
|
-
expect(repository.read_all_streams_forward(:head, 10)).to eq([event])
|
824
|
-
end
|
825
|
-
|
826
|
-
specify 'GLOBAL_STREAM is unordered, one cannot expect specific version number to work' do
|
827
|
-
expect {
|
828
|
-
event = TestDomainEvent.new(event_id: "df8b2ba3-4e2c-4888-8d14-4364855fa80e")
|
829
|
-
repository.append_to_stream(event, "all", 42)
|
830
|
-
}.to raise_error(RubyEventStore::InvalidExpectedVersion)
|
831
|
-
end
|
832
|
-
|
833
|
-
specify 'GLOBAL_STREAM is unordered, one cannot expect :none to work' do
|
834
|
-
expect {
|
835
|
-
event = TestDomainEvent.new(event_id: "df8b2ba3-4e2c-4888-8d14-4364855fa80e")
|
836
|
-
repository.append_to_stream(event, "all", :none)
|
837
|
-
}.to raise_error(RubyEventStore::InvalidExpectedVersion)
|
838
|
-
end
|
839
|
-
|
840
|
-
specify 'GLOBAL_STREAM is unordered, one cannot expect :auto to work' do
|
841
|
-
expect {
|
842
|
-
event = TestDomainEvent.new(event_id: "df8b2ba3-4e2c-4888-8d14-4364855fa80e")
|
843
|
-
repository.append_to_stream(event, "all", :auto)
|
844
|
-
}.to raise_error(RubyEventStore::InvalidExpectedVersion)
|
845
|
-
end
|
922
|
+
event = SRecord.new(event_id: "df8b2ba3-4e2c-4888-8d14-4364855fa80e")
|
923
|
+
repository.append_to_stream(event, RubyEventStore::Stream.new(RubyEventStore::GLOBAL_STREAM), RubyEventStore::ExpectedVersion.any)
|
846
924
|
|
847
|
-
|
848
|
-
[Object.new, SecureRandom.uuid, :foo].each do |invalid_expected_version|
|
849
|
-
expect {
|
850
|
-
repository.append_to_stream(
|
851
|
-
TestDomainEvent.new(event_id: SecureRandom.uuid),
|
852
|
-
'some_stream',
|
853
|
-
invalid_expected_version
|
854
|
-
)
|
855
|
-
}.to raise_error(RubyEventStore::InvalidExpectedVersion)
|
856
|
-
end
|
857
|
-
end
|
858
|
-
|
859
|
-
specify "only :none, :any, :auto and Integer allowed as expected_version when linking" do
|
860
|
-
skip unless test_link_events_to_stream
|
861
|
-
[Object.new, SecureRandom.uuid, :foo].each do |invalid_expected_version|
|
862
|
-
repository.append_to_stream(
|
863
|
-
TestDomainEvent.new(event_id: evid = SecureRandom.uuid),
|
864
|
-
SecureRandom.uuid,
|
865
|
-
-1
|
866
|
-
)
|
867
|
-
expect {
|
868
|
-
repository.link_to_stream(evid, SecureRandom.uuid, invalid_expected_version)
|
869
|
-
}.to raise_error(RubyEventStore::InvalidExpectedVersion)
|
870
|
-
end
|
925
|
+
expect(read_all_streams_forward(repository, :head, 10)).to eq([event])
|
871
926
|
end
|
872
927
|
|
873
928
|
specify "events not persisted if append failed" do
|
874
929
|
repository.append_to_stream([
|
875
|
-
|
876
|
-
], 'stream',
|
930
|
+
SRecord.new(event_id: SecureRandom.uuid),
|
931
|
+
], RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.none)
|
877
932
|
|
878
933
|
expect do
|
879
934
|
repository.append_to_stream([
|
880
|
-
|
935
|
+
SRecord.new(
|
881
936
|
event_id: '9bedf448-e4d0-41a3-a8cd-f94aec7aa763'
|
882
937
|
),
|
883
|
-
], 'stream',
|
938
|
+
], RubyEventStore::Stream.new('stream'), RubyEventStore::ExpectedVersion.none)
|
884
939
|
end.to raise_error(RubyEventStore::WrongExpectedEventVersion)
|
885
940
|
expect(repository.has_event?('9bedf448-e4d0-41a3-a8cd-f94aec7aa763')).to be_falsey
|
886
941
|
end
|
887
942
|
|
888
|
-
specify "all stream always present" do
|
889
|
-
expect(repository.get_all_streams).to match_array([RubyEventStore::Stream.new("all")])
|
890
|
-
end
|
891
|
-
|
892
|
-
specify "reading all existing stream names" do
|
893
|
-
repository.append_to_stream(TestDomainEvent.new, "test", -1)
|
894
|
-
repository.append_to_stream(TestDomainEvent.new, "test", 0)
|
895
|
-
expect(repository.get_all_streams).to match_array([RubyEventStore::Stream.new("all"), RubyEventStore::Stream.new("test")])
|
896
|
-
end
|
897
|
-
|
898
943
|
specify 'reading particular event' do
|
899
|
-
test_event =
|
944
|
+
test_event = SRecord.new(event_id: "941cd8f5-b3f9-47af-b4e4-07f8cea37467")
|
900
945
|
repository.
|
901
|
-
append_to_stream(
|
902
|
-
append_to_stream(test_event, "test", 0)
|
946
|
+
append_to_stream(SRecord.new, RubyEventStore::Stream.new("test"), RubyEventStore::ExpectedVersion.none).
|
947
|
+
append_to_stream(test_event, RubyEventStore::Stream.new("test"), RubyEventStore::ExpectedVersion.new(0))
|
903
948
|
|
904
949
|
expect(repository.read_event("941cd8f5-b3f9-47af-b4e4-07f8cea37467")).to eq(test_event)
|
905
950
|
end
|
@@ -917,7 +962,7 @@ RSpec.shared_examples :event_repository do |repository_class|
|
|
917
962
|
specify 'linking non-existent event' do
|
918
963
|
skip unless test_link_events_to_stream
|
919
964
|
expect do
|
920
|
-
repository.link_to_stream('72922e65-1b32-4e97-8023-03ae81dd3a27', "flow",
|
965
|
+
repository.link_to_stream('72922e65-1b32-4e97-8023-03ae81dd3a27', RubyEventStore::Stream.new("flow"), RubyEventStore::ExpectedVersion.none)
|
921
966
|
end.to raise_error do |err|
|
922
967
|
expect(err).to be_a(RubyEventStore::EventNotFound)
|
923
968
|
expect(err.event_id).to eq('72922e65-1b32-4e97-8023-03ae81dd3a27')
|
@@ -925,7 +970,23 @@ RSpec.shared_examples :event_repository do |repository_class|
|
|
925
970
|
end
|
926
971
|
end
|
927
972
|
|
928
|
-
specify '
|
929
|
-
|
973
|
+
specify 'read returns enumerator' do
|
974
|
+
specification = RubyEventStore::Specification.new(repository)
|
975
|
+
expect(repository.read(specification.result)).to be_kind_of(Enumerator)
|
976
|
+
end
|
977
|
+
|
978
|
+
specify 'can store arbitrary binary data' do
|
979
|
+
skip unless test_binary
|
980
|
+
migrate_to_binary
|
981
|
+
binary = "\xB0"
|
982
|
+
expect(binary.valid_encoding?).to eq(false)
|
983
|
+
binary.force_encoding("binary")
|
984
|
+
expect(binary.valid_encoding?).to eq(true)
|
985
|
+
|
986
|
+
repository.append_to_stream(
|
987
|
+
event = SRecord.new(data: binary, metadata: binary),
|
988
|
+
RubyEventStore::Stream.new('stream'),
|
989
|
+
RubyEventStore::ExpectedVersion.none
|
990
|
+
)
|
930
991
|
end
|
931
992
|
end
|