ruby_event_store 2.1.0 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/lib/ruby_event_store/batch_enumerator.rb +3 -3
  3. data/lib/ruby_event_store/broker.rb +5 -4
  4. data/lib/ruby_event_store/client.rb +81 -48
  5. data/lib/ruby_event_store/composed_dispatcher.rb +1 -3
  6. data/lib/ruby_event_store/correlated_commands.rb +4 -15
  7. data/lib/ruby_event_store/errors.rb +11 -10
  8. data/lib/ruby_event_store/event.rb +9 -14
  9. data/lib/ruby_event_store/expected_version.rb +3 -7
  10. data/lib/ruby_event_store/in_memory_repository.rb +100 -37
  11. data/lib/ruby_event_store/instrumented_dispatcher.rb +11 -2
  12. data/lib/ruby_event_store/instrumented_repository.rb +13 -8
  13. data/lib/ruby_event_store/link_by_metadata.rb +4 -21
  14. data/lib/ruby_event_store/mappers/default.rb +6 -4
  15. data/lib/ruby_event_store/mappers/encryption_key.rb +7 -16
  16. data/lib/ruby_event_store/mappers/encryption_mapper.rb +6 -6
  17. data/lib/ruby_event_store/mappers/forgotten_data.rb +1 -1
  18. data/lib/ruby_event_store/mappers/in_memory_encryption_key_repository.rb +1 -1
  19. data/lib/ruby_event_store/mappers/null_mapper.rb +0 -1
  20. data/lib/ruby_event_store/mappers/pipeline.rb +3 -10
  21. data/lib/ruby_event_store/mappers/pipeline_mapper.rb +1 -0
  22. data/lib/ruby_event_store/mappers/transformation/domain_event.rb +22 -12
  23. data/lib/ruby_event_store/mappers/transformation/encryption.rb +21 -25
  24. data/lib/ruby_event_store/mappers/transformation/event_class_remapper.rb +6 -5
  25. data/lib/ruby_event_store/mappers/transformation/stringify_metadata_keys.rb +6 -5
  26. data/lib/ruby_event_store/mappers/transformation/symbolize_metadata_keys.rb +6 -5
  27. data/lib/ruby_event_store/mappers/transformation/upcast.rb +2 -6
  28. data/lib/ruby_event_store/metadata.rb +46 -17
  29. data/lib/ruby_event_store/projection.rb +12 -20
  30. data/lib/ruby_event_store/record.rb +14 -26
  31. data/lib/ruby_event_store/serialized_record.rb +14 -26
  32. data/lib/ruby_event_store/serializers/yaml.rb +17 -0
  33. data/lib/ruby_event_store/spec/broker_lint.rb +38 -28
  34. data/lib/ruby_event_store/spec/event_lint.rb +10 -10
  35. data/lib/ruby_event_store/spec/event_repository_lint.rb +746 -730
  36. data/lib/ruby_event_store/spec/mapper_lint.rb +2 -2
  37. data/lib/ruby_event_store/spec/subscriptions_lint.rb +58 -68
  38. data/lib/ruby_event_store/specification.rb +20 -16
  39. data/lib/ruby_event_store/specification_reader.rb +2 -3
  40. data/lib/ruby_event_store/specification_result.rb +52 -46
  41. data/lib/ruby_event_store/stream.rb +3 -7
  42. data/lib/ruby_event_store/subscriptions.rb +17 -17
  43. data/lib/ruby_event_store/transform_keys.rb +1 -1
  44. data/lib/ruby_event_store/version.rb +1 -1
  45. data/lib/ruby_event_store.rb +44 -43
  46. metadata +6 -4
@@ -2,88 +2,58 @@ module RubyEventStore
2
2
  # @private
3
3
  class SRecord
4
4
  def self.new(
5
- event_id: SecureRandom.uuid,
6
- data: {},
7
- metadata: {},
8
- event_type: 'SRecordTestEvent',
9
- timestamp: Time.new.utc,
10
- valid_at: nil
5
+ event_id: SecureRandom.uuid,
6
+ data: {},
7
+ metadata: {},
8
+ event_type: "SRecordTestEvent",
9
+ timestamp: Time.new.utc,
10
+ valid_at: nil
11
11
  )
12
12
  Record.new(
13
- event_id: event_id,
14
- data: data,
15
- metadata: metadata,
13
+ event_id: event_id,
14
+ data: data,
15
+ metadata: metadata,
16
16
  event_type: event_type,
17
- timestamp: timestamp.round(TIMESTAMP_PRECISION),
18
- valid_at: (valid_at || timestamp).round(TIMESTAMP_PRECISION),
17
+ timestamp: timestamp.round(TIMESTAMP_PRECISION),
18
+ valid_at: (valid_at || timestamp).round(TIMESTAMP_PRECISION)
19
19
  )
20
20
  end
21
21
  end
22
22
 
23
23
  # @private
24
24
  Type1 = Class.new(RubyEventStore::Event)
25
+
25
26
  # @private
26
27
  Type2 = Class.new(RubyEventStore::Event)
27
- # @private
28
- Type3 = Class.new(RubyEventStore::Event)
29
28
 
30
29
  # @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
30
+ Type3 = Class.new(RubyEventStore::Event)
62
31
  end
63
32
 
64
33
  module RubyEventStore
65
- ::RSpec.shared_examples :event_repository do
66
- let(:helper) { EventRepositoryHelper.new }
34
+ ::RSpec.shared_examples :event_repository do |mk_repository, helper|
35
+ let(:repository) { mk_repository.call }
67
36
  let(:specification) { Specification.new(SpecificationReader.new(repository, Mappers::NullMapper.new)) }
68
37
  let(:global_stream) { Stream.new(GLOBAL_STREAM) }
69
- let(:stream) { Stream.new(SecureRandom.uuid) }
70
- let(:stream_flow) { Stream.new('flow') }
71
- let(:stream_other) { Stream.new('other') }
72
- let(:stream_test) { Stream.new('test') }
73
- let(:version_none) { ExpectedVersion.none }
74
- let(:version_auto) { ExpectedVersion.auto }
75
- let(:version_any) { ExpectedVersion.any }
76
- let(:version_0) { ExpectedVersion.new(0) }
77
- let(:version_1) { ExpectedVersion.new(1) }
78
- let(:version_2) { ExpectedVersion.new(2) }
79
- let(:version_3) { ExpectedVersion.new(3) }
80
-
81
- def verify_conncurency_assumptions
38
+ let(:stream) { Stream.new(SecureRandom.uuid) }
39
+ let(:stream_flow) { Stream.new("flow") }
40
+ let(:stream_other) { Stream.new("other") }
41
+ let(:stream_test) { Stream.new("test") }
42
+ let(:version_none) { ExpectedVersion.none }
43
+ let(:version_auto) { ExpectedVersion.auto }
44
+ let(:version_any) { ExpectedVersion.any }
45
+ let(:version_0) { ExpectedVersion.new(0) }
46
+ let(:version_1) { ExpectedVersion.new(1) }
47
+ let(:version_2) { ExpectedVersion.new(2) }
48
+ let(:version_3) { ExpectedVersion.new(3) }
49
+
50
+ def verify_conncurency_assumptions(helper)
82
51
  return unless helper.has_connection_pooling?
83
- expect(helper.connection_pool_size).to eq(5)
52
+ expect(helper.connection_pool_size).to eq(5),
53
+ "expected connection pool of size 5, got #{helper.connection_pool_size}"
84
54
  end
85
55
 
86
- def read_events(scope, stream = nil, from: nil, to: nil, count: nil)
56
+ def read_events(repository, scope, stream = nil, from: nil, to: nil, count: nil)
87
57
  scope = scope.stream(stream.name) if stream
88
58
  scope = scope.from(from) if from
89
59
  scope = scope.to(to) if to
@@ -91,25 +61,25 @@ module RubyEventStore
91
61
  repository.read(scope.result).to_a
92
62
  end
93
63
 
94
- def read_events_forward(_repository, stream = nil, from: nil, to: nil, count: nil)
95
- read_events(specification, stream, from: from, to: to, count: count)
64
+ def read_events_forward(repository, stream = nil, from: nil, to: nil, count: nil)
65
+ read_events(repository, specification, stream, from: from, to: to, count: count)
96
66
  end
97
67
 
98
- def read_events_backward(_repository, stream = nil, from: nil, to: nil, count: nil)
99
- read_events(specification.backward, stream, from: from, to: to, count: count)
68
+ def read_events_backward(repository, stream = nil, from: nil, to: nil, count: nil)
69
+ read_events(repository, specification.backward, stream, from: from, to: to, count: count)
100
70
  end
101
71
 
102
- it 'just created is empty' do
72
+ it "just created is empty" do
103
73
  expect(read_events_forward(repository)).to be_empty
104
74
  end
105
75
 
106
- specify 'append_to_stream returns self' do
76
+ specify "append_to_stream returns self" do
107
77
  repository
108
78
  .append_to_stream([event = SRecord.new], stream, version_none)
109
79
  .append_to_stream([event = SRecord.new], stream, version_0)
110
80
  end
111
81
 
112
- specify 'link_to_stream returns self' do
82
+ specify "link_to_stream returns self" do
113
83
  event0 = SRecord.new
114
84
  event1 = SRecord.new
115
85
  repository
@@ -118,14 +88,14 @@ module RubyEventStore
118
88
  .link_to_stream([event1.event_id], stream_flow, version_0)
119
89
  end
120
90
 
121
- specify 'adds an initial event to a new stream' do
91
+ specify "adds an initial event to a new stream" do
122
92
  repository.append_to_stream([event = SRecord.new], stream, version_none)
123
93
  expect(read_events_forward(repository).first).to eq(event)
124
94
  expect(read_events_forward(repository, stream).first).to eq(event)
125
95
  expect(read_events_forward(repository, stream_other)).to be_empty
126
96
  end
127
97
 
128
- specify 'links an initial event to a new stream' do
98
+ specify "links an initial event to a new stream" do
129
99
  repository
130
100
  .append_to_stream([event = SRecord.new], stream, version_none)
131
101
  .link_to_stream([event.event_id], stream_flow, version_none)
@@ -136,476 +106,350 @@ module RubyEventStore
136
106
  expect(read_events_forward(repository, stream_other)).to be_empty
137
107
  end
138
108
 
139
- specify 'adds multiple initial events to a new stream' do
140
- repository.append_to_stream([
141
- event0 = SRecord.new,
142
- event1 = SRecord.new,
143
- ], stream, version_none)
109
+ specify "adds multiple initial events to a new stream" do
110
+ repository.append_to_stream([event0 = SRecord.new, event1 = SRecord.new], stream, version_none)
144
111
  expect(read_events_forward(repository, count: 2)).to eq([event0, event1])
145
112
  expect(read_events_forward(repository, stream)).to eq([event0, event1])
146
113
  end
147
114
 
148
- specify 'links multiple initial events to a new stream' do
149
- repository.append_to_stream([
150
- event0 = SRecord.new,
151
- event1 = SRecord.new,
152
- ], stream, version_none).link_to_stream([
153
- event0.event_id,
154
- event1.event_id,
155
- ], stream_flow, version_none)
115
+ specify "links multiple initial events to a new stream" do
116
+ repository
117
+ .append_to_stream([event0 = SRecord.new, event1 = SRecord.new], stream, version_none)
118
+ .link_to_stream([event0.event_id, event1.event_id], stream_flow, version_none)
156
119
  expect(read_events_forward(repository, count: 2)).to eq([event0, event1])
157
120
  expect(read_events_forward(repository, stream_flow)).to eq([event0, event1])
158
121
  end
159
122
 
160
- specify 'correct expected version on second write' do
161
- repository.append_to_stream([
162
- event0 = SRecord.new,
163
- event1 = SRecord.new,
164
- ], stream, version_none)
165
- repository.append_to_stream([
166
- event2 = SRecord.new,
167
- event3 = SRecord.new,
168
- ], stream, version_1)
123
+ specify "correct expected version on second write" do
124
+ repository.append_to_stream([event0 = SRecord.new, event1 = SRecord.new], stream, version_none)
125
+ repository.append_to_stream([event2 = SRecord.new, event3 = SRecord.new], stream, version_1)
169
126
  expect(read_events_forward(repository, count: 4)).to eq([event0, event1, event2, event3])
170
127
  expect(read_events_forward(repository, stream)).to eq([event0, event1, event2, event3])
171
128
  end
172
129
 
173
- specify 'correct expected version on second link' do
174
- repository.append_to_stream([
175
- event0 = SRecord.new,
176
- event1 = SRecord.new,
177
- ], stream, version_none).append_to_stream([
178
- event2 = SRecord.new,
179
- event3 = SRecord.new,
180
- ], stream_flow, version_none).link_to_stream([
181
- event0.event_id,
182
- event1.event_id,
183
- ], stream_flow, version_1)
130
+ specify "correct expected version on second link" do
131
+ repository
132
+ .append_to_stream([event0 = SRecord.new, event1 = SRecord.new], stream, version_none)
133
+ .append_to_stream([event2 = SRecord.new, event3 = SRecord.new], stream_flow, version_none)
134
+ .link_to_stream([event0.event_id, event1.event_id], stream_flow, version_1)
184
135
  expect(read_events_forward(repository, count: 4)).to eq([event0, event1, event2, event3])
