ruby_event_store 2.2.0 → 2.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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 +75 -46
  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 +23 -13
  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 +745 -741
  36. data/lib/ruby_event_store/spec/mapper_lint.rb +2 -2
  37. data/lib/ruby_event_store/spec/subscriptions_lint.rb +58 -57
  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 +14 -15
  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,40 +885,36 @@ 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
@@ -975,29 +922,16 @@ module RubyEventStore
975
922
  expect(repository.read(specification.in_batches.as_at.result)).to be_kind_of(Enumerator)
976
923
  expect(repository.read(specification.in_batches.as_of.result)).to be_kind_of(Enumerator)
977
924
  events = Array.new(10) { SRecord.new }
978
- repository.append_to_stream(
979
- events,
980
- Stream.new("Dummy"),
981
- ExpectedVersion.none
982
- )
925
+ repository.append_to_stream(events, Stream.new("Dummy"), ExpectedVersion.none)
983
926
  expect(repository.read(specification.in_batches.result)).to be_kind_of(Enumerator)
984
927
  expect(repository.read(specification.in_batches.as_at.result)).to be_kind_of(Enumerator)
985
928
  expect(repository.read(specification.in_batches.as_of.result)).to be_kind_of(Enumerator)
986
-
987
929
  end
988
930
 
989
931
  specify do
990
932
  events = Array.new(400) { SRecord.new }
991
- repository.append_to_stream(
992
- events[200...400],
993
- Stream.new("Foo"),
994
- ExpectedVersion.none
995
- )
996
- repository.append_to_stream(
997
- events[0...200],
998
- Stream.new("Dummy"),
999
- ExpectedVersion.none
1000
- )
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)
1001
935
 
1002
936
  batches = repository.read(specification.stream("Dummy").in_batches.result).to_a
1003
937
  expect(batches.size).to eq(2)
@@ -1007,11 +941,7 @@ module RubyEventStore
1007
941
 
1008
942
  specify do
1009
943
  events = Array.new(200) { SRecord.new }
1010
- repository.append_to_stream(
1011
- events,
1012
- Stream.new(GLOBAL_STREAM),
1013
- ExpectedVersion.any
1014
- )
944
+ repository.append_to_stream(events, Stream.new(GLOBAL_STREAM), ExpectedVersion.any)
1015
945
 
1016
946
  batches = repository.read(specification.in_batches.result).to_a
1017
947
  expect(batches.size).to eq(2)
@@ -1021,22 +951,14 @@ module RubyEventStore
1021
951
 
1022
952
  specify do
1023
953
  events = Array.new(200) { SRecord.new }
1024
- repository.append_to_stream(
1025
- events,
1026
- Stream.new(GLOBAL_STREAM),
1027
- ExpectedVersion.any
1028
- )
954
+ repository.append_to_stream(events, Stream.new(GLOBAL_STREAM), ExpectedVersion.any)
1029
955
 
1030
956
  expect(repository.read(specification.in_batches(200).result).to_a.size).to eq(1)
1031
957
  end
1032
958
 
1033
959
  specify do
1034
960
  events = Array.new(200) { SRecord.new }
1035
- repository.append_to_stream(
1036
- events,
1037
- Stream.new(GLOBAL_STREAM),
1038
- ExpectedVersion.any
1039
- )
961
+ repository.append_to_stream(events, Stream.new(GLOBAL_STREAM), ExpectedVersion.any)
1040
962
 
1041
963
  batches = repository.read(specification.limit(199).in_batches.result).to_a
1042
964
  expect(batches.size).to eq(2)
@@ -1048,11 +970,7 @@ module RubyEventStore
1048
970
 
1049
971
  specify do
1050
972
  events = Array.new(200) { SRecord.new }
1051
- repository.append_to_stream(
1052
- events,
1053
- Stream.new(GLOBAL_STREAM),
1054
- ExpectedVersion.any
1055
- )
973
+ repository.append_to_stream(events, Stream.new(GLOBAL_STREAM), ExpectedVersion.any)
1056
974
 
1057
975
  batches = repository.read(specification.limit(99).in_batches.result).to_a
