ruby_event_store 0.27.1 → 0.28.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|