185
136
  expect(read_events_forward(repository, stream_flow)).to eq([event2, event3, event0, event1])
186
137
  end
187
138
 
188
- specify 'incorrect expected version on second write' do
189
- repository.append_to_stream([
190
- event0 = SRecord.new,
191
- event1 = SRecord.new,
192
- ], stream, version_none)
139
+ specify "incorrect expected version on second write" do
140
+ repository.append_to_stream([event0 = SRecord.new, event1 = SRecord.new], stream, version_none)
193
141
  expect do
194
- repository.append_to_stream([
195
- event2 = SRecord.new,
196
- event3 = SRecord.new,
197
- ], stream, version_0)
142
+ repository.append_to_stream([event2 = SRecord.new, event3 = SRecord.new], stream, version_0)
198
143
  end.to raise_error(WrongExpectedEventVersion)
199
144
 
200
145
  expect(read_events_forward(repository, count: 4)).to eq([event0, event1])
201
146
  expect(read_events_forward(repository, stream)).to eq([event0, event1])
202
147
  end
203
148
 
204
- specify 'incorrect expected version on second link' do
205
- repository.append_to_stream([
206
- event0 = SRecord.new,
207
- event1 = SRecord.new,
208
- ], stream, version_none)
209
- repository.append_to_stream([
210
- event2 = SRecord.new,
211
- event3 = SRecord.new,
212
- ], stream_other, version_none)
213
- expect do
214
- repository.link_to_stream([
215
- event2.event_id,
216
- event3.event_id,
217
- ], stream, version_0)
218
- end.to raise_error(WrongExpectedEventVersion)
149
+ specify "incorrect expected version on second link" do
150
+ repository.append_to_stream([event0 = SRecord.new, event1 = SRecord.new], stream, version_none)
151
+ repository.append_to_stream([event2 = SRecord.new, event3 = SRecord.new], stream_other, version_none)
152
+ expect { repository.link_to_stream([event2.event_id, event3.event_id], stream, version_0) }.to raise_error(
153
+ WrongExpectedEventVersion
154
+ )
219
155
 
220
156
  expect(read_events_forward(repository, count: 4)).to eq([event0, event1, event2, event3])
221
157
  expect(read_events_forward(repository, stream)).to eq([event0, event1])
222
158
  end
223
159
 
224
- specify ':none on first and subsequent write' do
225
- repository.append_to_stream([
226
- eventA = SRecord.new,
227
- ], stream, version_none)
228
- expect do
229
- repository.append_to_stream([
230
- eventB = SRecord.new,
231
- ], stream, version_none)
232
- end.to raise_error(WrongExpectedEventVersion)
160
+ specify ":none on first and subsequent write" do
161
+ repository.append_to_stream([eventA = SRecord.new], stream, version_none)
162
+ expect { repository.append_to_stream([eventB = SRecord.new], stream, version_none) }.to raise_error(
163
+ WrongExpectedEventVersion
164
+ )
233
165
  expect(read_events_forward(repository, count: 1)).to eq([eventA])
234
166
  expect(read_events_forward(repository, stream)).to eq([eventA])
235
167
  end
236
168
 
237
- specify ':none on first and subsequent link' do
238
- repository.append_to_stream([
239
- eventA = SRecord.new,
240
- eventB = SRecord.new,
241
- ], stream, version_none)
169
+ specify ":none on first and subsequent link" do
170
+ repository.append_to_stream([eventA = SRecord.new, eventB = SRecord.new], stream, version_none)
242
171
 
243
172
  repository.link_to_stream([eventA.event_id], stream_flow, version_none)
244
- expect do
245
- repository.link_to_stream([eventB.event_id], stream_flow, version_none)
246
- end.to raise_error(WrongExpectedEventVersion)
173
+ expect { repository.link_to_stream([eventB.event_id], stream_flow, version_none) }.to raise_error(
174
+ WrongExpectedEventVersion
175
+ )
247
176
 
248
177
  expect(read_events_forward(repository, count: 1)).to eq([eventA])
249
178
  expect(read_events_forward(repository, stream_flow)).to eq([eventA])
250
179
  end
251
180
 
252
- specify ':any allows stream with best-effort order and no guarantee' do
253
- repository.append_to_stream([
254
- event0 = SRecord.new,
255
- event1 = SRecord.new,
256
- ], stream, version_any)
257
- repository.append_to_stream([
258
- event2 = SRecord.new,
259
- event3 = SRecord.new,
260
- ], stream, version_any)
181
+ specify ":any allows stream with best-effort order and no guarantee" do
182
+ repository.append_to_stream([event0 = SRecord.new, event1 = SRecord.new], stream, version_any)
183
+ repository.append_to_stream([event2 = SRecord.new, event3 = SRecord.new], stream, version_any)
261
184
  expect(read_events_forward(repository, count: 4).to_set).to eq(Set.new([event0, event1, event2, event3]))
262
185
  expect(read_events_forward(repository, stream).to_set).to eq(Set.new([event0, event1, event2, event3]))
263
186
  end
264
187
 
265
- specify ':any allows linking in stream with best-effort order and no guarantee' do
266
- repository.append_to_stream([
267
- event0 = SRecord.new,
268
- event1 = SRecord.new,
269
- event2 = SRecord.new,
270
- event3 = SRecord.new,
271
- ], stream, version_any)
188
+ specify ":any allows linking in stream with best-effort order and no guarantee" do
189
+ repository.append_to_stream(
190
+ [event0 = SRecord.new, event1 = SRecord.new, event2 = SRecord.new, event3 = SRecord.new],
191
+ stream,
192
+ version_any
193
+ )
272
194
 
273
- repository.link_to_stream([
274
- event0.event_id, event1.event_id,
275
- ], stream_flow, version_any)
276
- repository.link_to_stream([
277
- event2.event_id, event3.event_id,
278
- ], stream_flow, version_any)
195
+ repository.link_to_stream([event0.event_id, event1.event_id], stream_flow, version_any)
196
+ repository.link_to_stream([event2.event_id, event3.event_id], stream_flow, version_any)
279
197
 
280
198
  expect(read_events_forward(repository, count: 4).to_set).to eq(Set.new([event0, event1, event2, event3]))
281
199
  expect(read_events_forward(repository, stream_flow).to_set).to eq(Set.new([event0, event1, event2, event3]))
282
200
  end
283
201
 
284
- specify ':auto queries for last position in given stream' do
285
- repository.append_to_stream([
286
- eventA = SRecord.new,
287
- eventB = SRecord.new,
288
- eventC = SRecord.new,
289
- ], stream_other, version_auto)
290
- repository.append_to_stream([
291
- event0 = SRecord.new,
292
- event1 = SRecord.new,
293
- ], stream, version_auto)
294
- repository.append_to_stream([
295
- event2 = SRecord.new,
296
- event3 = SRecord.new,
297
- ], stream, version_1)
298
- end
299
-
300
- specify ':auto queries for last position in given stream when linking' do
301
- repository.append_to_stream([
302
- eventA = SRecord.new,
303
- eventB = SRecord.new,
304
- eventC = SRecord.new,
305
- ], stream_other, version_auto)
306
- repository.append_to_stream([
307
- event0 = SRecord.new,
308
- event1 = SRecord.new,
309
- ], stream, version_auto)
310
- repository.link_to_stream([
311
- eventA.event_id,
312
- eventB.event_id,
313
- eventC.event_id,
314
- ], stream, version_1)
315
- end
316
-
317
- specify ':auto starts from 0' do
318
- repository.append_to_stream([
319
- event0 = SRecord.new,
320
- ], stream, version_auto)
321
- expect do
322
- repository.append_to_stream([
323
- event1 = SRecord.new,
324
- ], stream, version_none)
325
- end.to raise_error(WrongExpectedEventVersion)
202
+ specify ":auto queries for last position in given stream" do
203
+ repository.append_to_stream(
204
+ [eventA = SRecord.new, eventB = SRecord.new, eventC = SRecord.new],
205
+ stream_other,
206
+ version_auto
207
+ )
208
+ repository.append_to_stream([event0 = SRecord.new, event1 = SRecord.new], stream, version_auto)
209
+ repository.append_to_stream([event2 = SRecord.new, event3 = SRecord.new], stream, version_1)
326
210
  end
327
211
 
328
- specify ':auto linking starts from 0' do
329
- repository.append_to_stream([
330
- event0 = SRecord.new,
331
- ], stream_other, version_auto)
332
- repository.link_to_stream([
333
- event0.event_id,
334
- ], stream, version_auto)
335
- expect do
336
- repository.append_to_stream([
337
- event1 = SRecord.new,
338
- ], stream, version_none)
339
- end.to raise_error(WrongExpectedEventVersion)
212
+ specify ":auto queries for last position in given stream when linking" do
213
+ repository.append_to_stream(
214
+ [eventA = SRecord.new, eventB = SRecord.new, eventC = SRecord.new],
215
+ stream_other,
216
+ version_auto
217
+ )
218
+ repository.append_to_stream([event0 = SRecord.new, event1 = SRecord.new], stream, version_auto)
219
+ repository.link_to_stream([eventA.event_id, eventB.event_id, eventC.event_id], stream, version_1)
220
+ end
221
+
222
+ specify ":auto starts from 0" do
223
+ repository.append_to_stream([event0 = SRecord.new], stream, version_auto)
224
+ expect { repository.append_to_stream([event1 = SRecord.new], stream, version_none) }.to raise_error(
225
+ WrongExpectedEventVersion
226
+ )
227
+ end
228
+
229
+ specify ":auto linking starts from 0" do
230
+ repository.append_to_stream([event0 = SRecord.new], stream_other, version_auto)
231
+ repository.link_to_stream([event0.event_id], stream, version_auto)
232
+ expect { repository.append_to_stream([event1 = SRecord.new], stream, version_none) }.to raise_error(
233
+ WrongExpectedEventVersion
234
+ )
340
235
  end
341
236
 
342
- specify ':auto queries for last position and follows in incremental way' do
237
+ specify ":auto queries for last position and follows in incremental way" do
343
238
  # It is expected that there is higher level lock
344
239
  # So this query is safe from race conditions
345
- repository.append_to_stream([
346
- event0 = SRecord.new,
347
- event1 = SRecord.new,
348
- ], stream, version_auto)
349
- repository.append_to_stream([
350
- event2 = SRecord.new,
351
- event3 = SRecord.new,
352
- ], stream, version_auto)
353
- expect(read_events_forward(repository, count: 4)).to eq([
354
- event0, event1,
355
- event2, event3
356
- ])
240
+ repository.append_to_stream([event0 = SRecord.new, event1 = SRecord.new], stream, version_auto)
241
+ repository.append_to_stream([event2 = SRecord.new, event3 = SRecord.new], stream, version_auto)
242
+ expect(read_events_forward(repository, count: 4)).to eq([event0, event1, event2, event3])
357
243
  expect(read_events_forward(repository, stream)).to eq([event0, event1, event2, event3])
358
244
  end
359
245
 
360
- specify ':auto queries for last position and follows in incremental way when linking' do
361
- repository.append_to_stream([
362
- event0 = SRecord.new,
363
- event1 = SRecord.new,
364
- event2 = SRecord.new,
365
- event3 = SRecord.new,
366
- ], stream, version_auto)
367
- repository.link_to_stream([
368
- event0.event_id, event1.event_id,
369
- ], stream_flow, version_auto)
370
- repository.link_to_stream([
371
- event2.event_id, event3.event_id,
372
- ], stream_flow, version_auto)
373
- expect(read_events_forward(repository, count: 4)).to eq([
374
- event0, event1,
375
- event2, event3
376
- ])
246
+ specify ":auto queries for last position and follows in incremental way when linking" do
247
+ repository.append_to_stream(
248
+ [event0 = SRecord.new, event1 = SRecord.new, event2 = SRecord.new, event3 = SRecord.new],
249
+ stream,
250
+ version_auto
251
+ )
252
+ repository.link_to_stream([event0.event_id, event1.event_id], stream_flow, version_auto)
253
+ repository.link_to_stream([event2.event_id, event3.event_id], stream_flow, version_auto)
254
+ expect(read_events_forward(repository, count: 4)).to eq([event0, event1, event2, event3])
377
255
  expect(read_events_forward(repository, stream_flow)).to eq([event0, event1, event2, event3])
378
256
  end
379
257
 
380
- specify ':auto is compatible with manual expectation' do
381
- repository.append_to_stream([
382
- event0 = SRecord.new,
383
- event1 = SRecord.new,
384
- ], stream, version_auto)
385
- repository.append_to_stream([
386
- event2 = SRecord.new,
387
- event3 = SRecord.new,
388
- ], stream, version_1)
258
+ specify ":auto is compatible with manual expectation" do
259
+ repository.append_to_stream([event0 = SRecord.new, event1 = SRecord.new], stream, version_auto)
260
+ repository.append_to_stream([event2 = SRecord.new, event3 = SRecord.new], stream, version_1)
389
261
  expect(read_events_forward(repository, count: 4)).to eq([event0, event1, event2, event3])
390
262
  expect(read_events_forward(repository, stream)).to eq([event0, event1, event2, event3])
391
263
  end
392
264
 