1058
976
  expect(batches.size).to eq(1)
@@ -1062,11 +980,7 @@ module RubyEventStore
1062
980
 
1063
981
  specify do
1064
982
  events = Array.new(200) { SRecord.new }
1065
- repository.append_to_stream(
1066
- events,
1067
- Stream.new(GLOBAL_STREAM),
1068
- ExpectedVersion.any
1069
- )
983
+ repository.append_to_stream(events, Stream.new(GLOBAL_STREAM), ExpectedVersion.any)
1070
984
 
1071
985
  batches = repository.read(specification.backward.limit(99).in_batches.result).to_a
1072
986
  expect(batches.size).to eq(1)
@@ -1076,11 +990,7 @@ module RubyEventStore
1076
990
 
1077
991
  specify do
1078
992
  events = Array.new(200) { SRecord.new }
1079
- repository.append_to_stream(
1080
- events,
1081
- Stream.new(GLOBAL_STREAM),
1082
- ExpectedVersion.any
1083
- )
993
+ repository.append_to_stream(events, Stream.new(GLOBAL_STREAM), ExpectedVersion.any)
1084
994
 
1085
995
  batches = repository.read(specification.from(events[100].event_id).limit(99).in_batches.result).to_a
1086
996
  expect(batches.size).to eq(1)
@@ -1093,11 +1003,7 @@ module RubyEventStore
1093
1003
  expect(repository.read(specification.read_last.result)).to be_nil
1094
1004
 
1095
1005
  events = Array.new(5) { SRecord.new }
1096
- repository.append_to_stream(
1097
- events,
1098
- Stream.new(GLOBAL_STREAM),
1099
- ExpectedVersion.any
1100
- )
1006
+ repository.append_to_stream(events, Stream.new(GLOBAL_STREAM), ExpectedVersion.any)
1101
1007
 
1102
1008
  expect(repository.read(specification.stream("Any").read_first.result)).to be_nil
1103
1009
  expect(repository.read(specification.stream("Any").read_last.result)).to be_nil
@@ -1137,33 +1043,70 @@ module RubyEventStore
1137
1043
  specify "changes events" do
1138
1044
  skip unless helper.supports_upsert?
1139
1045
  events = Array.new(5) { SRecord.new }
1140
- repository.append_to_stream(
1141
- events[0..2],
1142
- Stream.new("whatever"),
1143
- ExpectedVersion.any
1144
- )
1145
- repository.append_to_stream(
1146
- events[3..4],
1147
- Stream.new("elo"),
1148
- 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
+ ]
1149
1099
  )
1150
- repository.update_messages([
1151
- 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),
1152
- 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),
1153
- 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),
1154
- 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),
1155
- e = SRecord.new(event_id: events[4].event_id.dup, data: { "test" => 4 }, metadata: { "test" => 42 }, event_type: "event_type4", timestamp: events[4].timestamp),
1156
- ])
1157
-
1158
- expect(repository.read(specification.result).to_a).to eq([a,b,c,d,e])
1159
- expect(repository.read(specification.stream("whatever").result).to_a).to eq([a,b,c])
1160
- 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])
1161
1104
  end
1162
1105
 
1163
1106
  specify "cannot change unexisting event" do
1164
1107
  skip unless helper.supports_upsert?
1165
1108
  e = SRecord.new
1166
- expect{ repository.update_messages([e]) }.to raise_error do |err|
1109
+ expect { repository.update_messages([e]) }.to raise_error do |err|
1167
1110
  expect(err).to be_a(EventNotFound)
1168
1111
  expect(err.event_id).to eq(e.event_id)
1169
1112
  expect(err.message).to eq("Event not found: #{e.event_id}")
@@ -1180,51 +1123,63 @@ module RubyEventStore
1180
1123
  end
1181
1124
 
1182
1125
  specify do
