ruby_event_store 1.2.2 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +3 -1
- data/lib/ruby_event_store.rb +3 -7
- data/lib/ruby_event_store/broker.rb +3 -3
- data/lib/ruby_event_store/client.rb +47 -23
- data/lib/ruby_event_store/composed_dispatcher.rb +2 -2
- data/lib/ruby_event_store/constants.rb +1 -0
- data/lib/ruby_event_store/errors.rb +0 -1
- data/lib/ruby_event_store/event.rb +8 -1
- data/lib/ruby_event_store/immediate_async_dispatcher.rb +2 -2
- data/lib/ruby_event_store/in_memory_repository.rb +98 -59
- data/lib/ruby_event_store/instrumented_dispatcher.rb +2 -2
- data/lib/ruby_event_store/instrumented_repository.rb +3 -3
- data/lib/ruby_event_store/mappers/default.rb +3 -8
- data/lib/ruby_event_store/mappers/encryption_mapper.rb +3 -4
- data/lib/ruby_event_store/mappers/instrumented_mapper.rb +4 -4
- data/lib/ruby_event_store/mappers/json_mapper.rb +7 -7
- data/lib/ruby_event_store/mappers/pipeline.rb +2 -5
- data/lib/ruby_event_store/mappers/pipeline_mapper.rb +2 -2
- data/lib/ruby_event_store/mappers/transformation/domain_event.rb +16 -8
- data/lib/ruby_event_store/mappers/transformation/encryption.rb +20 -12
- data/lib/ruby_event_store/mappers/transformation/event_class_remapper.rb +11 -4
- data/lib/ruby_event_store/mappers/transformation/stringify_metadata_keys.rb +12 -7
- data/lib/ruby_event_store/mappers/transformation/symbolize_metadata_keys.rb +12 -7
- data/lib/ruby_event_store/mappers/transformation/upcast.rb +37 -0
- data/lib/ruby_event_store/null.rb +13 -0
- data/lib/ruby_event_store/projection.rb +2 -1
- data/lib/ruby_event_store/record.rb +68 -0
- data/lib/ruby_event_store/serialized_record.rb +23 -4
- data/lib/ruby_event_store/spec/broker_lint.rb +9 -9
- data/lib/ruby_event_store/spec/event_repository_lint.rb +267 -105
- data/lib/ruby_event_store/spec/mapper_lint.rb +6 -6
- data/lib/ruby_event_store/spec/subscriptions_lint.rb +25 -0
- data/lib/ruby_event_store/specification.rb +100 -7
- data/lib/ruby_event_store/specification_reader.rb +2 -2
- data/lib/ruby_event_store/specification_result.rb +86 -2
- data/lib/ruby_event_store/subscriptions.rb +23 -9
- data/lib/ruby_event_store/transform_keys.rb +5 -5
- data/lib/ruby_event_store/version.rb +1 -1
- metadata +15 -21
- data/CHANGELOG.md +0 -93
- data/Gemfile +0 -11
- data/Makefile +0 -22
- data/lib/ruby_event_store/mappers/protobuf.rb +0 -24
- data/lib/ruby_event_store/mappers/transformation/item.rb +0 -56
- data/lib/ruby_event_store/mappers/transformation/proto_event.rb +0 -17
- data/lib/ruby_event_store/mappers/transformation/protobuf_encoder.rb +0 -30
- data/lib/ruby_event_store/mappers/transformation/protobuf_nested_struct_metadata.rb +0 -30
- data/lib/ruby_event_store/mappers/transformation/serialization.rb +0 -34
- data/lib/ruby_event_store/mappers/transformation/serialized_record.rb +0 -27
- data/ruby_event_store.gemspec +0 -29
@@ -3,18 +3,20 @@
|
|
3
3
|
module RubyEventStore
|
4
4
|
class SerializedRecord
|
5
5
|
StringsRequired = Class.new(StandardError)
|
6
|
-
def initialize(event_id:, data:, metadata:, event_type:)
|
6
|
+
def initialize(event_id:, data:, metadata:, event_type:, timestamp:, valid_at:)
|
7
7
|
raise StringsRequired unless [event_id, event_type].all? { |v| v.instance_of?(String) }
|
8
8
|
@event_id = event_id
|
9
9
|
@data = data
|
10
10
|
@metadata = metadata
|
11
11
|
@event_type = event_type
|
12
|
+
@timestamp = timestamp
|
13
|
+
@valid_at = valid_at
|
12
14
|
freeze
|
13
15
|
end
|
14
16
|
|
15
|
-
attr_reader :event_id, :data, :metadata, :event_type
|
17
|
+
attr_reader :event_id, :data, :metadata, :event_type, :timestamp, :valid_at
|
16
18
|
|
17
|
-
BIG_VALUE =
|
19
|
+
BIG_VALUE = 0b110011100100000010010010110011101011110101010101001100111110111
|
18
20
|
def hash
|
19
21
|
[
|
20
22
|
self.class,
|
@@ -22,6 +24,8 @@ module RubyEventStore
|
|
22
24
|
data,
|
23
25
|
metadata,
|
24
26
|
event_type,
|
27
|
+
timestamp,
|
28
|
+
valid_at,
|
25
29
|
].hash ^ BIG_VALUE
|
26
30
|
end
|
27
31
|
|
@@ -30,7 +34,9 @@ module RubyEventStore
|
|
30
34
|
other.event_id.eql?(event_id) &&
|
31
35
|
other.data.eql?(data) &&
|
32
36
|
other.metadata.eql?(metadata) &&
|
33
|
-
other.event_type.eql?(event_type)
|
37
|
+
other.event_type.eql?(event_type) &&
|
38
|
+
other.timestamp.eql?(timestamp) &&
|
39
|
+
other.valid_at.eql?(valid_at)
|
34
40
|
end
|
35
41
|
|
36
42
|
def to_h
|
@@ -39,9 +45,22 @@ module RubyEventStore
|
|
39
45
|
data: data,
|
40
46
|
metadata: metadata,
|
41
47
|
event_type: event_type,
|
48
|
+
timestamp: timestamp,
|
49
|
+
valid_at: valid_at,
|
42
50
|
}
|
43
51
|
end
|
44
52
|
|
53
|
+
def deserialize(serializer)
|
54
|
+
Record.new(
|
55
|
+
event_id: event_id,
|
56
|
+
event_type: event_type,
|
57
|
+
data: serializer.load(data),
|
58
|
+
metadata: serializer.load(metadata),
|
59
|
+
timestamp: Time.iso8601(timestamp),
|
60
|
+
valid_at: Time.iso8601(valid_at),
|
61
|
+
)
|
62
|
+
end
|
63
|
+
|
45
64
|
alias_method :eql?, :==
|
46
65
|
end
|
47
66
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
RSpec.shared_examples :broker do |broker_klass|
|
2
2
|
let(:event) { instance_double(::RubyEventStore::Event, event_type: 'EventType') }
|
3
|
-
let(:
|
3
|
+
let(:record) { instance_double(::RubyEventStore::Record) }
|
4
4
|
let(:handler) { HandlerClass.new }
|
5
5
|
let(:subscriptions) { ::RubyEventStore::Subscriptions.new }
|
6
6
|
let(:dispatcher) { ::RubyEventStore::Dispatcher.new }
|
@@ -9,26 +9,26 @@ RSpec.shared_examples :broker do |broker_klass|
|
|
9
9
|
specify "no dispatch when no subscriptions" do
|
10
10
|
expect(subscriptions).to receive(:all_for).with('EventType').and_return([])
|
11
11
|
expect(dispatcher).not_to receive(:call)
|
12
|
-
broker.call(event,
|
12
|
+
broker.call(event, record)
|
13
13
|
end
|
14
14
|
|
15
15
|
specify "calls subscription" do
|
16
16
|
expect(subscriptions).to receive(:all_for).with('EventType').and_return([handler])
|
17
|
-
expect(dispatcher).to receive(:call).with(handler, event,
|
18
|
-
broker.call(event,
|
17
|
+
expect(dispatcher).to receive(:call).with(handler, event, record)
|
18
|
+
broker.call(event, record)
|
19
19
|
end
|
20
20
|
|
21
21
|
specify "calls subscribed class" do
|
22
22
|
expect(subscriptions).to receive(:all_for).with('EventType').and_return([HandlerClass])
|
23
|
-
expect(dispatcher).to receive(:call).with(HandlerClass, event,
|
24
|
-
broker.call(event,
|
23
|
+
expect(dispatcher).to receive(:call).with(HandlerClass, event, record)
|
24
|
+
broker.call(event, record)
|
25
25
|
end
|
26
26
|
|
27
27
|
specify "calls all subscriptions" do
|
28
28
|
expect(subscriptions).to receive(:all_for).with('EventType').and_return([handler, HandlerClass])
|
29
|
-
expect(dispatcher).to receive(:call).with(handler, event,
|
30
|
-
expect(dispatcher).to receive(:call).with(HandlerClass, event,
|
31
|
-
broker.call(event,
|
29
|
+
expect(dispatcher).to receive(:call).with(handler, event, record)
|
30
|
+
expect(dispatcher).to receive(:call).with(HandlerClass, event, record)
|
31
|
+
broker.call(event, record)
|
32
32
|
end
|
33
33
|
|
34
34
|
specify 'raise error when no subscriber' do
|
@@ -3,15 +3,19 @@ module RubyEventStore
|
|
3
3
|
class SRecord
|
4
4
|
def self.new(
|
5
5
|
event_id: SecureRandom.uuid,
|
6
|
-
data:
|
7
|
-
metadata:
|
8
|
-
event_type: 'SRecordTestEvent'
|
6
|
+
data: {},
|
7
|
+
metadata: {},
|
8
|
+
event_type: 'SRecordTestEvent',
|
9
|
+
timestamp: Time.new.utc,
|
10
|
+
valid_at: nil
|
9
11
|
)
|
10
|
-
|
12
|
+
Record.new(
|
11
13
|
event_id: event_id,
|
12
14
|
data: data,
|
13
15
|
metadata: metadata,
|
14
16
|
event_type: event_type,
|
17
|
+
timestamp: timestamp.round(TIMESTAMP_PRECISION),
|
18
|
+
valid_at: (valid_at || timestamp).round(TIMESTAMP_PRECISION),
|
15
19
|
)
|
16
20
|
end
|
17
21
|
end
|
@@ -22,13 +26,45 @@ module RubyEventStore
|
|
22
26
|
Type2 = Class.new(RubyEventStore::Event)
|
23
27
|
# @private
|
24
28
|
Type3 = Class.new(RubyEventStore::Event)
|
29
|
+
|
30
|
+
# @private
|
31
|
+
class EventRepositoryHelper
|
32
|
+
def supports_concurrent_auto?
|
33
|
+
true
|
34
|
+
end
|
35
|
+
|
36
|
+
def supports_concurrent_any?
|
37
|
+
true
|
38
|
+
end
|
39
|
+
|
40
|
+
def supports_binary?
|
41
|
+
true
|
42
|
+
end
|
43
|
+
|
44
|
+
def supports_upsert?
|
45
|
+
true
|
46
|
+
end
|
47
|
+
|
48
|
+
def has_connection_pooling?
|
49
|
+
false
|
50
|
+
end
|
51
|
+
|
52
|
+
def connection_pool_size
|
53
|
+
end
|
54
|
+
|
55
|
+
def cleanup_concurrency_test
|
56
|
+
end
|
57
|
+
|
58
|
+
def rescuable_concurrency_test_errors
|
59
|
+
[]
|
60
|
+
end
|
61
|
+
end
|
25
62
|
end
|
26
63
|
|
27
64
|
module RubyEventStore
|
28
|
-
RSpec.shared_examples :event_repository do
|
29
|
-
let(:
|
30
|
-
let(:
|
31
|
-
let(:specification) { Specification.new(SpecificationReader.new(repository, mapper)) }
|
65
|
+
::RSpec.shared_examples :event_repository do
|
66
|
+
let(:helper) { EventRepositoryHelper.new }
|
67
|
+
let(:specification) { Specification.new(SpecificationReader.new(repository, Mappers::NullMapper.new)) }
|
32
68
|
let(:global_stream) { Stream.new(GLOBAL_STREAM) }
|
33
69
|
let(:stream) { Stream.new(SecureRandom.uuid) }
|
34
70
|
let(:stream_flow) { Stream.new('flow') }
|
@@ -42,6 +78,11 @@ module RubyEventStore
|
|
42
78
|
let(:version_2) { ExpectedVersion.new(2) }
|
43
79
|
let(:version_3) { ExpectedVersion.new(3) }
|
44
80
|
|
81
|
+
def verify_conncurency_assumptions
|
82
|
+
return unless helper.has_connection_pooling?
|
83
|
+
expect(helper.connection_pool_size).to eq(5)
|
84
|
+
end
|
85
|
+
|
45
86
|
def read_events(scope, stream = nil, from: nil, to: nil, count: nil)
|
46
87
|
scope = scope.stream(stream.name) if stream
|
47
88
|
scope = scope.from(from) if from
|
@@ -64,8 +105,8 @@ module RubyEventStore
|
|
64
105
|
|
65
106
|
specify 'append_to_stream returns self' do
|
66
107
|
repository
|
67
|
-
.append_to_stream(event = SRecord.new, stream, version_none)
|
68
|
-
.append_to_stream(event = SRecord.new, stream, version_0)
|
108
|
+
.append_to_stream([event = SRecord.new], stream, version_none)
|
109
|
+
.append_to_stream([event = SRecord.new], stream, version_0)
|
69
110
|
end
|
70
111
|
|
71
112
|
specify 'link_to_stream returns self' do
|
@@ -73,12 +114,12 @@ module RubyEventStore
|
|
73
114
|
event1 = SRecord.new
|
74
115
|
repository
|
75
116
|
.append_to_stream([event0, event1], stream, version_none)
|
76
|
-
.link_to_stream(event0.event_id, stream_flow, version_none)
|
77
|
-
.link_to_stream(event1.event_id, stream_flow, version_0)
|
117
|
+
.link_to_stream([event0.event_id], stream_flow, version_none)
|
118
|
+
.link_to_stream([event1.event_id], stream_flow, version_0)
|
78
119
|
end
|
79
120
|
|
80
121
|
specify 'adds an initial event to a new stream' do
|
81
|
-
repository.append_to_stream(event = SRecord.new, stream, version_none)
|
122
|
+
repository.append_to_stream([event = SRecord.new], stream, version_none)
|
82
123
|
expect(read_events_forward(repository).first).to eq(event)
|
83
124
|
expect(read_events_forward(repository, stream).first).to eq(event)
|
84
125
|
expect(read_events_forward(repository, stream_other)).to be_empty
|
@@ -86,8 +127,8 @@ module RubyEventStore
|
|
86
127
|
|
87
128
|
specify 'links an initial event to a new stream' do
|
88
129
|
repository
|
89
|
-
.append_to_stream(event = SRecord.new, stream, version_none)
|
90
|
-
.link_to_stream(event.event_id, stream_flow, version_none)
|
130
|
+
.append_to_stream([event = SRecord.new], stream, version_none)
|
131
|
+
.link_to_stream([event.event_id], stream_flow, version_none)
|
91
132
|
|
92
133
|
expect(read_events_forward(repository, count: 1).first).to eq(event)
|
93
134
|
expect(read_events_forward(repository, stream).first).to eq(event)
|
@@ -393,7 +434,7 @@ module RubyEventStore
|
|
393
434
|
end
|
394
435
|
|
395
436
|
specify 'unlimited concurrency for :any - everything should succeed', timeout: 10, mutant: false do
|
396
|
-
skip unless
|
437
|
+
skip unless helper.supports_concurrent_any?
|
397
438
|
verify_conncurency_assumptions
|
398
439
|
begin
|
399
440
|
concurrency_level = 4
|
@@ -426,12 +467,12 @@ module RubyEventStore
|
|
426
467
|
end
|
427
468
|
expect(events0).to eq(events0.sort_by{|ev| ev.event_id })
|
428
469
|
ensure
|
429
|
-
cleanup_concurrency_test
|
470
|
+
helper.cleanup_concurrency_test
|
430
471
|
end
|
431
472
|
end
|
432
473
|
|
433
474
|
specify 'unlimited concurrency for :any - everything should succeed when linking', timeout: 10, mutant: false do
|
434
|
-
skip unless
|
475
|
+
skip unless helper.supports_concurrent_any?
|
435
476
|
verify_conncurency_assumptions
|
436
477
|
begin
|
437
478
|
concurrency_level = 4
|
@@ -453,7 +494,7 @@ module RubyEventStore
|
|
453
494
|
begin
|
454
495
|
100.times do |j|
|
455
496
|
eid = "0000000#{i}-#{sprintf("%04d", j)}-0000-0000-000000000000"
|
456
|
-
repository.link_to_stream(eid, stream_flow, version_any)
|
497
|
+
repository.link_to_stream([eid], stream_flow, version_any)
|
457
498
|
end
|
458
499
|
rescue WrongExpectedEventVersion
|
459
500
|
fail_occurred = true
|
@@ -471,12 +512,12 @@ module RubyEventStore
|
|
471
512
|
end
|
472
513
|
expect(events0).to eq(events0.sort_by{|ev| ev.event_id })
|
473
514
|
ensure
|
474
|
-
cleanup_concurrency_test
|
515
|
+
helper.cleanup_concurrency_test
|
475
516
|
end
|
476
517
|
end
|
477
518
|
|
478
519
|
specify 'limited concurrency for :auto - some operations will fail without outside lock, stream is ordered', mutant: false do
|
479
|
-
skip unless
|
520
|
+
skip unless helper.supports_concurrent_auto?
|
480
521
|
verify_conncurency_assumptions
|
481
522
|
begin
|
482
523
|
concurrency_level = 4
|
@@ -494,7 +535,7 @@ module RubyEventStore
|
|
494
535
|
SRecord.new(event_id: eid),
|
495
536
|
], stream, version_auto)
|
496
537
|
sleep(rand(concurrency_level) / 1000.0)
|
497
|
-
rescue WrongExpectedEventVersion, *rescuable_concurrency_test_errors
|
538
|
+
rescue WrongExpectedEventVersion, *helper.rescuable_concurrency_test_errors
|
498
539
|
fail_occurred +=1
|
499
540
|
end
|
500
541
|
end
|
@@ -510,14 +551,14 @@ module RubyEventStore
|
|
510
551
|
ev.event_id.start_with?("0-")
|
511
552
|
end
|
512
553
|
expect(events0).to eq(events0.sort_by{|ev| ev.event_id })
|
513
|
-
additional_limited_concurrency_for_auto_check
|
554
|
+
additional_limited_concurrency_for_auto_check if defined? additional_limited_concurrency_for_auto_check
|
514
555
|
ensure
|
515
|
-
cleanup_concurrency_test
|
556
|
+
helper.cleanup_concurrency_test
|
516
557
|
end
|
517
558
|
end
|
518
559
|
|
519
560
|
specify 'limited concurrency for :auto - some operations will fail without outside lock, stream is ordered', mutant: false do
|
520
|
-
skip unless
|
561
|
+
skip unless helper.supports_concurrent_auto?
|
521
562
|
verify_conncurency_assumptions
|
522
563
|
begin
|
523
564
|
concurrency_level = 4
|
@@ -540,9 +581,9 @@ module RubyEventStore
|
|
540
581
|
100.times do |j|
|
541
582
|
begin
|
542
583
|
eid = "0000000#{i}-#{sprintf("%04d", j)}-0000-0000-000000000000"
|
543
|
-
repository.link_to_stream(eid, stream, version_auto)
|
584
|
+
repository.link_to_stream([eid], stream, version_auto)
|
544
585
|
sleep(rand(concurrency_level) / 1000.0)
|
545
|
-
rescue WrongExpectedEventVersion, *rescuable_concurrency_test_errors
|
586
|
+
rescue WrongExpectedEventVersion, *helper.rescuable_concurrency_test_errors
|
546
587
|
fail_occurred +=1
|
547
588
|
end
|
548
589
|
end
|
@@ -558,51 +599,51 @@ module RubyEventStore
|
|
558
599
|
ev.event_id.start_with?("0-")
|
559
600
|
end
|
560
601
|
expect(events0).to eq(events0.sort_by{|ev| ev.event_id })
|
561
|
-
additional_limited_concurrency_for_auto_check
|
602
|
+
additional_limited_concurrency_for_auto_check if defined? additional_limited_concurrency_for_auto_check
|
562
603
|
ensure
|
563
|
-
cleanup_concurrency_test
|
604
|
+
helper.cleanup_concurrency_test
|
564
605
|
end
|
565
606
|
end
|
566
607
|
|
567
608
|
it 'appended event is stored in given stream' do
|
568
609
|
expected_event = SRecord.new
|
569
|
-
repository.append_to_stream(expected_event, stream, version_any)
|
610
|
+
repository.append_to_stream([expected_event], stream, version_any)
|
570
611
|
expect(read_events_forward(repository, count: 1).first).to eq(expected_event)
|
571
612
|
expect(read_events_forward(repository, stream).first).to eq(expected_event)
|
572
613
|
expect(read_events_forward(repository, stream_other)).to be_empty
|
573
614
|
end
|
574
615
|
|
575
616
|
it 'data attributes are retrieved' do
|
576
|
-
event = SRecord.new(data:
|
577
|
-
repository.append_to_stream(event, stream, version_any)
|
617
|
+
event = SRecord.new(data: { "order_id" => 3 })
|
618
|
+
repository.append_to_stream([event], stream, version_any)
|
578
619
|
retrieved_event = read_events_forward(repository, count: 1).first
|
579
|
-
expect(retrieved_event.data).to eq(
|
620
|
+
expect(retrieved_event.data).to eq({ "order_id" => 3 })
|
580
621
|
end
|
581
622
|
|
582
623
|
it 'metadata attributes are retrieved' do
|
583
|
-
event = SRecord.new(metadata:
|
584
|
-
repository.append_to_stream(event, stream, version_any)
|
624
|
+
event = SRecord.new(metadata: { "request_id" => 3 })
|
625
|
+
repository.append_to_stream([event], stream, version_any)
|
585
626
|
retrieved_event = read_events_forward(repository, count: 1).first
|
586
|
-
expect(retrieved_event.metadata).to eq(
|
627
|
+
expect(retrieved_event.metadata).to eq({ "request_id" => 3 })
|
587
628
|
end
|
588
629
|
|
589
630
|
it 'data and metadata attributes are retrieved when linking' do
|
590
631
|
event = SRecord.new(
|
591
|
-
data:
|
592
|
-
metadata:
|
632
|
+
data: { "order_id" => 3 },
|
633
|
+
metadata: { "request_id" => 4},
|
593
634
|
)
|
594
635
|
repository
|
595
|
-
.append_to_stream(event, stream, version_any)
|
596
|
-
.link_to_stream(event.event_id, stream_flow, version_any)
|
636
|
+
.append_to_stream([event], stream, version_any)
|
637
|
+
.link_to_stream([event.event_id], stream_flow, version_any)
|
597
638
|
retrieved_event = read_events_forward(repository, stream_flow).first
|
598
|
-
expect(retrieved_event.metadata).to eq(
|
599
|
-
expect(retrieved_event.data).to eq(
|
639
|
+
expect(retrieved_event.metadata).to eq({ "request_id" => 4 })
|
640
|
+
expect(retrieved_event.data).to eq({ "order_id" => 3 })
|
600
641
|
expect(event).to eq(retrieved_event)
|
601
642
|
end
|
602
643
|
|
603
644
|
it 'does not have deleted streams' do
|
604
|
-
repository.append_to_stream(e1 = SRecord.new, stream, version_none)
|
605
|
-
repository.append_to_stream(e2 = SRecord.new, stream_other, version_none)
|
645
|
+
repository.append_to_stream([e1 = SRecord.new], stream, version_none)
|
646
|
+
repository.append_to_stream([e2 = SRecord.new], stream_other, version_none)
|
606
647
|
|
607
648
|
repository.delete_stream(stream)
|
608
649
|
expect(read_events_forward(repository, stream)).to be_empty
|
@@ -612,8 +653,8 @@ module RubyEventStore
|
|
612
653
|
|
613
654
|
it 'does not have deleted streams with linked events' do
|
614
655
|
repository
|
615
|
-
.append_to_stream(e1 = SRecord.new, stream, version_none)
|
616
|
-
.link_to_stream(e1.event_id, stream_flow, version_none)
|
656
|
+
.append_to_stream([e1 = SRecord.new], stream, version_none)
|
657
|
+
.link_to_stream([e1.event_id], stream_flow, version_none)
|
617
658
|
|
618
659
|
repository.delete_stream(stream_flow)
|
619
660
|
expect(read_events_forward(repository, stream_flow)).to be_empty
|
@@ -622,7 +663,7 @@ module RubyEventStore
|
|
622
663
|
|
623
664
|
it 'has or has not domain event' do
|
624
665
|
just_an_id = 'd5c134c2-db65-4e87-b6ea-d196f8f1a292'
|
625
|
-
repository.append_to_stream(SRecord.new(event_id: just_an_id), stream, version_none)
|
666
|
+
repository.append_to_stream([SRecord.new(event_id: just_an_id)], stream, version_none)
|
626
667
|
|
627
668
|
expect(repository.has_event?(just_an_id)).to be_truthy
|
628
669
|
expect(repository.has_event?(just_an_id.clone)).to be_truthy
|
@@ -634,8 +675,8 @@ module RubyEventStore
|
|
634
675
|
end
|
635
676
|
|
636
677
|
it 'knows last event in stream' do
|
637
|
-
repository.append_to_stream(a =SRecord.new(event_id: '00000000-0000-0000-0000-000000000001'), stream, version_none)
|
638
|
-
repository.append_to_stream(b = SRecord.new(event_id: '00000000-0000-0000-0000-000000000002'), stream, version_0)
|
678
|
+
repository.append_to_stream([a =SRecord.new(event_id: '00000000-0000-0000-0000-000000000001')], stream, version_none)
|
679
|
+
repository.append_to_stream([b = SRecord.new(event_id: '00000000-0000-0000-0000-000000000002')], stream, version_0)
|
639
680
|
|
640
681
|
expect(repository.last_stream_event(stream)).to eq(b)
|
641
682
|
expect(repository.last_stream_event(stream_other)).to be_nil
|
@@ -665,11 +706,11 @@ module RubyEventStore
|
|
665
706
|
ab60114c-011d-4d58-ab31-7ba65d99975e
|
666
707
|
868cac42-3d19-4b39-84e8-cd32d65c2445
|
667
708
|
].map { |id| SRecord.new(event_id: id) }
|
668
|
-
repository.append_to_stream(SRecord.new, stream_other, version_none)
|
709
|
+
repository.append_to_stream([SRecord.new], stream_other, version_none)
|
669
710
|
events.each.with_index do |event, index|
|
670
|
-
repository.append_to_stream(event, stream, ExpectedVersion.new(index - 1))
|
711
|
+
repository.append_to_stream([event], stream, ExpectedVersion.new(index - 1))
|
671
712
|
end
|
672
|
-
repository.append_to_stream(SRecord.new, stream_other, version_0)
|
713
|
+
repository.append_to_stream([SRecord.new], stream_other, version_0)
|
673
714
|
|
674
715
|
expect(read_events_forward(repository, stream, count: 3)).to eq(events.first(3))
|
675
716
|
expect(read_events_forward(repository, stream, count: 100)).to eq(events)
|
@@ -700,13 +741,13 @@ module RubyEventStore
|
|
700
741
|
ab60114c-011d-4d58-ab31-7ba65d99975e
|
701
742
|
868cac42-3d19-4b39-84e8-cd32d65c2445
|
702
743
|
].map { |id| SRecord.new(event_id: id) }
|
703
|
-
repository.append_to_stream(SRecord.new, stream_other, version_none)
|
744
|
+
repository.append_to_stream([SRecord.new], stream_other, version_none)
|
704
745
|
events.each.with_index do |event, index|
|
705
746
|
repository
|
706
|
-
.append_to_stream(event, stream, ExpectedVersion.new(index - 1))
|
707
|
-
.link_to_stream(event.event_id, stream_flow, ExpectedVersion.new(index - 1))
|
747
|
+
.append_to_stream([event], stream, ExpectedVersion.new(index - 1))
|
748
|
+
.link_to_stream([event.event_id], stream_flow, ExpectedVersion.new(index - 1))
|
708
749
|
end
|
709
|
-
repository.append_to_stream(SRecord.new, stream_other, version_0)
|
750
|
+
repository.append_to_stream([SRecord.new], stream_other, version_0)
|
710
751
|
|
711
752
|
expect(read_events_forward(repository, stream_flow, count: 3)).to eq(events.first(3))
|
712
753
|
expect(read_events_forward(repository, stream_flow, count: 100)).to eq(events)
|
@@ -727,11 +768,11 @@ module RubyEventStore
|
|
727
768
|
s1 = stream
|
728
769
|
s2 = stream_other
|
729
770
|
repository
|
730
|
-
.append_to_stream(a = SRecord.new(event_id: '7010d298-ab69-4bb1-9251-f3466b5d1282'), s1, version_none)
|
731
|
-
.append_to_stream(b = SRecord.new(event_id: '34f88aca-aaba-4ca0-9256-8017b47528c5'), s2, version_none)
|
732
|
-
.append_to_stream(c = SRecord.new(event_id: '8e61c864-ceae-4684-8726-97c34eb8fc4f'), s1, version_0)
|
733
|
-
.append_to_stream(d = SRecord.new(event_id: '30963ed9-6349-450b-ac9b-8ea50115b3bd'), s2, version_0)
|
734
|
-
.append_to_stream(e = SRecord.new(event_id: '5bdc58b7-e8a7-4621-afd6-ccb828d72457'), s2, version_1)
|
771
|
+
.append_to_stream([a = SRecord.new(event_id: '7010d298-ab69-4bb1-9251-f3466b5d1282')], s1, version_none)
|
772
|
+
.append_to_stream([b = SRecord.new(event_id: '34f88aca-aaba-4ca0-9256-8017b47528c5')], s2, version_none)
|
773
|
+
.append_to_stream([c = SRecord.new(event_id: '8e61c864-ceae-4684-8726-97c34eb8fc4f')], s1, version_0)
|
774
|
+
.append_to_stream([d = SRecord.new(event_id: '30963ed9-6349-450b-ac9b-8ea50115b3bd')], s2, version_0)
|
775
|
+
.append_to_stream([e = SRecord.new(event_id: '5bdc58b7-e8a7-4621-afd6-ccb828d72457')], s2, version_1)
|
735
776
|
|
736
777
|
expect(read_events_forward(repository, s1)).to eq [a,c]
|
737
778
|
expect(read_events_backward(repository, s1)).to eq [c,a]
|
@@ -740,16 +781,16 @@ module RubyEventStore
|
|
740
781
|
it 'reads all stream linked events forward & backward' do
|
741
782
|
s1, fs1, fs2 = stream, stream_flow, stream_other
|
742
783
|
repository
|
743
|
-
.append_to_stream(a = SRecord.new(event_id: '7010d298-ab69-4bb1-9251-f3466b5d1282'), s1, version_none)
|
744
|
-
.append_to_stream(b = SRecord.new(event_id: '34f88aca-aaba-4ca0-9256-8017b47528c5'), s1, version_0)
|
745
|
-
.append_to_stream(c = SRecord.new(event_id: '8e61c864-ceae-4684-8726-97c34eb8fc4f'), s1, version_1)
|
746
|
-
.append_to_stream(d = SRecord.new(event_id: '30963ed9-6349-450b-ac9b-8ea50115b3bd'), s1, version_2)
|
747
|
-
.append_to_stream(e = SRecord.new(event_id: '5bdc58b7-e8a7-4621-afd6-ccb828d72457'), s1, version_3)
|
748
|
-
.link_to_stream('7010d298-ab69-4bb1-9251-f3466b5d1282', fs1, version_none)
|
749
|
-
.link_to_stream('34f88aca-aaba-4ca0-9256-8017b47528c5', fs2, version_none)
|
750
|
-
.link_to_stream('8e61c864-ceae-4684-8726-97c34eb8fc4f', fs1, version_0)
|
751
|
-
.link_to_stream('30963ed9-6349-450b-ac9b-8ea50115b3bd', fs2, version_0)
|
752
|
-
.link_to_stream('5bdc58b7-e8a7-4621-afd6-ccb828d72457', fs2, version_1)
|
784
|
+
.append_to_stream([a = SRecord.new(event_id: '7010d298-ab69-4bb1-9251-f3466b5d1282')], s1, version_none)
|
785
|
+
.append_to_stream([b = SRecord.new(event_id: '34f88aca-aaba-4ca0-9256-8017b47528c5')], s1, version_0)
|
786
|
+
.append_to_stream([c = SRecord.new(event_id: '8e61c864-ceae-4684-8726-97c34eb8fc4f')], s1, version_1)
|
787
|
+
.append_to_stream([d = SRecord.new(event_id: '30963ed9-6349-450b-ac9b-8ea50115b3bd')], s1, version_2)
|
788
|
+
.append_to_stream([e = SRecord.new(event_id: '5bdc58b7-e8a7-4621-afd6-ccb828d72457')], s1, version_3)
|
789
|
+
.link_to_stream(['7010d298-ab69-4bb1-9251-f3466b5d1282'], fs1, version_none)
|
790
|
+
.link_to_stream(['34f88aca-aaba-4ca0-9256-8017b47528c5'], fs2, version_none)
|
791
|
+
.link_to_stream(['8e61c864-ceae-4684-8726-97c34eb8fc4f'], fs1, version_0)
|
792
|
+
.link_to_stream(['30963ed9-6349-450b-ac9b-8ea50115b3bd'], fs2, version_0)
|
793
|
+
.link_to_stream(['5bdc58b7-e8a7-4621-afd6-ccb828d72457'], fs2, version_1)
|
753
794
|
|
754
795
|
expect(read_events_forward(repository, fs1)).to eq [a,c]
|
755
796
|
expect(read_events_backward(repository, fs1)).to eq [c,a]
|
@@ -769,7 +810,7 @@ module RubyEventStore
|
|
769
810
|
868cac42-3d19-4b39-84e8-cd32d65c2445
|
770
811
|
].map { |id| SRecord.new(event_id: id) }
|
771
812
|
events.each do |ev|
|
772
|
-
repository.append_to_stream(ev, Stream.new(SecureRandom.uuid), version_none)
|
813
|
+
repository.append_to_stream([ev], Stream.new(SecureRandom.uuid), version_none)
|
773
814
|
end
|
774
815
|
|
775
816
|
expect(read_events_forward(repository, count: 3)).to eq(events.first(3))
|
@@ -802,8 +843,8 @@ module RubyEventStore
|
|
802
843
|
].map { |id| SRecord.new(event_id: id) }
|
803
844
|
events.each do |ev|
|
804
845
|
repository
|
805
|
-
.append_to_stream(ev, Stream.new(SecureRandom.uuid), version_none)
|
806
|
-
.link_to_stream(ev.event_id, Stream.new(SecureRandom.uuid), version_none)
|
846
|
+
.append_to_stream([ev], Stream.new(SecureRandom.uuid), version_none)
|
847
|
+
.link_to_stream([ev.event_id], Stream.new(SecureRandom.uuid), version_none)
|
807
848
|
end
|
808
849
|
|
809
850
|
expect(read_events_forward(repository, count: 3)).to eq(events.first(3))
|
@@ -826,8 +867,8 @@ module RubyEventStore
|
|
826
867
|
96c920b1-cdd0-40f4-907c-861b9fff7d02
|
827
868
|
56404f79-0ba0-4aa0-8524-dc3436368ca0
|
828
869
|
].map{|id| SRecord.new(event_id: id) }
|
829
|
-
repository.append_to_stream(events.first, stream, version_none)
|
830
|
-
repository.append_to_stream(events.last, stream, version_0)
|
870
|
+
repository.append_to_stream([events.first], stream, version_none)
|
871
|
+
repository.append_to_stream([events.last], stream, version_0)
|
831
872
|
|
832
873
|
expect(read_events_forward(repository, from: "96c920b1-cdd0-40f4-907c-861b9fff7d02")).to eq([events.last])
|
833
874
|
expect(read_events_backward(repository, from: "56404f79-0ba0-4aa0-8524-dc3436368ca0")).to eq([events.first])
|
@@ -842,13 +883,13 @@ module RubyEventStore
|
|
842
883
|
|
843
884
|
it 'does not allow same event twice in a stream' do
|
844
885
|
repository.append_to_stream(
|
845
|
-
SRecord.new(event_id: "a1b49edb-7636-416f-874a-88f94b859bef"),
|
886
|
+
[SRecord.new(event_id: "a1b49edb-7636-416f-874a-88f94b859bef")],
|
846
887
|
stream,
|
847
888
|
version_none
|
848
889
|
)
|
849
890
|
expect do
|
850
891
|
repository.append_to_stream(
|
851
|
-
SRecord.new(event_id: "a1b49edb-7636-416f-874a-88f94b859bef"),
|
892
|
+
[SRecord.new(event_id: "a1b49edb-7636-416f-874a-88f94b859bef")],
|
852
893
|
stream,
|
853
894
|
version_0
|
854
895
|
)
|
@@ -857,13 +898,13 @@ module RubyEventStore
|
|
857
898
|
|
858
899
|
it 'does not allow same event twice' do
|
859
900
|
repository.append_to_stream(
|
860
|
-
SRecord.new(event_id: "a1b49edb-7636-416f-874a-88f94b859bef"),
|
901
|
+
[SRecord.new(event_id: "a1b49edb-7636-416f-874a-88f94b859bef")],
|
861
902
|
stream,
|
862
903
|
version_none
|
863
904
|
)
|
864
905
|
expect do
|
865
906
|
repository.append_to_stream(
|
866
|
-
SRecord.new(event_id: "a1b49edb-7636-416f-874a-88f94b859bef"),
|
907
|
+
[SRecord.new(event_id: "a1b49edb-7636-416f-874a-88f94b859bef")],
|
867
908
|
stream_other,
|
868
909
|
version_none
|
869
910
|
)
|
@@ -871,41 +912,39 @@ module RubyEventStore
|
|
871
912
|
end
|
872
913
|
|
873
914
|
it 'does not allow linking same event twice in a stream' do
|
874
|
-
repository.append_to_stream(
|
875
|
-
|
876
|
-
|
915
|
+
repository.append_to_stream(
|
916
|
+
[SRecord.new(event_id: "a1b49edb-7636-416f-874a-88f94b859bef")],
|
917
|
+
stream,
|
877
918
|
version_none
|
878
|
-
).link_to_stream("a1b49edb-7636-416f-874a-88f94b859bef", stream_flow, version_none)
|
919
|
+
).link_to_stream(["a1b49edb-7636-416f-874a-88f94b859bef"], stream_flow, version_none)
|
879
920
|
expect do
|
880
|
-
repository.link_to_stream("a1b49edb-7636-416f-874a-88f94b859bef", stream_flow, version_0)
|
921
|
+
repository.link_to_stream(["a1b49edb-7636-416f-874a-88f94b859bef"], stream_flow, version_0)
|
881
922
|
end.to raise_error(EventDuplicatedInStream)
|
882
923
|
end
|
883
924
|
|
884
925
|
it 'allows appending to GLOBAL_STREAM explicitly' do
|
885
926
|
event = SRecord.new(event_id: "df8b2ba3-4e2c-4888-8d14-4364855fa80e")
|
886
|
-
repository.append_to_stream(event, global_stream, version_any)
|
927
|
+
repository.append_to_stream([event], global_stream, version_any)
|
887
928
|
|
888
929
|
expect(read_events_forward(repository, count: 10)).to eq([event])
|
889
930
|
end
|
890
931
|
|
891
932
|
specify "events not persisted if append failed" do
|
892
|
-
repository.append_to_stream([
|
893
|
-
SRecord.new,
|
894
|
-
], stream, version_none)
|
933
|
+
repository.append_to_stream([SRecord.new], stream, version_none)
|
895
934
|
|
896
935
|
expect do
|
897
|
-
repository.append_to_stream(
|
898
|
-
SRecord.new(
|
899
|
-
|
900
|
-
|
901
|
-
|
936
|
+
repository.append_to_stream(
|
937
|
+
[SRecord.new(event_id: '9bedf448-e4d0-41a3-a8cd-f94aec7aa763')],
|
938
|
+
stream,
|
939
|
+
version_none
|
940
|
+
)
|
902
941
|
end.to raise_error(WrongExpectedEventVersion)
|
903
942
|
expect(repository.has_event?('9bedf448-e4d0-41a3-a8cd-f94aec7aa763')).to be_falsey
|
904
943
|
end
|
905
944
|
|
906
945
|
specify 'linking non-existent event' do
|
907
946
|
expect do
|
908
|
-
repository.link_to_stream('72922e65-1b32-4e97-8023-03ae81dd3a27', stream_flow, version_none)
|
947
|
+
repository.link_to_stream(['72922e65-1b32-4e97-8023-03ae81dd3a27'], stream_flow, version_none)
|
909
948
|
end.to raise_error do |err|
|
910
949
|
expect(err).to be_a(EventNotFound)
|
911
950
|
expect(err.event_id).to eq('72922e65-1b32-4e97-8023-03ae81dd3a27')
|
@@ -918,14 +957,14 @@ module RubyEventStore
|
|
918
957
|
end
|
919
958
|
|
920
959
|
specify 'can store arbitrary binary data' do
|
921
|
-
skip unless
|
960
|
+
skip unless helper.supports_binary?
|
922
961
|
binary = "\xB0"
|
923
962
|
expect(binary.valid_encoding?).to eq(false)
|
924
963
|
binary.force_encoding("binary")
|
925
964
|
expect(binary.valid_encoding?).to eq(true)
|
926
965
|
|
927
966
|
repository.append_to_stream(
|
928
|
-
event = SRecord.new(data: binary, metadata: binary),
|
967
|
+
[event = SRecord.new(data: binary, metadata: binary)],
|
929
968
|
stream,
|
930
969
|
version_none
|
931
970
|
)
|
@@ -1091,7 +1130,7 @@ module RubyEventStore
|
|
1091
1130
|
|
1092
1131
|
context "#update_messages" do
|
1093
1132
|
specify "changes events" do
|
1094
|
-
skip unless
|
1133
|
+
skip unless helper.supports_upsert?
|
1095
1134
|
events = Array.new(5) { SRecord.new }
|
1096
1135
|
repository.append_to_stream(
|
1097
1136
|
events[0..2],
|
@@ -1104,19 +1143,20 @@ module RubyEventStore
|
|
1104
1143
|
ExpectedVersion.any
|
1105
1144
|
)
|
1106
1145
|
repository.update_messages([
|
1107
|
-
a = SRecord.new(event_id: events[0].event_id.clone, data: events[0].data,
|
1108
|
-
b = SRecord.new(event_id: events[1].event_id.dup,
|
1109
|
-
c = SRecord.new(event_id: events[2].event_id,
|
1110
|
-
d = SRecord.new(event_id: events[3].event_id.clone, data: events[3].data,
|
1111
|
-
e = SRecord.new(event_id: events[4].event_id.dup,
|
1146
|
+
a = SRecord.new(event_id: events[0].event_id.clone, data: events[0].data, metadata: events[0].metadata, event_type: events[0].event_type, timestamp: events[0].timestamp),
|
1147
|
+
b = SRecord.new(event_id: events[1].event_id.dup, data: { "test" => 1 }, metadata: events[1].metadata, event_type: events[1].event_type, timestamp: events[1].timestamp),
|
1148
|
+
c = SRecord.new(event_id: events[2].event_id, data: events[2].data, metadata: { "test" => 2 }, event_type: events[2].event_type, timestamp: events[2].timestamp),
|
1149
|
+
d = SRecord.new(event_id: events[3].event_id.clone, data: events[3].data, metadata: events[3].metadata, event_type: "event_type3", timestamp: events[3].timestamp),
|
1150
|
+
e = SRecord.new(event_id: events[4].event_id.dup, data: { "test" => 4 }, metadata: { "test" => 42 }, event_type: "event_type4", timestamp: events[4].timestamp),
|
1112
1151
|
])
|
1152
|
+
|
1113
1153
|
expect(repository.read(specification.result).to_a).to eq([a,b,c,d,e])
|
1114
1154
|
expect(repository.read(specification.stream("whatever").result).to_a).to eq([a,b,c])
|
1115
1155
|
expect(repository.read(specification.stream("elo").result).to_a).to eq([d,e])
|
1116
1156
|
end
|
1117
1157
|
|
1118
1158
|
specify "cannot change unexisting event" do
|
1119
|
-
skip unless
|
1159
|
+
skip unless helper.supports_upsert?
|
1120
1160
|
e = SRecord.new
|
1121
1161
|
expect{ repository.update_messages([e]) }.to raise_error do |err|
|
1122
1162
|
expect(err).to be_a(EventNotFound)
|
@@ -1124,6 +1164,14 @@ module RubyEventStore
|
|
1124
1164
|
expect(err.message).to eq("Event not found: #{e.event_id}")
|
1125
1165
|
end
|
1126
1166
|
end
|
1167
|
+
|
1168
|
+
specify "does not change timestamp" do
|
1169
|
+
r = SRecord.new(timestamp: Time.utc(2020, 1, 1))
|
1170
|
+
repository.append_to_stream([r], Stream.new("whatever"), ExpectedVersion.any)
|
1171
|
+
repository.update_messages([SRecord.new(event_id: r.event_id, timestamp: Time.utc(2020, 1, 20))])
|
1172
|
+
|
1173
|
+
expect(repository.read(specification.result).first.timestamp).to eq(Time.utc(2020, 1, 1))
|
1174
|
+
end
|
1127
1175
|
end
|
1128
1176
|
|
1129
1177
|
specify do
|
@@ -1135,7 +1183,7 @@ module RubyEventStore
|
|
1135
1183
|
stream_c = Stream.new('Stream C')
|
1136
1184
|
repository.append_to_stream([event_1, event_2], stream_a, version_any)
|
1137
1185
|
repository.append_to_stream([event_3], stream_b, version_any)
|
1138
|
-
repository.link_to_stream(event_1.event_id, stream_c, version_none)
|
1186
|
+
repository.link_to_stream([event_1.event_id], stream_c, version_none)
|
1139
1187
|
|
1140
1188
|
expect(repository.streams_of('8a6f053e-3ce2-4c82-a55b-4d02c66ae6ea')).to eq [stream_a, stream_c]
|
1141
1189
|
expect(repository.streams_of('8cee1139-4f96-483a-a175-2b947283c3c7')).to eq [stream_a]
|
@@ -1228,5 +1276,119 @@ module RubyEventStore
|
|
1228
1276
|
expect(repository.count(specification.stream("Dummy").of_type([Type3]).result)).to eq(2)
|
1229
1277
|
expect(repository.count(specification.stream(stream.name).of_type([Type3]).result)).to eq(0)
|
1230
1278
|
end
|
1279
|
+
|
1280
|
+
specify 'timestamp precision' do
|
1281
|
+
time = Time.utc(2020, 9, 11, 12, 26, 0, 123456)
|
1282
|
+
repository.append_to_stream([SRecord.new(timestamp: time)], stream, version_none)
|
1283
|
+
event = read_events_forward(repository, count: 1).first
|
1284
|
+
|
1285
|
+
expect(event.timestamp).to eq(time)
|
1286
|
+
end
|
1287
|
+
|
1288
|
+
specify 'fetching records older than specified date in stream' do
|
1289
|
+
event_1 = SRecord.new(event_id: '8a6f053e-3ce2-4c82-a55b-4d02c66ae6ea', timestamp: Time.utc(2020, 1, 1))
|
1290
|
+
event_2 = SRecord.new(event_id: '8cee1139-4f96-483a-a175-2b947283c3c7', timestamp: Time.utc(2020, 1, 2))
|
1291
|
+
event_3 = SRecord.new(event_id: 'd345f86d-b903-4d78-803f-38990c078d9e', timestamp: Time.utc(2020, 1, 3))
|
1292
|
+
repository.append_to_stream([event_1, event_2, event_3], Stream.new('whatever'), version_any)
|
1293
|
+
|
1294
|
+
expect(repository.read(specification.stream('whatever').older_than(Time.utc(2020, 1, 2)).result).to_a).to eq([event_1])
|
1295
|
+
end
|
1296
|
+
|
1297
|
+
specify 'fetching records older than or equal to specified date in stream' do
|
1298
|
+
event_1 = SRecord.new(event_id: '8a6f053e-3ce2-4c82-a55b-4d02c66ae6ea', timestamp: Time.utc(2020, 1, 1))
|
1299
|
+
event_2 = SRecord.new(event_id: '8cee1139-4f96-483a-a175-2b947283c3c7', timestamp: Time.utc(2020, 1, 2))
|
1300
|
+
event_3 = SRecord.new(event_id: 'd345f86d-b903-4d78-803f-38990c078d9e', timestamp: Time.utc(2020, 1, 3))
|
1301
|
+
repository.append_to_stream([event_1, event_2, event_3], Stream.new('whatever'), version_any)
|
1302
|
+
|
1303
|
+
expect(repository.read(specification.stream('whatever').older_than_or_equal(Time.utc(2020, 1, 2)).result).to_a).to eq([event_1, event_2])
|
1304
|
+
end
|
1305
|
+
|
1306
|
+
specify 'fetching records newer than specified date in stream' do
|
1307
|
+
event_1 = SRecord.new(event_id: '8a6f053e-3ce2-4c82-a55b-4d02c66ae6ea', timestamp: Time.utc(2020, 1, 1))
|
1308
|
+
event_2 = SRecord.new(event_id: '8cee1139-4f96-483a-a175-2b947283c3c7', timestamp: Time.utc(2020, 1, 2))
|
1309
|
+
event_3 = SRecord.new(event_id: 'd345f86d-b903-4d78-803f-38990c078d9e', timestamp: Time.utc(2020, 1, 3))
|
1310
|
+
repository.append_to_stream([event_1, event_2, event_3], Stream.new('whatever'), version_any)
|
1311
|
+
|
1312
|
+
expect(repository.read(specification.stream('whatever').newer_than(Time.utc(2020, 1, 2)).result).to_a).to eq([event_3])
|
1313
|
+
end
|
1314
|
+
|
1315
|
+
specify 'fetching records newer than or equal to specified date in stream' do
|
1316
|
+
event_1 = SRecord.new(event_id: '8a6f053e-3ce2-4c82-a55b-4d02c66ae6ea', timestamp: Time.utc(2020, 1, 1))
|
1317
|
+
event_2 = SRecord.new(event_id: '8cee1139-4f96-483a-a175-2b947283c3c7', timestamp: Time.utc(2020, 1, 2))
|
1318
|
+
event_3 = SRecord.new(event_id: 'd345f86d-b903-4d78-803f-38990c078d9e', timestamp: Time.utc(2020, 1, 3))
|
1319
|
+
repository.append_to_stream([event_1, event_2, event_3], Stream.new('whatever'), version_any)
|
1320
|
+
|
1321
|
+
expect(repository.read(specification.stream('whatever').newer_than_or_equal(Time.utc(2020, 1, 2)).result).to_a).to eq([event_2, event_3])
|
1322
|
+
end
|
1323
|
+
|
1324
|
+
specify 'fetching records older than specified date' do
|
1325
|
+
event_1 = SRecord.new(event_id: '8a6f053e-3ce2-4c82-a55b-4d02c66ae6ea', timestamp: Time.utc(2020, 1, 1))
|
1326
|
+
event_2 = SRecord.new(event_id: '8cee1139-4f96-483a-a175-2b947283c3c7', timestamp: Time.utc(2020, 1, 2))
|
1327
|
+
event_3 = SRecord.new(event_id: 'd345f86d-b903-4d78-803f-38990c078d9e', timestamp: Time.utc(2020, 1, 3))
|
1328
|
+
repository.append_to_stream([event_1, event_2, event_3], Stream.new('whatever'), version_any)
|
1329
|
+
|
1330
|
+
expect(repository.read(specification.older_than(Time.utc(2020, 1, 2)).result).to_a).to eq([event_1])
|
1331
|
+
end
|
1332
|
+
|
1333
|
+
specify 'fetching records older than or equal to specified date' do
|
1334
|
+
event_1 = SRecord.new(event_id: '8a6f053e-3ce2-4c82-a55b-4d02c66ae6ea', timestamp: Time.utc(2020, 1, 1))
|
1335
|
+
event_2 = SRecord.new(event_id: '8cee1139-4f96-483a-a175-2b947283c3c7', timestamp: Time.utc(2020, 1, 2))
|
1336
|
+
event_3 = SRecord.new(event_id: 'd345f86d-b903-4d78-803f-38990c078d9e', timestamp: Time.utc(2020, 1, 3))
|
1337
|
+
repository.append_to_stream([event_1, event_2, event_3], Stream.new('whatever'), version_any)
|
1338
|
+
|
1339
|
+
expect(repository.read(specification.older_than_or_equal(Time.utc(2020, 1, 2)).result).to_a).to eq([event_1, event_2])
|
1340
|
+
end
|
1341
|
+
|
1342
|
+
specify 'fetching records newer than specified date' do
|
1343
|
+
event_1 = SRecord.new(event_id: '8a6f053e-3ce2-4c82-a55b-4d02c66ae6ea', timestamp: Time.utc(2020, 1, 1))
|
1344
|
+
event_2 = SRecord.new(event_id: '8cee1139-4f96-483a-a175-2b947283c3c7', timestamp: Time.utc(2020, 1, 2))
|
1345
|
+
event_3 = SRecord.new(event_id: 'd345f86d-b903-4d78-803f-38990c078d9e', timestamp: Time.utc(2020, 1, 3))
|
1346
|
+
repository.append_to_stream([event_1, event_2, event_3], Stream.new('whatever'), version_any)
|
1347
|
+
|
1348
|
+
expect(repository.read(specification.newer_than(Time.utc(2020, 1, 2)).result).to_a).to eq([event_3])
|
1349
|
+
end
|
1350
|
+
|
1351
|
+
specify 'fetching records newer than or equal to specified date' do
|
1352
|
+
event_1 = SRecord.new(event_id: '8a6f053e-3ce2-4c82-a55b-4d02c66ae6ea', timestamp: Time.utc(2020, 1, 1))
|
1353
|
+
event_2 = SRecord.new(event_id: '8cee1139-4f96-483a-a175-2b947283c3c7', timestamp: Time.utc(2020, 1, 2))
|
1354
|
+
event_3 = SRecord.new(event_id: 'd345f86d-b903-4d78-803f-38990c078d9e', timestamp: Time.utc(2020, 1, 3))
|
1355
|
+
repository.append_to_stream([event_1, event_2, event_3], Stream.new('whatever'), version_any)
|
1356
|
+
|
1357
|
+
expect(repository.read(specification.newer_than_or_equal(Time.utc(2020, 1, 2)).result).to_a).to eq([event_2, event_3])
|
1358
|
+
end
|
1359
|
+
|
1360
|
+
specify 'fetching records from disjoint periods' do
|
1361
|
+
event_1 = SRecord.new(event_id: '8a6f053e-3ce2-4c82-a55b-4d02c66ae6ea', timestamp: Time.utc(2020, 1, 1))
|
1362
|
+
event_2 = SRecord.new(event_id: '8cee1139-4f96-483a-a175-2b947283c3c7', timestamp: Time.utc(2020, 1, 2))
|
1363
|
+
event_3 = SRecord.new(event_id: 'd345f86d-b903-4d78-803f-38990c078d9e', timestamp: Time.utc(2020, 1, 3))
|
1364
|
+
repository.append_to_stream([event_1, event_2, event_3], Stream.new('whatever'), version_any)
|
1365
|
+
|
1366
|
+
expect(repository.read(specification.older_than(Time.utc(2020, 1, 2)).newer_than(Time.utc(2020, 1, 2)).result).to_a).to eq([])
|
1367
|
+
end
|
1368
|
+
|
1369
|
+
specify 'fetching records within time range' do
|
1370
|
+
event_1 = SRecord.new(event_id: '8a6f053e-3ce2-4c82-a55b-4d02c66ae6ea', timestamp: Time.utc(2020, 1, 1))
|
1371
|
+
event_2 = SRecord.new(event_id: '8cee1139-4f96-483a-a175-2b947283c3c7', timestamp: Time.utc(2020, 1, 2))
|
1372
|
+
event_3 = SRecord.new(event_id: 'd345f86d-b903-4d78-803f-38990c078d9e', timestamp: Time.utc(2020, 1, 3))
|
1373
|
+
repository.append_to_stream([event_1, event_2, event_3], Stream.new('whatever'), version_any)
|
1374
|
+
|
1375
|
+
expect(repository.read(specification.between(Time.utc(2020, 1, 1)...Time.utc(2020, 1, 3)).result).to_a).to eq([event_1, event_2])
|
1376
|
+
end
|
1377
|
+
|
1378
|
+
specify "time order is respected" do
|
1379
|
+
repository.append_to_stream([
|
1380
|
+
SRecord.new(event_id: e1 = SecureRandom.uuid, timestamp: Time.new(2020,1,1), valid_at: Time.new(2020,1,9)),
|
1381
|
+
SRecord.new(event_id: e2 = SecureRandom.uuid, timestamp: Time.new(2020,1,3), valid_at: Time.new(2020,1,6)),
|
1382
|
+
SRecord.new(event_id: e3 = SecureRandom.uuid, timestamp: Time.new(2020,1,2), valid_at: Time.new(2020,1,3)),
|
1383
|
+
],
|
1384
|
+
Stream.new("Dummy"),
|
1385
|
+
ExpectedVersion.any
|
1386
|
+
)
|
1387
|
+
expect(repository.read(specification.result).map(&:event_id)).to eq [e1, e2, e3]
|
1388
|
+
expect(repository.read(specification.as_at.result).map(&:event_id)).to eq [e1, e3, e2]
|
1389
|
+
expect(repository.read(specification.as_at.backward.result).map(&:event_id)).to eq [e2, e3, e1]
|
1390
|
+
expect(repository.read(specification.as_of.result).map(&:event_id)).to eq [e3, e2, e1]
|
1391
|
+
expect(repository.read(specification.as_of.backward.result).map(&:event_id)).to eq [e1, e2, e3]
|
1392
|
+
end
|
1231
1393
|
end
|
1232
1394
|
end
|