393
- specify ':auto is compatible with manual expectation when linking' do
394
- repository.append_to_stream([
395
- event0 = SRecord.new,
396
- event1 = SRecord.new,
397
- ], stream, version_auto)
398
- repository.link_to_stream([
399
- event0.event_id,
400
- ], stream_flow, version_auto)
401
- repository.link_to_stream([
402
- event1.event_id,
403
- ], stream_flow, version_0)
404
- expect(read_events_forward(repository, count: 4)).to eq([event0, event1,])
405
- expect(read_events_forward(repository, stream_flow)).to eq([event0, event1,])
406
- end
407
-
408
- specify 'manual is compatible with auto expectation' do
409
- repository.append_to_stream([
410
- event0 = SRecord.new,
411
- event1 = SRecord.new,
412
- ], stream, version_none)
413
- repository.append_to_stream([
414
- event2 = SRecord.new,
415
- event3 = SRecord.new,
416
- ], stream, version_auto)
265
+ specify ":auto is compatible with manual expectation when linking" do
266
+ repository.append_to_stream([event0 = SRecord.new, event1 = SRecord.new], stream, version_auto)
267
+ repository.link_to_stream([event0.event_id], stream_flow, version_auto)
268
+ repository.link_to_stream([event1.event_id], stream_flow, version_0)
269
+ expect(read_events_forward(repository, count: 4)).to eq([event0, event1])
270
+ expect(read_events_forward(repository, stream_flow)).to eq([event0, event1])
271
+ end
272
+
273
+ specify "manual is compatible with auto expectation" do
274
+ repository.append_to_stream([event0 = SRecord.new, event1 = SRecord.new], stream, version_none)
275
+ repository.append_to_stream([event2 = SRecord.new, event3 = SRecord.new], stream, version_auto)
417
276
  expect(read_events_forward(repository, count: 4)).to eq([event0, event1, event2, event3])
418
277
  expect(read_events_forward(repository, stream)).to eq([event0, event1, event2, event3])
419
278
  end
420
279
 
421
- specify 'manual is compatible with auto expectation when linking' do
422
- repository.append_to_stream([
423
- event0 = SRecord.new,
424
- event1 = SRecord.new,
425
- ], stream, version_auto)
426
- repository.link_to_stream([
427
- event0.event_id,
428
- ], stream_flow, version_none)
429
- repository.link_to_stream([
430
- event1.event_id,
431
- ], stream_flow, version_auto)
280
+ specify "manual is compatible with auto expectation when linking" do
281
+ repository.append_to_stream([event0 = SRecord.new, event1 = SRecord.new], stream, version_auto)
282
+ repository.link_to_stream([event0.event_id], stream_flow, version_none)
283
+ repository.link_to_stream([event1.event_id], stream_flow, version_auto)
432
284
  expect(read_events_forward(repository, count: 4)).to eq([event0, event1])
433
285
  expect(read_events_forward(repository, stream_flow)).to eq([event0, event1])
434
286
  end
435
287
 
436
- specify 'unlimited concurrency for :any - everything should succeed', timeout: 10, mutant: false do
288
+ specify "unlimited concurrency for :any - everything should succeed", timeout: 10, mutant: false do
437
289
  skip unless helper.supports_concurrent_any?
438
- verify_conncurency_assumptions
290
+ verify_conncurency_assumptions(helper)
439
291
  begin
440
292
  concurrency_level = 4
441
- fail_occurred = false
442
- wait_for_it = true
293
+ fail_occurred = false
294
+ wait_for_it = true
443
295
 
444
- threads = concurrency_level.times.map do |i|
445
- Thread.new do
446
- true while wait_for_it
447
- begin
448
- 100.times do |j|
449
- eid = "0000000#{i}-#{sprintf("%04d", j)}-0000-0000-000000000000"
450
- repository.append_to_stream([
451
- SRecord.new(event_id: eid),
452
- ], stream, version_any)
296
+ threads =
297
+ concurrency_level.times.map do |i|
298
+ Thread.new do
299
+ true while wait_for_it
300
+ begin
301
+ 100.times do |j|
302
+ eid = "0000000#{i}-#{sprintf("%04d", j)}-0000-0000-000000000000"
303
+ repository.append_to_stream([SRecord.new(event_id: eid)], stream, version_any)
304
+ end
305
+ rescue WrongExpectedEventVersion
306
+ fail_occurred = true
453
307
  end
454
- rescue WrongExpectedEventVersion
455
- fail_occurred = true
456
308
  end
457
309
  end
458
- end
459
310
  wait_for_it = false
460
311
  threads.each(&:join)
461
312
  expect(fail_occurred).to eq(false)
462
313
  expect(read_events_forward(repository, stream).size).to eq(400)
463
314
  events_in_stream = read_events_forward(repository, stream)
464
315
  expect(events_in_stream.size).to eq(400)
465
- events0 = events_in_stream.select do |ev|
466
- ev.event_id.start_with?("0-")
467
- end
468
- expect(events0).to eq(events0.sort_by{|ev| ev.event_id })
469
- ensure
470
- helper.cleanup_concurrency_test
316
+ events0 = events_in_stream.select { |ev| ev.event_id.start_with?("0-") }
317
+ expect(events0).to eq(events0.sort_by { |ev| ev.event_id })
471
318
  end
472
319
  end
473
320
 
474
- specify 'unlimited concurrency for :any - everything should succeed when linking', timeout: 10, mutant: false do
321
+ specify "unlimited concurrency for :any - everything should succeed when linking", timeout: 10, mutant: false do
475
322
  skip unless helper.supports_concurrent_any?
476
- verify_conncurency_assumptions
323
+ verify_conncurency_assumptions(helper)
477
324
  begin
478
325
  concurrency_level = 4
479
- fail_occurred = false
480
- wait_for_it = true
326
+ fail_occurred = false
327
+ wait_for_it = true
481
328
 
482
329
  concurrency_level.times.map do |i|
483
330
  100.times do |j|
484
331
  eid = "0000000#{i}-#{sprintf("%04d", j)}-0000-0000-000000000000"
485
- repository.append_to_stream([
486
- SRecord.new(event_id: eid),
487
- ], stream, version_any)
332
+ repository.append_to_stream([SRecord.new(event_id: eid)], stream, version_any)
488
333
  end
489
334
  end
490
335
 
491
- threads = concurrency_level.times.map do |i|
492
- Thread.new do
493
- true while wait_for_it
494
- begin
495
- 100.times do |j|
496
- eid = "0000000#{i}-#{sprintf("%04d", j)}-0000-0000-000000000000"
497
- repository.link_to_stream([eid], stream_flow, version_any)
336
+ threads =
337
+ concurrency_level.times.map do |i|
338
+ Thread.new do
339
+ true while wait_for_it
340
+ begin
341
+ 100.times do |j|
342
+ eid = "0000000#{i}-#{sprintf("%04d", j)}-0000-0000-000000000000"
343
+ repository.link_to_stream([eid], stream_flow, version_any)
344
+ end
345
+ rescue WrongExpectedEventVersion
346
+ fail_occurred = true
498
347
  end
499
- rescue WrongExpectedEventVersion
500
- fail_occurred = true
501
348
  end
502
349
  end
503
- end
504
350
  wait_for_it = false
505
351
  threads.each(&:join)
506
352
  expect(fail_occurred).to eq(false)
507
353
  expect(read_events_forward(repository, stream_flow).size).to eq(400)
508
354
  events_in_stream = read_events_forward(repository, stream_flow)
509
355
  expect(events_in_stream.size).to eq(400)
510
- events0 = events_in_stream.select do |ev|
511
- ev.event_id.start_with?("0-")
512
- end
513
- expect(events0).to eq(events0.sort_by{|ev| ev.event_id })
514
- ensure
515
- helper.cleanup_concurrency_test
356
+ events0 = events_in_stream.select { |ev| ev.event_id.start_with?("0-") }
357
+ expect(events0).to eq(events0.sort_by { |ev| ev.event_id })
516
358
  end
517
359
  end
518
360
 
519
- specify 'limited concurrency for :auto - some operations will fail without outside lock, stream is ordered', mutant: false do
361
+ specify "limited concurrency for :auto - some operations will fail without outside lock, stream is ordered",
362
+ mutant: false do
520
363
  skip unless helper.supports_concurrent_auto?
521
- verify_conncurency_assumptions
364
+ verify_conncurency_assumptions(helper)
522
365
  begin
523
366
  concurrency_level = 4
524
367
 
525
368
  fail_occurred = 0
526
- wait_for_it = true
369
+ wait_for_it = true
527
370
 
528
- threads = concurrency_level.times.map do |i|
529
- Thread.new do
530
- true while wait_for_it
531
- 100.times do |j|
532
- begin
533
- eid = "0000000#{i}-#{sprintf("%04d", j)}-0000-0000-000000000000"
534
- repository.append_to_stream([
535
- SRecord.new(event_id: eid),
536
- ], stream, version_auto)
537
- sleep(rand(concurrency_level) / 1000.0)
538
- rescue WrongExpectedEventVersion, *helper.rescuable_concurrency_test_errors
539
- fail_occurred +=1
371
+ threads =
372
+ concurrency_level.times.map do |i|
373
+ Thread.new do
374
+ true while wait_for_it
375
+ 100.times do |j|
376
+ begin
377
+ eid = "0000000#{i}-#{sprintf("%04d", j)}-0000-0000-000000000000"
378
+ repository.append_to_stream([SRecord.new(event_id: eid)], stream, version_auto)
379
+ sleep(rand(concurrency_level) / 1000.0)
380
+ rescue WrongExpectedEventVersion
381
+ fail_occurred += 1
382
+ end
540
383
  end
541
384
  end
542
385
  end
543
- end
544
386
  wait_for_it = false
545
387
  threads.each(&:join)
546
388
  expect(fail_occurred).to be > 0
547
389
  events_in_stream = read_events_forward(repository, stream)
548
390
  expect(events_in_stream.size).to be < 400
549
391
  expect(events_in_stream.size).to be >= 100
550
- events0 = events_in_stream.select do |ev|
551
- ev.event_id.start_with?("0-")
552
- end
553
- expect(events0).to eq(events0.sort_by{|ev| ev.event_id })
554
- additional_limited_concurrency_for_auto_check if defined? additional_limited_concurrency_for_auto_check
555
- ensure
556
- helper.cleanup_concurrency_test
392
+ events0 = events_in_stream.select { |ev| ev.event_id.start_with?("0-") }
393
+ expect(events0).to eq(events0.sort_by { |ev| ev.event_id })
394
+
395
+ positions =
396
+ repository
397
+ .read(specification.stream(stream.name).result)
398
+ .map { |r| repository.position_in_stream(r.event_id, stream) }
399
+ expect(positions).to eq((0...positions.size).to_a)
557
400
  end
558
401
  end
559
402
 
560
- specify 'limited concurrency for :auto - some operations will fail without outside lock, stream is ordered', mutant: false do
403
+ specify "limited concurrency for :auto - some operations will fail without outside lock, stream is ordered",
404
+ mutant: false do
561
405
  skip unless helper.supports_concurrent_auto?
562
- verify_conncurency_assumptions
406
+ verify_conncurency_assumptions(helper)
563
407
  begin
564
408
  concurrency_level = 4
565
409
 
566
410
  concurrency_level.times.map do |i|
567
411
  100.times do |j|
568
412
  eid = "0000000#{i}-#{sprintf("%04d", j)}-0000-0000-000000000000"
569
- repository.append_to_stream([
570
- SRecord.new(event_id: eid),
571
- ], stream_other, version_any)
413
+ repository.append_to_stream([SRecord.new(event_id: eid)], stream_other, version_any)
572
414
  end
573
415
  end
574
416
 
575
417
  fail_occurred = 0
576
- wait_for_it = true
418
+ wait_for_it = true
577
419
 
578
- threads = concurrency_level.times.map do |i|
579
- Thread.new do
580
- true while wait_for_it
581
- 100.times do |j|
582
- begin
583
- eid = "0000000#{i}-#{sprintf("%04d", j)}-0000-0000-000000000000"
584
- repository.link_to_stream([eid], stream, version_auto)
585
- sleep(rand(concurrency_level) / 1000.0)
586
- rescue WrongExpectedEventVersion, *helper.rescuable_concurrency_test_errors
587
- fail_occurred +=1
420
+ threads =
421
+ concurrency_level.times.map do |i|
422
+ Thread.new do
423
+ true while wait_for_it
424
+ 100.times do |j|
425
+ begin
426
+ eid = "0000000#{i}-#{sprintf("%04d", j)}-0000-0000-000000000000"
427
+ repository.link_to_stream([eid], stream, version_auto)
428
+ sleep(rand(concurrency_level) / 1000.0)
429
+ rescue WrongExpectedEventVersion
430
+ fail_occurred += 1
431
+ end
588
432
  end
589
433
  end
590
434
  end
591
- end
592
435
  wait_for_it = false
593
436
  threads.each(&:join)
594
437
  expect(fail_occurred).to be > 0
595
438
  events_in_stream = read_events_forward(repository, stream)
596
439
  expect(events_in_stream.size).to be < 400
597
440
  expect(events_in_stream.size).to be >= 100