1183
- event_1 = SRecord.new(event_id: '8a6f053e-3ce2-4c82-a55b-4d02c66ae6ea')
1184
- event_2 = SRecord.new(event_id: '8cee1139-4f96-483a-a175-2b947283c3c7')
1185
- event_3 = SRecord.new(event_id: 'd345f86d-b903-4d78-803f-38990c078d9e')
1186
- stream_a = Stream.new('Stream A')
1187
- stream_b = Stream.new('Stream B')
1188
- 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")
1189
1132
  repository.append_to_stream([event_1, event_2], stream_a, version_any)
1190
1133
  repository.append_to_stream([event_3], stream_b, version_any)
1191
1134
  repository.link_to_stream([event_1.event_id], stream_c, version_none)
1192
1135
 
1193
- expect(repository.streams_of('8a6f053e-3ce2-4c82-a55b-4d02c66ae6ea')).to eq [stream_a, stream_c]
1194
- expect(repository.streams_of('8cee1139-4f96-483a-a175-2b947283c3c7')).to eq [stream_a]
1195
- expect(repository.streams_of('d345f86d-b903-4d78-803f-38990c078d9e')).to eq [stream_b]
1196
- 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 []
1197
1140
  end
1198
1141
 
1199
1142
  specify do
1200
- e1 = SRecord.new(event_id: '8a6f053e-3ce2-4c82-a55b-4d02c66ae6ea')
1201
- e2 = SRecord.new(event_id: '8cee1139-4f96-483a-a175-2b947283c3c7')
1202
- e3 = SRecord.new(event_id: 'd345f86d-b903-4d78-803f-38990c078d9e')
1203
- 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")
1204
1147
  repository.append_to_stream([e1, e2, e3], stream, version_any)
1205
1148
 
1206
- expect(repository.read(specification.with_id([
1207
- '8a6f053e-3ce2-4c82-a55b-4d02c66ae6ea'
1208
- ]).read_first.result)).to eq(e1)
1209
- expect(repository.read(specification.with_id([
1210
- 'd345f86d-b903-4d78-803f-38990c078d9e'
1211
- ]).read_first.result)).to eq(e3)
1212
- expect(repository.read(specification.with_id([
1213
- 'c31b327c-0da1-4178-a3cd-d2f6bb5d0688'
1214
- ]).read_first.result)).to eq(nil)
1215
- expect(repository.read(specification.with_id([
1216
- '8a6f053e-3ce2-4c82-a55b-4d02c66ae6ea',
1217
- 'd345f86d-b903-4d78-803f-38990c078d9e'
1218
- ]).in_batches.result).to_a[0]).to eq([e1,e3])
1219
- expect(repository.read(specification.stream('Stream A').with_id([
1220
- '8cee1139-4f96-483a-a175-2b947283c3c7'
1221
- ]).read_first.result)).to eq(e2)
1222
- expect(repository.read(specification.stream('Stream B').with_id([
1223
- '8cee1139-4f96-483a-a175-2b947283c3c7'
1224
- ]).read_first.result)).to eq(nil)
1225
- expect(repository.read(specification.stream('Stream B').with_id([
1226
- 'c31b327c-0da1-4178-a3cd-d2f6bb5d0688'
1227
- ]).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)
1228
1183
  expect(repository.read(specification.with_id([]).result).to_a).to eq([])
1229
1184
  end
1230
1185
 
@@ -1232,23 +1187,21 @@ module RubyEventStore
1232
1187
  e1 = SRecord.new(event_type: Type1.to_s)
1233
1188
  e2 = SRecord.new(event_type: Type2.to_s)
1234
1189
  e3 = SRecord.new(event_type: Type1.to_s)
1235
- stream = Stream.new('Stream A')
1190
+ stream = Stream.new("Stream A")
1236
1191
  repository.append_to_stream([e1, e2, e3], stream, version_any)
1237
1192
 
1238
- 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])
1239
1194
  expect(repository.read(specification.of_type([Type2]).result).to_a).to eq([e2])
1240
1195
  expect(repository.read(specification.of_type([Type3]).result).to_a).to eq([])
1241
- 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])
1242
1197
  end
1243
1198
 
1244
1199
  specify do
1245
- stream = Stream.new('Stream A')
1246
- dummy = Stream.new('Dummy')
1200
+ stream = Stream.new("Stream A")
1201
+ dummy = Stream.new("Dummy")
1247
1202
 