598
- events0 = events_in_stream.select do |ev|
599
- ev.event_id.start_with?("0-")
600
- end
601
- expect(events0).to eq(events0.sort_by{|ev| ev.event_id })
602
- additional_limited_concurrency_for_auto_check if defined? additional_limited_concurrency_for_auto_check
603
- ensure
604
- helper.cleanup_concurrency_test
441
+ events0 = events_in_stream.select { |ev| ev.event_id.start_with?("0-") }
442
+ expect(events0).to eq(events0.sort_by { |ev| ev.event_id })
443
+
444
+ positions =
445
+ repository
446
+ .read(specification.stream(stream.name).result)
447
+ .map { |r| repository.position_in_stream(r.event_id, stream) }
448
+ expect(positions).to eq((0...positions.size).to_a)
605
449
  end
606
450
  end
607
451
 
608
- it 'appended event is stored in given stream' do
452
+ it "appended event is stored in given stream" do
609
453
  expected_event = SRecord.new
610
454
  repository.append_to_stream([expected_event], stream, version_any)
611
455
  expect(read_events_forward(repository, count: 1).first).to eq(expected_event)
@@ -613,25 +457,22 @@ module RubyEventStore
613
457
  expect(read_events_forward(repository, stream_other)).to be_empty
614
458
  end
615
459
 
616
- it 'data attributes are retrieved' do
460
+ it "data attributes are retrieved" do
617
461
  event = SRecord.new(data: { "order_id" => 3 })
618
462
  repository.append_to_stream([event], stream, version_any)
619
463
  retrieved_event = read_events_forward(repository, count: 1).first
620
464
  expect(retrieved_event.data).to eq({ "order_id" => 3 })
621
465
  end
622
466
 
623
- it 'metadata attributes are retrieved' do
467
+ it "metadata attributes are retrieved" do
624
468
  event = SRecord.new(metadata: { "request_id" => 3 })
625
469
  repository.append_to_stream([event], stream, version_any)
626
470
  retrieved_event = read_events_forward(repository, count: 1).first
627
471
  expect(retrieved_event.metadata).to eq({ "request_id" => 3 })
628
472
  end
629
473
 
630
- it 'data and metadata attributes are retrieved when linking' do
631
- event = SRecord.new(
632
- data: { "order_id" => 3 },
633
- metadata: { "request_id" => 4},
634
- )
474
+ it "data and metadata attributes are retrieved when linking" do
475
+ event = SRecord.new(data: { "order_id" => 3 }, metadata: { "request_id" => 4 })
635
476
  repository
636
477
  .append_to_stream([event], stream, version_any)
637
478
  .link_to_stream([event.event_id], stream_flow, version_any)
@@ -641,17 +482,17 @@ module RubyEventStore
641
482
  expect(event).to eq(retrieved_event)
642
483
  end
643
484
 
644
- it 'does not have deleted streams' do
485
+ it "does not have deleted streams" do
645
486
  repository.append_to_stream([e1 = SRecord.new], stream, version_none)
646
487
  repository.append_to_stream([e2 = SRecord.new], stream_other, version_none)
647
488
 
648
489
  repository.delete_stream(stream)
649
490
  expect(read_events_forward(repository, stream)).to be_empty
650
491
  expect(read_events_forward(repository, stream_other)).to eq([e2])
651
- expect(read_events_forward(repository, count: 10)).to eq([e1,e2])
492
+ expect(read_events_forward(repository, count: 10)).to eq([e1, e2])
652
493
  end
653
494
 
654
- it 'does not have deleted streams with linked events' do
495
+ it "does not have deleted streams with linked events" do
655
496
  repository
656
497
  .append_to_stream([e1 = SRecord.new], stream, version_none)
657
498
  .link_to_stream([e1.event_id], stream_flow, version_none)
@@ -661,51 +502,152 @@ module RubyEventStore
661
502
  expect(read_events_forward(repository, count: 10)).to eq([e1])
662
503
  end
663
504
 
664
- it 'has or has not domain event' do
665
- just_an_id = 'd5c134c2-db65-4e87-b6ea-d196f8f1a292'
505
+ it "has or has not domain event" do
506
+ just_an_id = "d5c134c2-db65-4e87-b6ea-d196f8f1a292"
666
507
  repository.append_to_stream([SRecord.new(event_id: just_an_id)], stream, version_none)
667
508
 
668
509
  expect(repository.has_event?(just_an_id)).to be_truthy
669
510
  expect(repository.has_event?(just_an_id.clone)).to be_truthy
670
- expect(repository.has_event?('any other id')).to be_falsey
511
+ expect(repository.has_event?("any other id")).to be false
671
512
 
672
513
  repository.delete_stream(stream)
673
514
  expect(repository.has_event?(just_an_id)).to be_truthy
674
515
  expect(repository.has_event?(just_an_id.clone)).to be_truthy
675
516
  end
676
517
 
677
- it 'knows last event in stream' do
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)
518
+ it "#position_in_stream happy path" do
519
+ skip unless helper.supports_position_queries?
520
+ repository.append_to_stream([event0 = SRecord.new, event1 = SRecord.new], stream, version_auto)
680
521
 
681
- expect(repository.last_stream_event(stream)).to eq(b)
682
- expect(repository.last_stream_event(stream_other)).to be_nil
522
+ expect(repository.position_in_stream(event0.event_id, stream)).to eq(0)
523
+ expect(repository.position_in_stream(event1.event_id, stream)).to eq(1)
683
524
  end
684
525
 
685
- it 'knows last event in stream when linked' do
686
- repository.append_to_stream([
687
- e0 = SRecord.new(event_id: '00000000-0000-0000-0000-000000000001'),
688
- e1 = SRecord.new(event_id: '00000000-0000-0000-0000-000000000002'),
689
- ],
526
+ it "#position_in_stream happy path with linking" do
527
+ skip unless helper.supports_position_queries?
528
+ repository.append_to_stream([event0 = SRecord.new, event1 = SRecord.new], stream, version_auto)
529
+ repository.link_to_stream([event1.event_id, event0.event_id], stream_other, version_auto)
530
+
531
+ expect(repository.position_in_stream(event0.event_id, stream)).to eq(0)
532
+ expect(repository.position_in_stream(event1.event_id, stream)).to eq(1)
533
+ expect(repository.position_in_stream(event1.event_id, stream_other)).to eq(0)
534
+ expect(repository.position_in_stream(event0.event_id, stream_other)).to eq(1)
535
+ end
536
+
537
+ it "#position_in_stream when event is not in the stream" do
538
+ skip unless helper.supports_position_queries?
539
+ just_an_id = "d5c134c2-db65-4e87-b6ea-d196f8f1a292"
540
+
541
+ expect { repository.position_in_stream(just_an_id, stream) }.to raise_error(EventNotFoundInStream)
542
+ end
543
+
544
+ it "#position_in_stream when event is published without position" do
545
+ skip unless helper.supports_position_queries?
546
+ repository.append_to_stream([event0 = SRecord.new], stream, version_any)
547
+
548
+ expect(repository.position_in_stream(event0.event_id, stream)).to eq(nil)
549
+ end
550
+
551
+ it "#global_position happy path" do
552
+ skip unless helper.supports_position_queries?
553
+ repository.append_to_stream([event0 = SRecord.new, event1 = SRecord.new], stream, version_any)
554
+
555
+ expect(repository.global_position(event0.event_id)).to eq(0)
556
+ expect(repository.global_position(event1.event_id)).to eq(1)
557
+ end
558
+
559
+ it "#global_position for not existing event" do
560
+ skip unless helper.supports_position_queries?
561
+ just_an_id = "d5c134c2-db65-4e87-b6ea-d196f8f1a292"
562
+
563
+ expect { repository.global_position(just_an_id) }.to raise_error do |err|
564
+ expect(err).to be_a(EventNotFound)
565
+ expect(err.event_id).to eq(just_an_id)
566
+ end
567
+ end
568
+
569
+ it "#event_in_stream? when event does not exist" do
570
+ skip unless helper.supports_event_in_stream_query?
571
+ repository.append_to_stream([SRecord.new], stream, version_any)
572
+ just_an_id = "d5c134c2-db65-4e87-b6ea-d196f8f1a292"
573
+
574
+ expect(repository.event_in_stream?(just_an_id, stream)).to eq(false)
575
+ end
576
+
577
+ it "#event_in_stream? when event published into stream" do
578
+ skip unless helper.supports_event_in_stream_query?
579
+ repository.append_to_stream([event0 = SRecord.new], stream, version_any)
580
+
581
+ expect(repository.event_in_stream?(event0.event_id, stream)).to eq(true)
582
+ end
583
+
584
+ it "#event_in_stream? when event not linked into stream" do
585
+ skip unless helper.supports_event_in_stream_query?
586
+ repository.append_to_stream([SRecord.new], stream_flow, version_any)
587
+ repository.append_to_stream([event1 = SRecord.new], stream, version_any)
588
+
589
+ expect(repository.event_in_stream?(event1.event_id, stream_flow)).to eq(false)
590
+ end
591
+
592
+ it "#event_in_stream? when event linked into stream" do
593
+ skip unless helper.supports_event_in_stream_query?
594
+ repository.append_to_stream([event0 = SRecord.new], stream, version_any)
595
+ repository.link_to_stream([event0.event_id], stream_flow, version_any)
596
+
597
+ expect(repository.event_in_stream?(event0.event_id, stream_flow)).to eq(true)
598
+ end
599
+
600
+ it "#event_in_stream? when stream is empty" do
601
+ skip unless helper.supports_event_in_stream_query?
602
+ just_an_id = "d5c134c2-db65-4e87-b6ea-d196f8f1a292"
603
+
604
+ expect(repository.event_in_stream?(just_an_id, stream)).to eq(false)
605
+ end
606
+
607
+ it "knows last event in stream" do
608
+ repository.append_to_stream(
609
+ [a = SRecord.new(event_id: "00000000-0000-0000-0000-000000000001")],
690
610
  stream,
691
611
  version_none
692
- ).link_to_stream([e1.event_id, e0.event_id], stream_flow, version_none)
612
+ )
613
+ repository.append_to_stream(
614
+ [b = SRecord.new(event_id: "00000000-0000-0000-0000-000000000002")],
615
+ stream,
616
+ version_0
617
+ )
618
+
619
+ expect(repository.last_stream_event(stream)).to eq(b)
620
+ expect(repository.last_stream_event(stream_other)).to be_nil
621
+ end
622
+
623
+ it "knows last event in stream when linked" do
624
+ repository
625
+ .append_to_stream(
626
+ [
627
+ e0 = SRecord.new(event_id: "00000000-0000-0000-0000-000000000001"),
628
+ e1 = SRecord.new(event_id: "00000000-0000-0000-0000-000000000002")
629
+ ],
630
+ stream,
631
+ version_none
632
+ )
633
+ .link_to_stream([e1.event_id, e0.event_id], stream_flow, version_none)
693
634
  expect(repository.last_stream_event(stream_flow)).to eq(e0)
694
635
  end
695
636
 
696
- it 'reads batch of events from stream forward & backward' do
697
- events = %w[
698
- 96c920b1-cdd0-40f4-907c-861b9fff7d02
699
- 56404f79-0ba0-4aa0-8524-dc3436368ca0
700
- 6a54dd21-f9d8-4857-a195-f5588d9e406c
701
- 0e50a9cd-f981-4e39-93d5-697fc7285b98
702
- d85589bc-b993-41d4-812f-fc631d9185d5
703
- 96bdacda-77dd-4d7d-973d-cbdaa5842855
704
- 94688199-e6b7-4180-bf8e-825b6808e6cc
705
- 68fab040-741e-4bc2-9cca-5b8855b0ca19
706
- ab60114c-011d-4d58-ab31-7ba65d99975e
707
- 868cac42-3d19-4b39-84e8-cd32d65c2445
708
- ].map { |id| SRecord.new(event_id: id) }
637
+ it "reads batch of events from stream forward & backward" do
638
+ events =
639
+ %w[
640
+ 96c920b1-cdd0-40f4-907c-861b9fff7d02
641
+ 56404f79-0ba0-4aa0-8524-dc3436368ca0
642
+ 6a54dd21-f9d8-4857-a195-f5588d9e406c
643
+ 0e50a9cd-f981-4e39-93d5-697fc7285b98
644
+ d85589bc-b993-41d4-812f-fc631d9185d5
645
+ 96bdacda-77dd-4d7d-973d-cbdaa5842855
646
+ 94688199-e6b7-4180-bf8e-825b6808e6cc
647
+ 68fab040-741e-4bc2-9cca-5b8855b0ca19
648
+ ab60114c-011d-4d58-ab31-7ba65d99975e
649
+ 868cac42-3d19-4b39-84e8-cd32d65c2445
650
+ ].map { |id| SRecord.new(event_id: id) }
709
651
  repository.append_to_stream([SRecord.new], stream_other, version_none)
710
652
  events.each.with_index do |event, index|
711
653
  repository.append_to_stream([event], stream, ExpectedVersion.new(index - 1))
@@ -722,25 +664,30 @@ module RubyEventStore
722
664
 
723
665
  expect(read_events_backward(repository, stream, count: 3)).to eq(events.last(3).reverse)
724
666
  expect(read_events_backward(repository, stream, count: 100)).to eq(events.reverse)
725
- expect(read_events_backward(repository, stream, from: events[4].event_id, count: 4)).to eq(events.first(4).reverse)
726
- expect(read_events_backward(repository, stream, from: events[4].event_id, count: 100)).to eq(events.first(4).reverse)
667
+ expect(read_events_backward(repository, stream, from: events[4].event_id, count: 4)).to eq(
668
+ events.first(4).reverse
669
+ )
670
+ expect(read_events_backward(repository, stream, from: events[4].event_id, count: 100)).to eq(
671
+ events.first(4).reverse
672
+ )
727
673
  expect(read_events_backward(repository, stream, to: events[4].event_id, count: 4)).to eq(events.last(4).reverse)
728
674
  expect(read_events_backward(repository, stream, to: events[4].event_id, count: 100)).to eq(events.last(5).reverse)
729
675
  end
730
676
 
731
- it 'reads batch of linked events from stream forward & backward' do
732
- events = %w[
733
- 96c920b1-cdd0-40f4-907c-861b9fff7d02
734
- 56404f79-0ba0-4aa0-8524-dc3436368ca0
735
- 6a54dd21-f9d8-4857-a195-f5588d9e406c
736
- 0e50a9cd-f981-4e39-93d5-697fc7285b98
737
- d85589bc-b993-41d4-812f-fc631d9185d5
738
- 96bdacda-77dd-4d7d-973d-cbdaa5842855
739
- 94688199-e6b7-4180-bf8e-825b6808e6cc
740
- 68fab040-741e-4bc2-9cca-5b8855b0ca19
741
- ab60114c-011d-4d58-ab31-7ba65d99975e
742
- 868cac42-3d19-4b39-84e8-cd32d65c2445
743
- ].map { |id| SRecord.new(event_id: id) }
677
+ it "reads batch of linked events from stream forward & backward" do
678
+ events =
679
+ %w[
680
+ 96c920b1-cdd0-40f4-907c-861b9fff7d02
681
+ 56404f79-0ba0-4aa0-8524-dc3436368ca0
682
+ 6a54dd21-f9d8-4857-a195-f5588d9e406c
683
+ 0e50a9cd-f981-4e39-93d5-697fc7285b98
684
+ d85589bc-b993-41d4-812f-fc631d9185d5
685
+ 96bdacda-77dd-4d7d-973d-cbdaa5842855
686
+ 94688199-e6b7-4180-bf8e-825b6808e6cc
687
+ 68fab040-741e-4bc2-9cca-5b8855b0ca19
688
+ ab60114c-011d-4d58-ab31-7ba65d99975e
689
+ 868cac42-3d19-4b39-84e8-cd32d65c2445
690
+ ].map { |id| SRecord.new(event_id: id) }
744
691
  repository.append_to_stream([SRecord.new], stream_other, version_none)
745
692
  events.each.with_index do |event, index|
746
693
  repository
@@ -758,60 +705,67 @@ module RubyEventStore
758
705
 
759
706
  expect(read_events_backward(repository, stream_flow, count: 3)).to eq(events.last(3).reverse)
760
707
  expect(read_events_backward(repository, stream_flow, count: 100)).to eq(events.reverse)
761
- expect(read_events_backward(repository, stream_flow, from: events[4].event_id, count: 4)).to eq(events.first(4).reverse)
762
- expect(read_events_backward(repository, stream_flow, from: events[4].event_id, count: 100)).to eq(events.first(4).reverse)
763
- expect(read_events_backward(repository, stream_flow, to: events[4].event_id, count: 4)).to eq(events[6..9].reverse)
764
- expect(read_events_backward(repository, stream_flow, to: events[4].event_id, count: 100)).to eq(events[5..9].reverse)
708
+ expect(read_events_backward(repository, stream_flow, from: events[4].event_id, count: 4)).to eq(
709
+ events.first(4).reverse
710
+ )
711
+ expect(read_events_backward(repository, stream_flow, from: events[4].event_id, count: 100)).to eq(
712
+ events.first(4).reverse
713
+ )
714
+ expect(read_events_backward(repository, stream_flow, to: events[4].event_id, count: 4)).to eq(
715
+ events[6..9].reverse
716
+ )
717
+ expect(read_events_backward(repository, stream_flow, to: events[4].event_id, count: 100)).to eq(
718
+ events[5..9].reverse
719
+ )
765
720
  end
766
721
 
767
- it 'reads all stream events forward & backward' do
722
+ it "reads all stream events forward & backward" do
768
723
  s1 = stream
769
724
  s2 = stream_other
770
725
  repository
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)
726
+ .append_to_stream([a = SRecord.new(event_id: "7010d298-ab69-4bb1-9251-f3466b5d1282")], s1, version_none)
727
+ .append_to_stream([b = SRecord.new(event_id: "34f88aca-aaba-4ca0-9256-8017b47528c5")], s2, version_none)
728
+ .append_to_stream([c = SRecord.new(event_id: "8e61c864-ceae-4684-8726-97c34eb8fc4f")], s1, version_0)
729
+ .append_to_stream([d = SRecord.new(event_id: "30963ed9-6349-450b-ac9b-8ea50115b3bd")], s2, version_0)
730
+ .append_to_stream([e = SRecord.new(event_id: "5bdc58b7-e8a7-4621-afd6-ccb828d72457")], s2, version_1)
776
731
 
777
- expect(read_events_forward(repository, s1)).to eq [a,c]
778
- expect(read_events_backward(repository, s1)).to eq [c,a]
732
+ expect(read_events_forward(repository, s1)).to eq [a, c]
733
+ expect(read_events_backward(repository, s1)).to eq [c, a]
779
734
  end
780
735
 
781
- it 'reads all stream linked events forward & backward' do
736
+ it "reads all stream linked events forward & backward" do
782
737
  s1, fs1, fs2 = stream, stream_flow, stream_other
783
738
  repository
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)
794
-
795
- expect(read_events_forward(repository, fs1)).to eq [a,c]
796
- expect(read_events_backward(repository, fs1)).to eq [c,a]
797
- end
798
-
799
- it 'reads batch of events from all streams forward & backward' do
800
- events = %w[
801
- 96c920b1-cdd0-40f4-907c-861b9fff7d02
802
- 56404f79-0ba0-4aa0-8524-dc3436368ca0
803
- 6a54dd21-f9d8-4857-a195-f5588d9e406c
804
- 0e50a9cd-f981-4e39-93d5-697fc7285b98
805
- d85589bc-b993-41d4-812f-fc631d9185d5
806
- 96bdacda-77dd-4d7d-973d-cbdaa5842855
807
- 94688199-e6b7-4180-bf8e-825b6808e6cc
808
- 68fab040-741e-4bc2-9cca-5b8855b0ca19
809
- ab60114c-011d-4d58-ab31-7ba65d99975e
810
- 868cac42-3d19-4b39-84e8-cd32d65c2445
811
- ].map { |id| SRecord.new(event_id: id) }
812
- events.each do |ev|
813
- repository.append_to_stream([ev], Stream.new(SecureRandom.uuid), version_none)
814
- end
739
+ .append_to_stream([a = SRecord.new(event_id: "7010d298-ab69-4bb1-9251-f3466b5d1282")], s1, version_none)
740
+ .append_to_stream([b = SRecord.new(event_id: "34f88aca-aaba-4ca0-9256-8017b47528c5")], s1, version_0)
741
+ .append_to_stream([c = SRecord.new(event_id: "8e61c864-ceae-4684-8726-97c34eb8fc4f")], s1, version_1)
742
+ .append_to_stream([d = SRecord.new(event_id: "30963ed9-6349-450b-ac9b-8ea50115b3bd")], s1, version_2)
743
+ .append_to_stream([e = SRecord.new(event_id: "5bdc58b7-e8a7-4621-afd6-ccb828d72457")], s1, version_3)
744
+ .link_to_stream(["7010d298-ab69-4bb1-9251-f3466b5d1282"], fs1, version_none)
745
+ .link_to_stream(["34f88aca-aaba-4ca0-9256-8017b47528c5"], fs2, version_none)
746
+ .link_to_stream(["8e61c864-ceae-4684-8726-97c34eb8fc4f"], fs1, version_0)
747
+ .link_to_stream(["30963ed9-6349-450b-ac9b-8ea50115b3bd"], fs2, version_0)
748
+ .link_to_stream(["5bdc58b7-e8a7-4621-afd6-ccb828d72457"], fs2, version_1)
749
+
750
+ expect(read_events_forward(repository, fs1)).to eq [a, c]
751
+ expect(read_events_backward(repository, fs1)).to eq [c, a]
752
+ end
753
+
754
+ it "reads batch of events from all streams forward & backward" do
755
+ events =
756
+ %w[
757
+ 96c920b1-cdd0-40f4-907c-861b9fff7d02
758
+ 56404f79-0ba0-4aa0-8524-dc3436368ca0
759
+ 6a54dd21-f9d8-4857-a195-f5588d9e406c
760
+ 0e50a9cd-f981-4e39-93d5-697fc7285b98
761
+ d85589bc-b993-41d4-812f-fc631d9185d5
762
+ 96bdacda-77dd-4d7d-973d-cbdaa5842855
763
+ 94688199-e6b7-4180-bf8e-825b6808e6cc
764
+ 68fab040-741e-4bc2-9cca-5b8855b0ca19
765
+ ab60114c-011d-4d58-ab31-7ba65d99975e
766
+ 868cac42-3d19-4b39-84e8-cd32d65c2445
767
+ ].map { |id| SRecord.new(event_id: id) }
768
+ events.each { |ev| repository.append_to_stream([ev], Stream.new(SecureRandom.uuid), version_none) }
815
769
 
816
770
  expect(read_events_forward(repository, count: 3)).to eq(events.first(3))
817
771
  expect(read_events_forward(repository, count: 100)).to eq(events)
@@ -828,19 +782,20 @@ module RubyEventStore
828
782
  expect(read_events_backward(repository, to: events[4].event_id, count: 100)).to eq(events.last(5).reverse)
829
783
  end
830
784
 
831
- it 'linked events do not affect reading from all streams - no duplicates' do
832
- events = %w[
833
- 96c920b1-cdd0-40f4-907c-861b9fff7d02
834
- 56404f79-0ba0-4aa0-8524-dc3436368ca0
835
- 6a54dd21-f9d8-4857-a195-f5588d9e406c
836
- 0e50a9cd-f981-4e39-93d5-697fc7285b98
837
- d85589bc-b993-41d4-812f-fc631d9185d5
838
- 96bdacda-77dd-4d7d-973d-cbdaa5842855
839
- 94688199-e6b7-4180-bf8e-825b6808e6cc
840
- 68fab040-741e-4bc2-9cca-5b8855b0ca19
841
- ab60114c-011d-4d58-ab31-7ba65d99975e
842
- 868cac42-3d19-4b39-84e8-cd32d65c2445
843
- ].map { |id| SRecord.new(event_id: id) }
785
+ it "linked events do not affect reading from all streams - no duplicates" do
786
+ events =
787
+ %w[
788
+ 96c920b1-cdd0-40f4-907c-861b9fff7d02
789
+ 56404f79-0ba0-4aa0-8524-dc3436368ca0
790
+ 6a54dd21-f9d8-4857-a195-f5588d9e406c
791
+ 0e50a9cd-f981-4e39-93d5-697fc7285b98
792
+ d85589bc-b993-41d4-812f-fc631d9185d5
793
+ 96bdacda-77dd-4d7d-973d-cbdaa5842855
794
+ 94688199-e6b7-4180-bf8e-825b6808e6cc
795
+ 68fab040-741e-4bc2-9cca-5b8855b0ca19
796
+ ab60114c-011d-4d58-ab31-7ba65d99975e
797
+ 868cac42-3d19-4b39-84e8-cd32d65c2445
798
+ ].map { |id| SRecord.new(event_id: id) }
844
799
  events.each do |ev|
845
800
  repository
846
801
  .append_to_stream([ev], Stream.new(SecureRandom.uuid), version_none)
@@ -862,46 +817,44 @@ module RubyEventStore
862
817
  expect(read_events_backward(repository, to: events[4].event_id, count: 100)).to eq(events.last(5).reverse)
863
818
  end
864
819
 
865
- it 'reads events different uuid object but same content' do
866
- events = %w[
867
- 96c920b1-cdd0-40f4-907c-861b9fff7d02
868
- 56404f79-0ba0-4aa0-8524-dc3436368ca0
869
- ].map{|id| SRecord.new(event_id: id) }
820
+ it "reads events different uuid object but same content" do
821
+ events =
822
+ %w[96c920b1-cdd0-40f4-907c-861b9fff7d02 56404f79-0ba0-4aa0-8524-dc3436368ca0].map do |id|
823
+ SRecord.new(event_id: id)
824
+ end
870
825
  repository.append_to_stream([events.first], stream, version_none)
871
- repository.append_to_stream([events.last], stream, version_0)
826
+ repository.append_to_stream([events.last], stream, version_0)
872
827
 
873
828
  expect(read_events_forward(repository, from: "96c920b1-cdd0-40f4-907c-861b9fff7d02")).to eq([events.last])
874
829
  expect(read_events_backward(repository, from: "56404f79-0ba0-4aa0-8524-dc3436368ca0")).to eq([events.first])
875
- expect(read_events_forward(repository, to: "56404f79-0ba0-4aa0-8524-dc3436368ca0", count: 1)).to eq([events.first])
876
- expect(read_events_backward(repository, to: "96c920b1-cdd0-40f4-907c-861b9fff7d02", count: 1)).to eq([events.last])
830
+ expect(read_events_forward(repository, to: "56404f79-0ba0-4aa0-8524-dc3436368ca0", count: 1)).to eq(
831
+ [events.first]
832
+ )
833
+ expect(read_events_backward(repository, to: "96c920b1-cdd0-40f4-907c-861b9fff7d02", count: 1)).to eq(
834
+ [events.last]
835
+ )
877
836
 