1248
1203
  expect(repository.count(specification.result)).to eq(0)
1249
- (1..3).each do
1250
- repository.append_to_stream([SRecord.new(event_type: Type1.to_s)], stream, version_any)
1251
- end
1204
+ (1..3).each { repository.append_to_stream([SRecord.new(event_type: Type1.to_s)], stream, version_any) }
1252
1205
  expect(repository.count(specification.result)).to eq(3)
1253
1206
  event_id = SecureRandom.uuid
1254
1207
  repository.append_to_stream([SRecord.new(event_type: Type1.to_s, event_id: event_id)], dummy, version_any)
@@ -1261,8 +1214,8 @@ module RubyEventStore
1261
1214
  expect(repository.count(specification.with_id([not_existing_uuid]).result)).to eq(0)
1262
1215
 
1263
1216
  expect(repository.count(specification.stream(stream.name).result)).to eq(3)
1264
- expect(repository.count(specification.stream('Dummy').result)).to eq(1)
1265
- 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)
1266
1219
 
1267
1220
  repository.append_to_stream([SRecord.new(event_type: Type1.to_s)], dummy, version_any)
1268
1221
  expect(repository.count(specification.from(event_id).result)).to eq(1)
@@ -1282,134 +1235,185 @@ module RubyEventStore
1282
1235
  expect(repository.count(specification.stream(stream.name).of_type([Type3]).result)).to eq(0)
1283
1236
  end
1284
1237
 
1285
- specify 'timestamp precision' do
1286
- 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)
1287
1240
  repository.append_to_stream([SRecord.new(timestamp: time)], stream, version_none)
1288
1241
  event = read_events_forward(repository, count: 1).first
1289
1242
 
1290
1243
  expect(event.timestamp).to eq(time)
1291
1244
  end
1292
1245
 
1293
- specify 'fetching records older than specified date in stream' do
1294
- event_1 = SRecord.new(event_id: '8a6f053e-3ce2-4c82-a55b-4d02c66ae6ea', timestamp: Time.utc(2020, 1, 1))
1295
- event_2 = SRecord.new(event_id: '8cee1139-4f96-483a-a175-2b947283c3c7', timestamp: Time.utc(2020, 1, 2))
1296
- event_3 = SRecord.new(event_id: 'd345f86d-b903-4d78-803f-38990c078d9e', timestamp: Time.utc(2020, 1, 3))
1297
- 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)
1298
1251
 
1299
- 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
+ )
1300
1255
  end
1301
1256
 
1302
- specify 'fetching records older than or equal to specified date in stream' do
1303
- event_1 = SRecord.new(event_id: '8a6f053e-3ce2-4c82-a55b-4d02c66ae6ea', timestamp: Time.utc(2020, 1, 1))
1304
- event_2 = SRecord.new(event_id: '8cee1139-4f96-483a-a175-2b947283c3c7', timestamp: Time.utc(2020, 1, 2))
1305
- event_3 = SRecord.new(event_id: 'd345f86d-b903-4d78-803f-38990c078d9e', timestamp: Time.utc(2020, 1, 3))
1306
- 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)
1307
1262
 
1308
- 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])
1309
1266
  end
1310
1267
 
1311
- specify 'fetching records newer than specified date in stream' do
1312
- event_1 = SRecord.new(event_id: '8a6f053e-3ce2-4c82-a55b-4d02c66ae6ea', timestamp: Time.utc(2020, 1, 1))
1313
- event_2 = SRecord.new(event_id: '8cee1139-4f96-483a-a175-2b947283c3c7', timestamp: Time.utc(2020, 1, 2))
1314
- event_3 = SRecord.new(event_id: 'd345f86d-b903-4d78-803f-38990c078d9e', timestamp: Time.utc(2020, 1, 3))
1315
- 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)
1316
1273
 
1317
- 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
+ )
1318
1277
  end
1319
1278
 