878
837
  expect(read_events_forward(repository, stream, from: "96c920b1-cdd0-40f4-907c-861b9fff7d02")).to eq([events.last])
879
- expect(read_events_backward(repository, stream, from: "56404f79-0ba0-4aa0-8524-dc3436368ca0")).to eq([events.first])
880
- expect(read_events_forward(repository, stream, to: "56404f79-0ba0-4aa0-8524-dc3436368ca0", count: 1)).to eq([events.first])
881
- expect(read_events_backward(repository, stream, to: "96c920b1-cdd0-40f4-907c-861b9fff7d02", count: 1)).to eq([events.last])
838
+ expect(read_events_backward(repository, stream, from: "56404f79-0ba0-4aa0-8524-dc3436368ca0")).to eq(
839
+ [events.first]
840
+ )
841
+ expect(read_events_forward(repository, stream, to: "56404f79-0ba0-4aa0-8524-dc3436368ca0", count: 1)).to eq(
842
+ [events.first]
843
+ )
844
+ expect(read_events_backward(repository, stream, to: "96c920b1-cdd0-40f4-907c-861b9fff7d02", count: 1)).to eq(
845
+ [events.last]
846
+ )
882
847
  end
883
848
 
884
- it 'does not allow same event twice in a stream' do
885
- repository.append_to_stream(
886
- [SRecord.new(event_id: "a1b49edb-7636-416f-874a-88f94b859bef")],
887
- stream,
888
- version_none
889
- )
849
+ it "does not allow same event twice in a stream" do
850
+ repository.append_to_stream([SRecord.new(event_id: "a1b49edb-7636-416f-874a-88f94b859bef")], stream, version_none)
890
851
  expect do
891
- repository.append_to_stream(
892
- [SRecord.new(event_id: "a1b49edb-7636-416f-874a-88f94b859bef")],
893
- stream,
894
- version_0
895
- )
852
+ repository.append_to_stream([SRecord.new(event_id: "a1b49edb-7636-416f-874a-88f94b859bef")], stream, version_0)
896
853
  end.to raise_error(EventDuplicatedInStream)
897
854
  end
898
855
 
899
- it 'does not allow same event twice' do
900
- repository.append_to_stream(
901
- [SRecord.new(event_id: "a1b49edb-7636-416f-874a-88f94b859bef")],
902
- stream,
903
- version_none
904
- )
856
+ it "does not allow same event twice" do
857
+ repository.append_to_stream([SRecord.new(event_id: "a1b49edb-7636-416f-874a-88f94b859bef")], stream, version_none)
905
858
  expect do
906
859
  repository.append_to_stream(
907
860
  [SRecord.new(event_id: "a1b49edb-7636-416f-874a-88f94b859bef")],
@@ -911,18 +864,16 @@ module RubyEventStore
911
864
  end.to raise_error(EventDuplicatedInStream)
912
865
  end
913
866
 
914
- it 'does not allow linking same event twice in a stream' do
915
- repository.append_to_stream(
916
- [SRecord.new(event_id: "a1b49edb-7636-416f-874a-88f94b859bef")],
917
- stream,
918
- version_none
919
- ).link_to_stream(["a1b49edb-7636-416f-874a-88f94b859bef"], stream_flow, version_none)
867
+ it "does not allow linking same event twice in a stream" do
868
+ repository
869
+ .append_to_stream([SRecord.new(event_id: "a1b49edb-7636-416f-874a-88f94b859bef")], stream, version_none)
870
+ .link_to_stream(["a1b49edb-7636-416f-874a-88f94b859bef"], stream_flow, version_none)
920
871
  expect do
921
872
  repository.link_to_stream(["a1b49edb-7636-416f-874a-88f94b859bef"], stream_flow, version_0)
922
873
  end.to raise_error(EventDuplicatedInStream)
923
874
  end
924
875
 
925
- it 'allows appending to GLOBAL_STREAM explicitly' do
876
+ it "allows appending to GLOBAL_STREAM explicitly" do
926
877
  event = SRecord.new(event_id: "df8b2ba3-4e2c-4888-8d14-4364855fa80e")
927
878
  repository.append_to_stream([event], global_stream, version_any)
928
879
 
@@ -934,65 +885,53 @@ module RubyEventStore
934
885
 
935
886
  expect do
936
887
  repository.append_to_stream(
937
- [SRecord.new(event_id: '9bedf448-e4d0-41a3-a8cd-f94aec7aa763')],
888
+ [SRecord.new(event_id: "9bedf448-e4d0-41a3-a8cd-f94aec7aa763")],
938
889
  stream,
939
890
  version_none
940
891
  )
941
892
  end.to raise_error(WrongExpectedEventVersion)
942
- expect(repository.has_event?('9bedf448-e4d0-41a3-a8cd-f94aec7aa763')).to be_falsey
893
+ expect(repository.has_event?("9bedf448-e4d0-41a3-a8cd-f94aec7aa763")).to be false
943
894
  end
944
895
 
945
- specify 'linking non-existent event' do
896
+ specify "linking non-existent event" do
946
897
  expect do
947
- repository.link_to_stream(['72922e65-1b32-4e97-8023-03ae81dd3a27'], stream_flow, version_none)
898
+ repository.link_to_stream(["72922e65-1b32-4e97-8023-03ae81dd3a27"], stream_flow, version_none)
948
899
  end.to raise_error do |err|
949
900
  expect(err).to be_a(EventNotFound)
950
- expect(err.event_id).to eq('72922e65-1b32-4e97-8023-03ae81dd3a27')
951
- expect(err.message).to eq('Event not found: 72922e65-1b32-4e97-8023-03ae81dd3a27')
901
+ expect(err.event_id).to eq("72922e65-1b32-4e97-8023-03ae81dd3a27")
902
+ expect(err.message).to eq("Event not found: 72922e65-1b32-4e97-8023-03ae81dd3a27")
952
903
  end
953
904
  end
954
905
 
955
- specify 'read returns enumerator' do
906
+ specify "read returns enumerator" do
956
907
  expect(repository.read(specification.result)).to be_kind_of(Enumerator)
957
908
  end
958
909
 
959
- specify 'can store arbitrary binary data' do
910
+ specify "can store arbitrary binary data" do
960
911
  skip unless helper.supports_binary?
961
912
  binary = "\xB0"
962
913
  expect(binary.valid_encoding?).to eq(false)
963
914
  binary.force_encoding("binary")
964
915
  expect(binary.valid_encoding?).to eq(true)
965
916
 
966
- repository.append_to_stream(
967
- [event = SRecord.new(data: binary, metadata: binary)],
968
- stream,
969
- version_none
970
- )
917
+ repository.append_to_stream([event = SRecord.new(data: binary, metadata: binary)], stream, version_none)
971
918
  end
972
919
 
973
920
  specify do
974
921
  expect(repository.read(specification.in_batches.result)).to be_kind_of(Enumerator)
922
+ expect(repository.read(specification.in_batches.as_at.result)).to be_kind_of(Enumerator)
923
+ expect(repository.read(specification.in_batches.as_of.result)).to be_kind_of(Enumerator)
975
924
  events = Array.new(10) { SRecord.new }
976
- repository.append_to_stream(
977
- events,
978
- Stream.new("Dummy"),
979
- ExpectedVersion.none
980
- )
925
+ repository.append_to_stream(events, Stream.new("Dummy"), ExpectedVersion.none)
981
926
  expect(repository.read(specification.in_batches.result)).to be_kind_of(Enumerator)
927
+ expect(repository.read(specification.in_batches.as_at.result)).to be_kind_of(Enumerator)
928
+ expect(repository.read(specification.in_batches.as_of.result)).to be_kind_of(Enumerator)
982
929
  end
983
930
 
984
931
  specify do
985
932
  events = Array.new(400) { SRecord.new }
986
- repository.append_to_stream(
987
- events[200...400],
988
- Stream.new("Foo"),
989
- ExpectedVersion.none
990
- )
991
- repository.append_to_stream(
992
- events[0...200],
993
- Stream.new("Dummy"),
994
- ExpectedVersion.none
995
- )
933
+ repository.append_to_stream(events[200...400], Stream.new("Foo"), ExpectedVersion.none)
934
+ repository.append_to_stream(events[0...200], Stream.new("Dummy"), ExpectedVersion.none)
996
935
 
997
936
  batches = repository.read(specification.stream("Dummy").in_batches.result).to_a
998
937
  expect(batches.size).to eq(2)
@@ -1002,11 +941,7 @@ module RubyEventStore
1002
941
 
1003
942
  specify do
1004
943
  events = Array.new(200) { SRecord.new }
1005
- repository.append_to_stream(
1006
- events,
1007
- Stream.new(GLOBAL_STREAM),
1008
- ExpectedVersion.any
1009
- )
944
+ repository.append_to_stream(events, Stream.new(GLOBAL_STREAM), ExpectedVersion.any)
1010
945
 
1011
946
  batches = repository.read(specification.in_batches.result).to_a
1012
947
  expect(batches.size).to eq(2)
@@ -1016,22 +951,14 @@ module RubyEventStore
1016
951
 
1017
952
  specify do
1018
953
  events = Array.new(200) { SRecord.new }
1019
- repository.append_to_stream(
1020
- events,
1021
- Stream.new(GLOBAL_STREAM),
1022
- ExpectedVersion.any
1023
- )
954
+ repository.append_to_stream(events, Stream.new(GLOBAL_STREAM), ExpectedVersion.any)
1024
955
 
1025
956
  expect(repository.read(specification.in_batches(200).result).to_a.size).to eq(1)
1026
957
  end
1027
958
 
1028
959
  specify do
1029
960
  events = Array.new(200) { SRecord.new }
1030
- repository.append_to_stream(
1031
- events,
1032
- Stream.new(GLOBAL_STREAM),
1033
- ExpectedVersion.any
1034
- )
961
+ repository.append_to_stream(events, Stream.new(GLOBAL_STREAM), ExpectedVersion.any)
1035
962
 
1036
963
  batches = repository.read(specification.limit(199).in_batches.result).to_a
1037
964
  expect(batches.size).to eq(2)
@@ -1043,11 +970,7 @@ module RubyEventStore
1043
970
 
1044
971
  specify do
1045
972
  events = Array.new(200) { SRecord.new }
1046
- repository.append_to_stream(
1047
- events,
1048
- Stream.new(GLOBAL_STREAM),
1049
- ExpectedVersion.any
1050
- )
973
+ repository.append_to_stream(events, Stream.new(GLOBAL_STREAM), ExpectedVersion.any)
1051
974
 
1052
975
  batches = repository.read(specification.limit(99).in_batches.result).to_a
1053
976
  expect(batches.size).to eq(1)
@@ -1057,11 +980,7 @@ module RubyEventStore
1057
980
 
1058
981
  specify do
1059
982
  events = Array.new(200) { SRecord.new }
1060
- repository.append_to_stream(
1061
- events,
1062
- Stream.new(GLOBAL_STREAM),
1063
- ExpectedVersion.any
1064
- )
983
+ repository.append_to_stream(events, Stream.new(GLOBAL_STREAM), ExpectedVersion.any)
1065
984
 
1066
985
  batches = repository.read(specification.backward.limit(99).in_batches.result).to_a
1067
986
  expect(batches.size).to eq(1)
@@ -1071,11 +990,7 @@ module RubyEventStore
1071
990
 
1072
991
  specify do
1073
992
  events = Array.new(200) { SRecord.new }
1074
- repository.append_to_stream(
1075
- events,
1076
- Stream.new(GLOBAL_STREAM),
1077
- ExpectedVersion.any
1078
- )
993
+ repository.append_to_stream(events, Stream.new(GLOBAL_STREAM), ExpectedVersion.any)
1079
994
 
1080
995
  batches = repository.read(specification.from(events[100].event_id).limit(99).in_batches.result).to_a
1081
996
  expect(batches.size).to eq(1)
@@ -1088,11 +1003,7 @@ module RubyEventStore
1088
1003
  expect(repository.read(specification.read_last.result)).to be_nil
1089
1004
 
1090
1005
  events = Array.new(5) { SRecord.new }
1091
- repository.append_to_stream(
1092
- events,
1093
- Stream.new(GLOBAL_STREAM),
1094
- ExpectedVersion.any
1095
- )
1006
+ repository.append_to_stream(events, Stream.new(GLOBAL_STREAM), ExpectedVersion.any)
1096
1007
 
1097
1008
  expect(repository.read(specification.stream("Any").read_first.result)).to be_nil
1098
1009
  expect(repository.read(specification.stream("Any").read_last.result)).to be_nil
@@ -1132,33 +1043,70 @@ module RubyEventStore
1132
1043
  specify "changes events" do
1133
1044
  skip unless helper.supports_upsert?
1134
1045
  events = Array.new(5) { SRecord.new }
1135
- repository.append_to_stream(
1136
- events[0..2],
1137
- Stream.new("whatever"),
1138
- ExpectedVersion.any
1046
+ repository.append_to_stream(events[0..2], Stream.new("whatever"), ExpectedVersion.any)
1047
+ repository.append_to_stream(events[3..4], Stream.new("elo"), ExpectedVersion.any)
1048
+ repository.update_messages(
1049
+ [
1050
+ a =
1051
+ SRecord.new(
1052
+ event_id: events[0].event_id.clone,
1053
+ data: events[0].data,
1054
+ metadata: events[0].metadata,
1055
+ event_type: events[0].event_type,
1056
+ timestamp: events[0].timestamp
1057
+ ),
1058
+ b =
1059
+ SRecord.new(
1060
+ event_id: events[1].event_id.dup,
1061
+ data: {
1062
+ "test" => 1
1063
+ },
1064
+ metadata: events[1].metadata,
1065
+ event_type: events[1].event_type,
1066
+ timestamp: events[1].timestamp
1067
+ ),
1068
+ c =
1069
+ SRecord.new(
1070
+ event_id: events[2].event_id,
1071
+ data: events[2].data,
1072
+ metadata: {
1073
+ "test" => 2
1074
+ },
1075
+ event_type: events[2].event_type,
1076
+ timestamp: events[2].timestamp
1077
+ ),
1078
+ d =
1079
+ SRecord.new(
1080
+ event_id: events[3].event_id.clone,
1081
+ data: events[3].data,
1082
+ metadata: events[3].metadata,
1083
+ event_type: "event_type3",
1084
+ timestamp: events[3].timestamp
1085
+ ),
1086
+ e =
1087
+ SRecord.new(
1088
+ event_id: events[4].event_id.dup,
1089
+ data: {
1090
+ "test" => 4
1091
+ },
1092
+ metadata: {
1093
+ "test" => 42
1094
+ },
1095
+ event_type: "event_type4",
1096
+ timestamp: events[4].timestamp
1097
+ )
1098
+ ]
1139
1099
  )
1140
- repository.append_to_stream(
1141
- events[3..4],
1142
- Stream.new("elo"),
1143
- ExpectedVersion.any
1144
- )
1145
- repository.update_messages([
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),
1151
- ])
1152
-
1153
- expect(repository.read(specification.result).to_a).to eq([a,b,c,d,e])
1154
- expect(repository.read(specification.stream("whatever").result).to_a).to eq([a,b,c])
1155
- expect(repository.read(specification.stream("elo").result).to_a).to eq([d,e])
1100
+
1101
+ expect(repository.read(specification.result).to_a).to eq([a, b, c, d, e])
1102
+ expect(repository.read(specification.stream("whatever").result).to_a).to eq([a, b, c])
1103
+ expect(repository.read(specification.stream("elo").result).to_a).to eq([d, e])
1156
1104
  end
1157
1105
 
1158
1106
  specify "cannot change unexisting event" do
1159
1107
  skip unless helper.supports_upsert?
1160
1108
  e = SRecord.new
1161
- expect{ repository.update_messages([e]) }.to raise_error do |err|
1109
+ expect { repository.update_messages([e]) }.to raise_error do |err|
1162
1110
  expect(err).to be_a(EventNotFound)
1163
1111
  expect(err.event_id).to eq(e.event_id)
1164
1112
  expect(err.message).to eq("Event not found: #{e.event_id}")
@@ -1175,51 +1123,63 @@ module RubyEventStore
1175
1123
  end
1176
1124
 
1177
1125
  specify do
1178
- event_1 = SRecord.new(event_id: '8a6f053e-3ce2-4c82-a55b-4d02c66ae6ea')
1179
- event_2 = SRecord.new(event_id: '8cee1139-4f96-483a-a175-2b947283c3c7')
1180
- event_3 = SRecord.new(event_id: 'd345f86d-b903-4d78-803f-38990c078d9e')
1181
- stream_a = Stream.new('Stream A')
1182
- stream_b = Stream.new('Stream B')
1183
- stream_c = Stream.new('Stream C')
1126
+ event_1 = SRecord.new(event_id: "8a6f053e-3ce2-4c82-a55b-4d02c66ae6ea")
1127
+ event_2 = SRecord.new(event_id: "8cee1139-4f96-483a-a175-2b947283c3c7")
1128
+ event_3 = SRecord.new(event_id: "d345f86d-b903-4d78-803f-38990c078d9e")
1129
+ stream_a = Stream.new("Stream A")
1130
+ stream_b = Stream.new("Stream B")
1131
+ stream_c = Stream.new("Stream C")
1184
1132
  repository.append_to_stream([event_1, event_2], stream_a, version_any)
1185
1133
  repository.append_to_stream([event_3], stream_b, version_any)
1186
1134
  repository.link_to_stream([event_1.event_id], stream_c, version_none)
1187
1135
 
1188
- expect(repository.streams_of('8a6f053e-3ce2-4c82-a55b-4d02c66ae6ea')).to eq [stream_a, stream_c]
1189
- expect(repository.streams_of('8cee1139-4f96-483a-a175-2b947283c3c7')).to eq [stream_a]
1190
- expect(repository.streams_of('d345f86d-b903-4d78-803f-38990c078d9e')).to eq [stream_b]
1191
- expect(repository.streams_of('d10c8fe9-2163-418d-ba47-88c9a1f9391b')).to eq []
1136
+ expect(repository.streams_of("8a6f053e-3ce2-4c82-a55b-4d02c66ae6ea")).to eq [stream_a, stream_c]
1137
+ expect(repository.streams_of("8cee1139-4f96-483a-a175-2b947283c3c7")).to eq [stream_a]
1138
+ expect(repository.streams_of("d345f86d-b903-4d78-803f-38990c078d9e")).to eq [stream_b]
1139
+ expect(repository.streams_of("d10c8fe9-2163-418d-ba47-88c9a1f9391b")).to eq []
1192
1140
  end
1193
1141
 
1194
1142
  specify do
1195
- e1 = SRecord.new(event_id: '8a6f053e-3ce2-4c82-a55b-4d02c66ae6ea')
1196
- e2 = SRecord.new(event_id: '8cee1139-4f96-483a-a175-2b947283c3c7')
1197
- e3 = SRecord.new(event_id: 'd345f86d-b903-4d78-803f-38990c078d9e')
1198
- stream = Stream.new('Stream A')
1143
+ e1 = SRecord.new(event_id: "8a6f053e-3ce2-4c82-a55b-4d02c66ae6ea")
1144
+ e2 = SRecord.new(event_id: "8cee1139-4f96-483a-a175-2b947283c3c7")
1145
+ e3 = SRecord.new(event_id: "d345f86d-b903-4d78-803f-38990c078d9e")
1146
+ stream = Stream.new("Stream A")
1199
1147
  repository.append_to_stream([e1, e2, e3], stream, version_any)
1200
1148
 
1201
- expect(repository.read(specification.with_id([
1202
- '8a6f053e-3ce2-4c82-a55b-4d02c66ae6ea'
1203
- ]).read_first.result)).to eq(e1)
1204
- expect(repository.read(specification.with_id([
1205
- 'd345f86d-b903-4d78-803f-38990c078d9e'
1206
- ]).read_first.result)).to eq(e3)
1207
- expect(repository.read(specification.with_id([
1208
- 'c31b327c-0da1-4178-a3cd-d2f6bb5d0688'
1209
- ]).read_first.result)).to eq(nil)
1210
- expect(repository.read(specification.with_id([
1211
- '8a6f053e-3ce2-4c82-a55b-4d02c66ae6ea',
1212
- 'd345f86d-b903-4d78-803f-38990c078d9e'
1213
- ]).in_batches.result).to_a[0]).to eq([e1,e3])
1214
- expect(repository.read(specification.stream('Stream A').with_id([
1215
- '8cee1139-4f96-483a-a175-2b947283c3c7'
1216
- ]).read_first.result)).to eq(e2)
1217
- expect(repository.read(specification.stream('Stream B').with_id([
1218
- '8cee1139-4f96-483a-a175-2b947283c3c7'
1219
- ]).read_first.result)).to eq(nil)
1220
- expect(repository.read(specification.stream('Stream B').with_id([
1221
- 'c31b327c-0da1-4178-a3cd-d2f6bb5d0688'
1222
- ]).read_first.result)).to eq(nil)
1149
+ expect(repository.read(specification.with_id(["8a6f053e-3ce2-4c82-a55b-4d02c66ae6ea"]).read_first.result)).to eq(
1150
+ e1
1151
+ )
1152
+ expect(repository.read(specification.with_id(["d345f86d-b903-4d78-803f-38990c078d9e"]).read_first.result)).to eq(
1153
+ e3
1154
+ )
1155
+ expect(repository.read(specification.with_id(["c31b327c-0da1-4178-a3cd-d2f6bb5d0688"]).read_first.result)).to eq(
1156
+ nil
1157
+ )
1158
+ expect(
1159
+ repository.read(
1160
+ specification
1161
+ .with_id(%w[8a6f053e-3ce2-4c82-a55b-4d02c66ae6ea d345f86d-b903-4d78-803f-38990c078d9e])
1162
+ .in_batches
1163
+ .result
1164
+ ).to_a[
1165
+ 0
1166
+ ]
1167
+ ).to eq([e1, e3])
1168
+ expect(
1169
+ repository.read(
1170
+ specification.stream("Stream A").with_id(["8cee1139-4f96-483a-a175-2b947283c3c7"]).read_first.result
1171
+ )
1172
+ ).to eq(e2)
1173
+ expect(
1174
+ repository.read(
1175
+ specification.stream("Stream B").with_id(["8cee1139-4f96-483a-a175-2b947283c3c7"]).read_first.result
1176
+ )
1177
+ ).to eq(nil)
1178
+ expect(
1179
+ repository.read(
1180
+ specification.stream("Stream B").with_id(["c31b327c-0da1-4178-a3cd-d2f6bb5d0688"]).read_first.result
1181
+ )
1182
+ ).to eq(nil)
1223
1183
  expect(repository.read(specification.with_id([]).result).to_a).to eq([])
1224
1184
  end
1225
1185
 
@@ -1227,23 +1187,21 @@ module RubyEventStore
1227
1187
  e1 = SRecord.new(event_type: Type1.to_s)
1228
1188
  e2 = SRecord.new(event_type: Type2.to_s)
1229
1189
  e3 = SRecord.new(event_type: Type1.to_s)
1230
- stream = Stream.new('Stream A')
1190
+ stream = Stream.new("Stream A")
1231
1191
  repository.append_to_stream([e1, e2, e3], stream, version_any)
1232
1192
 
1233
- expect(repository.read(specification.of_type([Type1]).result).to_a).to eq([e1,e3])
1193
+ expect(repository.read(specification.of_type([Type1]).result).to_a).to eq([e1, e3])
1234
1194
  expect(repository.read(specification.of_type([Type2]).result).to_a).to eq([e2])
1235
1195
  expect(repository.read(specification.of_type([Type3]).result).to_a).to eq([])
1236
- expect(repository.read(specification.of_type([Type1, Type2, Type3]).result).to_a).to eq([e1,e2,e3])
1196
+ expect(repository.read(specification.of_type([Type1, Type2, Type3]).result).to_a).to eq([e1, e2, e3])
1237
1197
  end
1238
1198
 
1239
1199
  specify do
1240
- stream = Stream.new('Stream A')
1241
- dummy = Stream.new('Dummy')
1200
+ stream = Stream.new("Stream A")
1201
+ dummy = Stream.new("Dummy")
1242
1202
 
1243
1203
  expect(repository.count(specification.result)).to eq(0)
1244
- (1..3).each do
1245
- repository.append_to_stream([SRecord.new(event_type: Type1.to_s)], stream, version_any)
1246
- end
1204
+ (1..3).each { repository.append_to_stream([SRecord.new(event_type: Type1.to_s)], stream, version_any) }
1247
1205
  expect(repository.count(specification.result)).to eq(3)
1248
1206
  event_id = SecureRandom.uuid
1249
1207
  repository.append_to_stream([SRecord.new(event_type: Type1.to_s, event_id: event_id)], dummy, version_any)
@@ -1256,8 +1214,8 @@ module RubyEventStore
1256
1214
  expect(repository.count(specification.with_id([not_existing_uuid]).result)).to eq(0)
1257
1215
 
1258
1216
  expect(repository.count(specification.stream(stream.name).result)).to eq(3)
1259
- expect(repository.count(specification.stream('Dummy').result)).to eq(1)
1260
- expect(repository.count(specification.stream('not-existing-stream').result)).to eq(0)
1217
+ expect(repository.count(specification.stream("Dummy").result)).to eq(1)
1218
+ expect(repository.count(specification.stream("not-existing-stream").result)).to eq(0)
1261
1219
 
1262
1220
  repository.append_to_stream([SRecord.new(event_type: Type1.to_s)], dummy, version_any)
1263
1221
  expect(repository.count(specification.from(event_id).result)).to eq(1)
@@ -1277,118 +1235,176 @@ module RubyEventStore
1277
1235
  expect(repository.count(specification.stream(stream.name).of_type([Type3]).result)).to eq(0)
1278
1236
  end
1279
1237
 
1280
- specify 'timestamp precision' do
1281
- time = Time.utc(2020, 9, 11, 12, 26, 0, 123456)
1238
+ specify "timestamp precision" do
1239
+ time = Time.utc(2020, 9, 11, 12, 26, 0, 123_456)
1282
1240
  repository.append_to_stream([SRecord.new(timestamp: time)], stream, version_none)
1283
1241
  event = read_events_forward(repository, count: 1).first
1284
1242
 
1285
1243
  expect(event.timestamp).to eq(time)
1286
1244
  end
1287
1245
 
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)
1246
+ specify "fetching records older than specified date in stream" do
1247
+ event_1 = SRecord.new(event_id: "8a6f053e-3ce2-4c82-a55b-4d02c66ae6ea", timestamp: Time.utc(2020, 1, 1))
1248
+ event_2 = SRecord.new(event_id: "8cee1139-4f96-483a-a175-2b947283c3c7", timestamp: Time.utc(2020, 1, 2))
1249
+ event_3 = SRecord.new(event_id: "d345f86d-b903-4d78-803f-38990c078d9e", timestamp: Time.utc(2020, 1, 3))
1250
+ repository.append_to_stream([event_1, event_2, event_3], Stream.new("whatever"), version_any)
1293
1251
 