1320
- specify 'fetching records newer than or equal to specified date in stream' do
1321
- event_1 = SRecord.new(event_id: '8a6f053e-3ce2-4c82-a55b-4d02c66ae6ea', timestamp: Time.utc(2020, 1, 1))
1322
- event_2 = SRecord.new(event_id: '8cee1139-4f96-483a-a175-2b947283c3c7', timestamp: Time.utc(2020, 1, 2))
1323
- event_3 = SRecord.new(event_id: 'd345f86d-b903-4d78-803f-38990c078d9e', timestamp: Time.utc(2020, 1, 3))
1324
- 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)
1325
1284
 
1326
- 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])
1327
1288
  end
1328
1289
 
1329
- specify 'fetching records older than specified date' do
1330
- event_1 = SRecord.new(event_id: '8a6f053e-3ce2-4c82-a55b-4d02c66ae6ea', timestamp: Time.utc(2020, 1, 1))
1331
- event_2 = SRecord.new(event_id: '8cee1139-4f96-483a-a175-2b947283c3c7', timestamp: Time.utc(2020, 1, 2))
1332
- event_3 = SRecord.new(event_id: 'd345f86d-b903-4d78-803f-38990c078d9e', timestamp: Time.utc(2020, 1, 3))
1333
- 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)
1334
1295
 
1335
1296
  expect(repository.read(specification.older_than(Time.utc(2020, 1, 2)).result).to_a).to eq([event_1])
1336
1297
  end
1337
1298
 
1338
- specify 'fetching records older than or equal to specified date' do
1339
- event_1 = SRecord.new(event_id: '8a6f053e-3ce2-4c82-a55b-4d02c66ae6ea', timestamp: Time.utc(2020, 1, 1))
1340
- event_2 = SRecord.new(event_id: '8cee1139-4f96-483a-a175-2b947283c3c7', timestamp: Time.utc(2020, 1, 2))
1341
- event_3 = SRecord.new(event_id: 'd345f86d-b903-4d78-803f-38990c078d9e', timestamp: Time.utc(2020, 1, 3))
1342
- 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)
1343
1304
 
1344
- 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
+ )
1345
1308
  end
1346
1309
 
1347
- specify 'fetching records newer than specified date' do
1348
- event_1 = SRecord.new(event_id: '8a6f053e-3ce2-4c82-a55b-4d02c66ae6ea', timestamp: Time.utc(2020, 1, 1))
1349
- event_2 = SRecord.new(event_id: '8cee1139-4f96-483a-a175-2b947283c3c7', timestamp: Time.utc(2020, 1, 2))
1350
- event_3 = SRecord.new(event_id: 'd345f86d-b903-4d78-803f-38990c078d9e', timestamp: Time.utc(2020, 1, 3))
1351
- 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)
1352
1315
 
1353
1316
  expect(repository.read(specification.newer_than(Time.utc(2020, 1, 2)).result).to_a).to eq([event_3])
1354
1317
  end
1355
1318
 
1356
- specify 'fetching records newer than or equal to specified date' do
1357
- event_1 = SRecord.new(event_id: '8a6f053e-3ce2-4c82-a55b-4d02c66ae6ea', timestamp: Time.utc(2020, 1, 1))
1358
- event_2 = SRecord.new(event_id: '8cee1139-4f96-483a-a175-2b947283c3c7', timestamp: Time.utc(2020, 1, 2))
1359
- event_3 = SRecord.new(event_id: 'd345f86d-b903-4d78-803f-38990c078d9e', timestamp: Time.utc(2020, 1, 3))
1360
- 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)
1361
1324
 
1362
- 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
+ )
1363
1328
  end
1364
1329
 
1365
- specify 'fetching records from disjoint periods' do
1366
- event_1 = SRecord.new(event_id: '8a6f053e-3ce2-4c82-a55b-4d02c66ae6ea', timestamp: Time.utc(2020, 1, 1))
1367
- event_2 = SRecord.new(event_id: '8cee1139-4f96-483a-a175-2b947283c3c7', timestamp: Time.utc(2020, 1, 2))
1368
- event_3 = SRecord.new(event_id: 'd345f86d-b903-4d78-803f-38990c078d9e', timestamp: Time.utc(2020, 1, 3))
1369
- 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)
1370
1335
 