1294
- expect(repository.read(specification.stream('whatever').older_than(Time.utc(2020, 1, 2)).result).to_a).to eq([event_1])
1252
+ expect(repository.read(specification.stream("whatever").older_than(Time.utc(2020, 1, 2)).result).to_a).to eq(
1253
+ [event_1]
1254
+ )
1295
1255
  end
1296
1256
 
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)
1257
+ specify "fetching records older than or equal to specified date in stream" do
1258
+ event_1 = SRecord.new(event_id: "8a6f053e-3ce2-4c82-a55b-4d02c66ae6ea", timestamp: Time.utc(2020, 1, 1))
1259
+ event_2 = SRecord.new(event_id: "8cee1139-4f96-483a-a175-2b947283c3c7", timestamp: Time.utc(2020, 1, 2))
1260
+ event_3 = SRecord.new(event_id: "d345f86d-b903-4d78-803f-38990c078d9e", timestamp: Time.utc(2020, 1, 3))
1261
+ repository.append_to_stream([event_1, event_2, event_3], Stream.new("whatever"), version_any)
1302
1262
 
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])
1263
+ expect(
1264
+ repository.read(specification.stream("whatever").older_than_or_equal(Time.utc(2020, 1, 2)).result).to_a
1265
+ ).to eq([event_1, event_2])
1304
1266
  end
1305
1267
 
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)
1268
+ specify "fetching records newer than specified date in stream" do
1269
+ event_1 = SRecord.new(event_id: "8a6f053e-3ce2-4c82-a55b-4d02c66ae6ea", timestamp: Time.utc(2020, 1, 1))
1270
+ event_2 = SRecord.new(event_id: "8cee1139-4f96-483a-a175-2b947283c3c7", timestamp: Time.utc(2020, 1, 2))
1271
+ event_3 = SRecord.new(event_id: "d345f86d-b903-4d78-803f-38990c078d9e", timestamp: Time.utc(2020, 1, 3))
1272
+ repository.append_to_stream([event_1, event_2, event_3], Stream.new("whatever"), version_any)
1311
1273
 
1312
- expect(repository.read(specification.stream('whatever').newer_than(Time.utc(2020, 1, 2)).result).to_a).to eq([event_3])
1274
+ expect(repository.read(specification.stream("whatever").newer_than(Time.utc(2020, 1, 2)).result).to_a).to eq(
1275
+ [event_3]
1276
+ )
1313
1277
  end
1314
1278
 
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)
1279
+ specify "fetching records newer than or equal to specified date in stream" do
1280
+ event_1 = SRecord.new(event_id: "8a6f053e-3ce2-4c82-a55b-4d02c66ae6ea", timestamp: Time.utc(2020, 1, 1))
1281
+ event_2 = SRecord.new(event_id: "8cee1139-4f96-483a-a175-2b947283c3c7", timestamp: Time.utc(2020, 1, 2))
1282
+ event_3 = SRecord.new(event_id: "d345f86d-b903-4d78-803f-38990c078d9e", timestamp: Time.utc(2020, 1, 3))
1283
+ repository.append_to_stream([event_1, event_2, event_3], Stream.new("whatever"), version_any)
1320
1284
 
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])
1285
+ expect(
1286
+ repository.read(specification.stream("whatever").newer_than_or_equal(Time.utc(2020, 1, 2)).result).to_a
1287
+ ).to eq([event_2, event_3])
1322
1288
  end
1323
1289
 
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)
1290
+ specify "fetching records older than specified date" do
1291
+ event_1 = SRecord.new(event_id: "8a6f053e-3ce2-4c82-a55b-4d02c66ae6ea", timestamp: Time.utc(2020, 1, 1))
1292
+ event_2 = SRecord.new(event_id: "8cee1139-4f96-483a-a175-2b947283c3c7", timestamp: Time.utc(2020, 1, 2))
1293
+ event_3 = SRecord.new(event_id: "d345f86d-b903-4d78-803f-38990c078d9e", timestamp: Time.utc(2020, 1, 3))
1294
+ repository.append_to_stream([event_1, event_2, event_3], Stream.new("whatever"), version_any)
1329
1295
 
1330
1296
  expect(repository.read(specification.older_than(Time.utc(2020, 1, 2)).result).to_a).to eq([event_1])
1331
1297
  end
1332
1298
 
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)
1299
+ specify "fetching records older than or equal to specified date" do
1300
+ event_1 = SRecord.new(event_id: "8a6f053e-3ce2-4c82-a55b-4d02c66ae6ea", timestamp: Time.utc(2020, 1, 1))
1301
+ event_2 = SRecord.new(event_id: "8cee1139-4f96-483a-a175-2b947283c3c7", timestamp: Time.utc(2020, 1, 2))
1302
+ event_3 = SRecord.new(event_id: "d345f86d-b903-4d78-803f-38990c078d9e", timestamp: Time.utc(2020, 1, 3))
1303
+ repository.append_to_stream([event_1, event_2, event_3], Stream.new("whatever"), version_any)
1338
1304
 
1339
- expect(repository.read(specification.older_than_or_equal(Time.utc(2020, 1, 2)).result).to_a).to eq([event_1, event_2])
1305
+ expect(repository.read(specification.older_than_or_equal(Time.utc(2020, 1, 2)).result).to_a).to eq(
1306
+ [event_1, event_2]
1307
+ )
1340
1308
  end
1341
1309
 
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)
1310
+ specify "fetching records newer than specified date" do
1311
+ event_1 = SRecord.new(event_id: "8a6f053e-3ce2-4c82-a55b-4d02c66ae6ea", timestamp: Time.utc(2020, 1, 1))
1312
+ event_2 = SRecord.new(event_id: "8cee1139-4f96-483a-a175-2b947283c3c7", timestamp: Time.utc(2020, 1, 2))
1313
+ event_3 = SRecord.new(event_id: "d345f86d-b903-4d78-803f-38990c078d9e", timestamp: Time.utc(2020, 1, 3))
1314
+ repository.append_to_stream([event_1, event_2, event_3], Stream.new("whatever"), version_any)
1347
1315
 
1348
1316
  expect(repository.read(specification.newer_than(Time.utc(2020, 1, 2)).result).to_a).to eq([event_3])
1349
1317
  end
1350
1318
 
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)
1319
+ specify "fetching records newer than or equal to specified date" do
1320
+ event_1 = SRecord.new(event_id: "8a6f053e-3ce2-4c82-a55b-4d02c66ae6ea", timestamp: Time.utc(2020, 1, 1))
1321
+ event_2 = SRecord.new(event_id: "8cee1139-4f96-483a-a175-2b947283c3c7", timestamp: Time.utc(2020, 1, 2))
1322
+ event_3 = SRecord.new(event_id: "d345f86d-b903-4d78-803f-38990c078d9e", timestamp: Time.utc(2020, 1, 3))
1323
+ repository.append_to_stream([event_1, event_2, event_3], Stream.new("whatever"), version_any)
1356
1324
 
1357
- expect(repository.read(specification.newer_than_or_equal(Time.utc(2020, 1, 2)).result).to_a).to eq([event_2, event_3])
1325
+ expect(repository.read(specification.newer_than_or_equal(Time.utc(2020, 1, 2)).result).to_a).to eq(
1326
+ [event_2, event_3]
1327
+ )
1358
1328
  end
1359
1329
 
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)
1330
+ specify "fetching records from disjoint periods" do
1331
+ event_1 = SRecord.new(event_id: "8a6f053e-3ce2-4c82-a55b-4d02c66ae6ea", timestamp: Time.utc(2020, 1, 1))
1332
+ event_2 = SRecord.new(event_id: "8cee1139-4f96-483a-a175-2b947283c3c7", timestamp: Time.utc(2020, 1, 2))
1333
+ event_3 = SRecord.new(event_id: "d345f86d-b903-4d78-803f-38990c078d9e", timestamp: Time.utc(2020, 1, 3))
1334
+ repository.append_to_stream([event_1, event_2, event_3], Stream.new("whatever"), version_any)
1365
1335
 
1366
- expect(repository.read(specification.older_than(Time.utc(2020, 1, 2)).newer_than(Time.utc(2020, 1, 2)).result).to_a).to eq([])
1336
+ expect(
1337
+ repository.read(specification.older_than(Time.utc(2020, 1, 2)).newer_than(Time.utc(2020, 1, 2)).result).to_a
1338
+ ).to eq([])
1367
1339
  end
1368
1340
 
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)
1341
+ specify "fetching records within time range" do
1342
+ event_1 = SRecord.new(event_id: "8a6f053e-3ce2-4c82-a55b-4d02c66ae6ea", timestamp: Time.utc(2020, 1, 1))
1343
+ event_2 = SRecord.new(event_id: "8cee1139-4f96-483a-a175-2b947283c3c7", timestamp: Time.utc(2020, 1, 2))
1344
+ event_3 = SRecord.new(event_id: "d345f86d-b903-4d78-803f-38990c078d9e", timestamp: Time.utc(2020, 1, 3))
1345
+ repository.append_to_stream([event_1, event_2, event_3], Stream.new("whatever"), version_any)
1374
1346
 
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])
1347
+ expect(repository.read(specification.between(Time.utc(2020, 1, 1)...Time.utc(2020, 1, 3)).result).to_a).to eq(
1348
+ [event_1, event_2]
1349
+ )
1376
1350
  end
1377
1351
 
1378
1352
  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)),
1353
+ repository.append_to_stream(
1354
+ [
1355
+ SRecord.new(
1356
+ event_id: e1 = SecureRandom.uuid,
1357
+ timestamp: Time.new(2020, 1, 1),
1358
+ valid_at: Time.new(2020, 1, 9)
1359
+ ),
1360
+ SRecord.new(
1361
+ event_id: e2 = SecureRandom.uuid,
1362
+ timestamp: Time.new(2020, 1, 3),
1363
+ valid_at: Time.new(2020, 1, 6)
1364
+ ),
1365
+ SRecord.new(event_id: e3 = SecureRandom.uuid, timestamp: Time.new(2020, 1, 2), valid_at: Time.new(2020, 1, 3))
1383
1366
  ],
1384
1367
  Stream.new("Dummy"),
1385
1368
  ExpectedVersion.any
1386
1369
  )
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]
1370
+ expect(repository.read(specification.result)).to eq_ids([e1, e2, e3])
1371
+ expect(repository.read(specification.as_at.result)).to eq_ids([e1, e3, e2])
1372
+ expect(repository.read(specification.as_at.backward.result)).to eq_ids([e2, e3, e1])
1373
+ expect(repository.read(specification.as_of.result)).to eq_ids([e3, e2, e1])
1374
+ expect(repository.read(specification.as_of.backward.result)).to eq_ids([e1, e2, e3])
1375
+ end
1376
+
1377
+ specify "time order is respected with batches" do
1378
+ repository.append_to_stream(
1379
+ [
1380
+ SRecord.new(
1381
+ event_id: e1 = SecureRandom.uuid,
1382
+ timestamp: Time.new(2020, 1, 1),
1383
+ valid_at: Time.new(2020, 1, 9)
1384
+ ),
1385
+ SRecord.new(
1386
+ event_id: e2 = SecureRandom.uuid,
1387
+ timestamp: Time.new(2020, 1, 3),
1388
+ valid_at: Time.new(2020, 1, 6)
1389
+ ),
1390
+ SRecord.new(event_id: e3 = SecureRandom.uuid, timestamp: Time.new(2020, 1, 2), valid_at: Time.new(2020, 1, 3))
1391
+ ],
1392
+ Stream.new("Dummy"),
1393
+ ExpectedVersion.any
1394
+ )
1395
+ expect(repository.read(specification.in_batches.result).to_a.flatten).to eq_ids([e1, e2, e3])
1396
+ expect(repository.read(specification.in_batches.as_at.result).to_a.flatten).to eq_ids([e1, e3, e2])
1397
+ expect(repository.read(specification.in_batches.as_at.backward.result).to_a.flatten).to eq_ids([e2, e3, e1])
1398
+ expect(repository.read(specification.in_batches.as_of.result).to_a.flatten).to eq_ids([e3, e2, e1])
1399
+ expect(repository.read(specification.in_batches.as_of.backward.result).to_a.flatten).to eq_ids([e1, e2, e3])
1400
+ end
1401
+ end
1402
+
1403
+ ::RSpec::Matchers.define :eq_ids do |expected_ids|
1404
+ match do |enum|
1405
+ @actual = enum.map(&:event_id)
1406
+ expected_ids == @actual
1392
1407
  end
1408
+ diffable
1393
1409
  end
1394
1410
  end