1371
- 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([])
1372
1339
  end
1373
1340
 
1374
- specify 'fetching records within time range' do
1375
- event_1 = SRecord.new(event_id: '8a6f053e-3ce2-4c82-a55b-4d02c66ae6ea', timestamp: Time.utc(2020, 1, 1))
1376
- event_2 = SRecord.new(event_id: '8cee1139-4f96-483a-a175-2b947283c3c7', timestamp: Time.utc(2020, 1, 2))
1377
- event_3 = SRecord.new(event_id: 'd345f86d-b903-4d78-803f-38990c078d9e', timestamp: Time.utc(2020, 1, 3))
1378
- 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)
1379
1346
 
1380
- 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
+ )
1381
1350
  end
1382
1351
 
1383
1352
  specify "time order is respected" do
1384
- repository.append_to_stream([
1385
- SRecord.new(event_id: e1 = SecureRandom.uuid, timestamp: Time.new(2020,1,1), valid_at: Time.new(2020,1,9)),
1386
- SRecord.new(event_id: e2 = SecureRandom.uuid, timestamp: Time.new(2020,1,3), valid_at: Time.new(2020,1,6)),
1387
- 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))
1388
1366
  ],
1389
1367
  Stream.new("Dummy"),
1390
1368
  ExpectedVersion.any
1391
1369
  )
1392
- expect(repository.read(specification.result).map(&:event_id)).to eq [e1, e2, e3]
1393
- expect(repository.read(specification.as_at.result).map(&:event_id)).to eq [e1, e3, e2]
1394
- expect(repository.read(specification.as_at.backward.result).map(&:event_id)).to eq [e2, e3, e1]
1395
- expect(repository.read(specification.as_of.result).map(&:event_id)).to eq [e3, e2, e1]
1396
- 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])
1397
1375
  end
1398
1376
 
1399
1377
  specify "time order is respected with batches" do
1400
- repository.append_to_stream([
1401
- SRecord.new(event_id: e1 = SecureRandom.uuid, timestamp: Time.new(2020,1,1), valid_at: Time.new(2020,1,9)),
1402
- SRecord.new(event_id: e2 = SecureRandom.uuid, timestamp: Time.new(2020,1,3), valid_at: Time.new(2020,1,6)),
1403
- SRecord.new(event_id: e3 = SecureRandom.uuid, timestamp: Time.new(2020,1,2), valid_at: Time.new(2020,1,3)),
1404
- ],
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
+ ],
1405
1392
  Stream.new("Dummy"),
1406
1393
  ExpectedVersion.any
1407
1394
  )
1408
- expect(repository.read(specification.in_batches.result).to_a.flatten.map(&:event_id)).to eq [e1, e2, e3]
1409
- expect(repository.read(specification.in_batches.as_at.result).to_a.flatten.map(&:event_id)).to eq [e1, e3, e2]
1410
- expect(repository.read(specification.in_batches.as_at.backward.result).to_a.flatten.map(&:event_id)).to eq [e2, e3, e1]
1411
- expect(repository.read(specification.in_batches.as_of.result).to_a.flatten.map(&:event_id)).to eq [e3, e2, e1]
1412
- expect(repository.read(specification.in_batches.as_of.backward.result).to_a.flatten.map(&:event_id)).to eq [e1, e2, e3]
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
+
1402
+ specify "appending empty list of commits should be a no-op" do
1403
+ repository.append_to_stream(
1404
+ [],
1405
+ RubyEventStore::Stream.new(RubyEventStore::GLOBAL_STREAM),
1406
+ RubyEventStore::ExpectedVersion.any
1407
+ )
1408
+ expect(repository.read(specification.result).count).to eq(0)
1409
+ end
1410
+ end
1411
+
1412
+ ::RSpec::Matchers.define :eq_ids do |expected_ids|
1413
+ match do |enum|
1414
+ @actual = enum.map(&:event_id)
1415
+ expected_ids == @actual
1413
1416
  end
1417
+ diffable
1414
1418
  end
1415
1419
  end