ruby_event_store 2.9.0 → 2.9.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fdf55a1535ea6531b1953ba7413455903257db368dba2bc369783cd90325a31f
4
- data.tar.gz: e7b071bbe5d4a389e47751af5d272a8dd9499af3c30c111b1dcba6ef8223e125
3
+ metadata.gz: 034aa1fb571c22b4e87df0161a00192535fdf8d6637df0e3db2fa9dc14c928d6
4
+ data.tar.gz: bbb8846d15f41eadf5e0c4cb3d63697ed80c536cfbd2c921453038ec40d0b3f9
5
5
  SHA512:
6
- metadata.gz: 5c95bb40dfeb3a8261970077ce5c6ac9e840d3eefeb56f0994b5aa91eb7c764e46f23d99281e33dc4f221a4cc74a504c83b6693230dcac16803e0e1678d86e7d
7
- data.tar.gz: a617e996ad6b0f72eb7d6cd7bfae02b2ad9151b001de72e71f2e03c28eed205be9abb35d633242487765d7b20e00bb37dc077475376ad89b8c0cf55662529491
6
+ metadata.gz: 5deb5169c06c20dfb077a0972a262fbf43fb1bf1e27257dd756a22d6f42eb34d1b486f34cebf7d55579bddb271b729ccd5e377d9f30ca5ed0abe814bba046ea5
7
+ data.tar.gz: 5188078974d0eb3d2311d00de74e69e5756e5d27b9afd7d1dc0cbbdc7b164fb26e6c27f52025215e2cd4978dc11e9eaa41f92f70502bd5516439a2205d8166b9
@@ -5,7 +5,7 @@ require "concurrent"
5
5
  module RubyEventStore
6
6
  class Client
7
7
  def initialize(
8
- repository:,
8
+ repository: InMemoryRepository.new,
9
9
  mapper: Mappers::Default.new,
10
10
  subscriptions: Subscriptions.new,
11
11
  dispatcher: Dispatcher.new,
@@ -153,19 +153,27 @@ module RubyEventStore
153
153
  serialized_records = serialized_records.drop(index_of(serialized_records, spec.start) + 1) if spec.start
154
154
  serialized_records = serialized_records.take(index_of(serialized_records, spec.stop)) if spec.stop
155
155
  serialized_records = serialized_records.take(spec.limit) if spec.limit?
156
- serialized_records = serialized_records.select { |sr| Time.iso8601(sr.timestamp) < spec.older_than } if spec
156
+ serialized_records = serialized_records.select { |sr| Time.iso8601(time_comparison_field(spec, sr)) < spec.older_than } if spec
157
157
  .older_than
158
158
  serialized_records =
159
- serialized_records.select { |sr| Time.iso8601(sr.timestamp) <= spec.older_than_or_equal } if spec
159
+ serialized_records.select { |sr| Time.iso8601(time_comparison_field(spec, sr)) <= spec.older_than_or_equal } if spec
160
160
  .older_than_or_equal
161
- serialized_records = serialized_records.select { |sr| Time.iso8601(sr.timestamp) > spec.newer_than } if spec
161
+ serialized_records = serialized_records.select { |sr| Time.iso8601(time_comparison_field(spec, sr)) > spec.newer_than } if spec
162
162
  .newer_than
163
163
  serialized_records =
164
- serialized_records.select { |sr| Time.iso8601(sr.timestamp) >= spec.newer_than_or_equal } if spec
164
+ serialized_records.select { |sr| Time.iso8601(time_comparison_field(spec, sr)) >= spec.newer_than_or_equal } if spec
165
165
  .newer_than_or_equal
166
166
  serialized_records
167
167
  end
168
168
 
169
+ def time_comparison_field(spec, sr)
170
+ if spec.time_sort_by_as_of?
171
+ sr.valid_at
172
+ else
173
+ sr.timestamp
174
+ end
175
+ end
176
+
169
177
  def read_event(event_id)
170
178
  storage.fetch(event_id) { raise EventNotFound.new(event_id) }
171
179
  end
@@ -6,7 +6,8 @@ module RubyEventStore
6
6
  def initialize(key_repository, serializer: Serializers::YAML, forgotten_data: ForgottenData.new)
7
7
  super(
8
8
  Pipeline.new(
9
- Transformation::Encryption.new(key_repository, serializer: serializer, forgotten_data: forgotten_data)
9
+ Transformation::Encryption.new(key_repository, serializer: serializer, forgotten_data: forgotten_data),
10
+ Transformation::SymbolizeMetadataKeys.new
10
11
  )
11
12
  )
12
13
  end
@@ -8,9 +8,9 @@ module RubyEventStore
8
8
  @instrumentation = instrumentation
9
9
  end
10
10
 
11
- def event_to_record(domain_event)
12
- instrumentation.instrument("serialize.mapper.rails_event_store", domain_event: domain_event) do
13
- mapper.event_to_record(domain_event)
11
+ def event_to_record(event)
12
+ instrumentation.instrument("serialize.mapper.rails_event_store", domain_event: event) do
13
+ mapper.event_to_record(event)
14
14
  end
15
15
  end
16
16
 
@@ -7,8 +7,8 @@ module RubyEventStore
7
7
  @transformations = [to_domain_event, transformations].flatten.freeze
8
8
  end
9
9
 
10
- def dump(domain_event)
11
- transformations.reduce(domain_event) { |item, transform| transform.dump(item) }
10
+ def dump(event)
11
+ transformations.reduce(event) { |item, transform| transform.dump(item) }
12
12
  end
13
13
 
14
14
  def load(record)
@@ -7,8 +7,8 @@ module RubyEventStore
7
7
  @pipeline = pipeline
8
8
  end
9
9
 
10
- def event_to_record(domain_event)
11
- pipeline.dump(domain_event)
10
+ def event_to_record(event)
11
+ pipeline.dump(event)
12
12
  end
13
13
 
14
14
  def record_to_event(record)
@@ -4,15 +4,15 @@ module RubyEventStore
4
4
  module Mappers
5
5
  module Transformation
6
6
  class DomainEvent
7
- def dump(domain_event)
8
- metadata = domain_event.metadata.dup.to_h
7
+ def dump(event)
8
+ metadata = event.metadata.dup.to_h
9
9
  timestamp = metadata.delete(:timestamp)
10
10
  valid_at = metadata.delete(:valid_at)
11
11
  Record.new(
12
- event_id: domain_event.event_id,
12
+ event_id: event.event_id,
13
13
  metadata: metadata,
14
- data: domain_event.data,
15
- event_type: domain_event.event_type,
14
+ data: event.data,
15
+ event_type: event.event_type,
16
16
  timestamp: timestamp,
17
17
  valid_at: valid_at
18
18
  )
@@ -33,7 +33,7 @@ end
33
33
  module RubyEventStore
34
34
  ::RSpec.shared_examples :event_repository do |mk_repository, helper|
35
35
  let(:repository) { mk_repository.call }
36
- let(:specification) { Specification.new(SpecificationReader.new(repository, Mappers::NullMapper.new)) }
36
+ let(:specification) { Specification.new(SpecificationReader.new(repository, Mappers::Default.new)) }
37
37
  let(:global_stream) { Stream.new(GLOBAL_STREAM) }
38
38
  let(:stream) { Stream.new(SecureRandom.uuid) }
39
39
  let(:stream_flow) { Stream.new("flow") }
@@ -968,6 +968,22 @@ module RubyEventStore
968
968
  expect(batches[1]).to eq(events[100..198])
969
969
  end
970
970
 
971
+ specify do
972
+ events = Array.new(200) { RubyEventStore::SRecord.new }
973
+ repository.append_to_stream(
974
+ events,
975
+ RubyEventStore::Stream.new(RubyEventStore::GLOBAL_STREAM),
976
+ RubyEventStore::ExpectedVersion.any
977
+ )
978
+
979
+ batches = repository.read(specification.as_at.forward.limit(101).in_batches.result).to_a
980
+ expect(batches.size).to eq(2)
981
+ expect(batches[0].size).to eq(100)
982
+ expect(batches[1].size).to eq(1)
983
+ expect(batches[0]).to eq(events[0..99])
984
+ expect(batches[1]).to eq([events[100]])
985
+ end
986
+
971
987
  specify do
972
988
  events = Array.new(200) { SRecord.new }
973
989
  repository.append_to_stream(events, Stream.new(GLOBAL_STREAM), ExpectedVersion.any)
@@ -1416,6 +1432,148 @@ module RubyEventStore
1416
1432
  )
1417
1433
  expect(repository.read(specification.result).count).to eq(0)
1418
1434
  end
1435
+
1436
+ specify "read in batches backward" do
1437
+ events = Array.new(200) { RubyEventStore::SRecord.new }
1438
+ repository.append_to_stream(
1439
+ events,
1440
+ RubyEventStore::Stream.new(RubyEventStore::GLOBAL_STREAM),
1441
+ RubyEventStore::ExpectedVersion.any
1442
+ )
1443
+
1444
+ batches = repository.read(specification.backward.limit(101).in_batches.result).to_a
1445
+ expect(batches.size).to eq(2)
1446
+ expect(batches[0].size).to eq(100)
1447
+ expect(batches[1].size).to eq(1)
1448
+ expect(batches[0]).to eq(events[100..-1].reverse)
1449
+ expect(batches[1]).to eq([events[99]])
1450
+ end
1451
+
1452
+ specify "read in batches forward" do
1453
+ events = Array.new(200) { RubyEventStore::SRecord.new }
1454
+ repository.append_to_stream(
1455
+ events,
1456
+ RubyEventStore::Stream.new(RubyEventStore::GLOBAL_STREAM),
1457
+ RubyEventStore::ExpectedVersion.any
1458
+ )
1459
+
1460
+ batches = repository.read(specification.forward.limit(101).in_batches.result).to_a
1461
+ expect(batches.size).to eq(2)
1462
+ expect(batches[0].size).to eq(100)
1463
+ expect(batches[1].size).to eq(1)
1464
+ expect(batches[0]).to eq(events[0..99])
1465
+ expect(batches[1]).to eq([events[100]])
1466
+ end
1467
+
1468
+ specify "read in batches forward from named stream" do
1469
+ all_events = Array.new(400) { RubyEventStore::SRecord.new }
1470
+ all_events.each_slice(2) do |(first, second)|
1471
+ repository.append_to_stream(
1472
+ [first],
1473
+ RubyEventStore::Stream.new("bazinga"),
1474
+ RubyEventStore::ExpectedVersion.any
1475
+ )
1476
+ repository.append_to_stream(
1477
+ [second],
1478
+ RubyEventStore::Stream.new(RubyEventStore::GLOBAL_STREAM),
1479
+ RubyEventStore::ExpectedVersion.any
1480
+ )
1481
+ end
1482
+ stream_events =
1483
+ all_events.each_with_index.select { |event, idx| event if idx % 2 == 0 }.map { |event, idx| event }
1484
+ batches = repository.read(specification.stream("bazinga").forward.limit(101).in_batches.result).to_a
1485
+ expect(batches.size).to eq(2)
1486
+ expect(batches[0].size).to eq(100)
1487
+ expect(batches[1].size).to eq(1)
1488
+ expect(batches[0]).to eq(stream_events[0..99])
1489
+ expect(batches[1]).to eq([stream_events[100]])
1490
+ end
1491
+
1492
+ specify "global stream order" do
1493
+ repository.append_to_stream(
1494
+ records = [
1495
+ RubyEventStore::SRecord.new(timestamp: with_precision(Time.new(2023, 1, 1, 12, 29, 0))),
1496
+ RubyEventStore::SRecord.new(timestamp: with_precision(Time.new(2023, 1, 1, 12, 28, 0))),
1497
+ RubyEventStore::SRecord.new(timestamp: with_precision(Time.new(2023, 1, 1, 12, 27, 0))),
1498
+ RubyEventStore::SRecord.new(timestamp: with_precision(Time.new(2023, 1, 1, 12, 26, 0)), valid_at: with_precision(Time.new(2023, 1, 1, 12, 30, 0))),
1499
+ ],
1500
+ RubyEventStore::Stream.new(RubyEventStore::GLOBAL_STREAM),
1501
+ RubyEventStore::ExpectedVersion.any
1502
+ )
1503
+
1504
+ expect(repository.read(specification.result).to_a).to eq([records[0], records[1], records[2], records[3]])
1505
+ expect(repository.read(specification.as_at.result).to_a).to eq([records[3], records[2], records[1], records[0]])
1506
+ expect(repository.read(specification.as_of.result).to_a).to eq([records[2], records[1], records[0], records[3]])
1507
+ end
1508
+
1509
+ specify "named stream order" do
1510
+ repository.append_to_stream(
1511
+ records = [
1512
+ RubyEventStore::SRecord.new(timestamp: with_precision(Time.new(2023, 1, 1, 12, 29, 0))),
1513
+ RubyEventStore::SRecord.new(timestamp: with_precision(Time.new(2023, 1, 1, 12, 28, 0))),
1514
+ RubyEventStore::SRecord.new(timestamp: with_precision(Time.new(2023, 1, 1, 12, 27, 0))),
1515
+ RubyEventStore::SRecord.new(timestamp: with_precision(Time.new(2023, 1, 1, 12, 26, 0)), valid_at: with_precision(Time.new(2023, 1, 1, 12, 30, 0))),
1516
+ ],
1517
+ RubyEventStore::Stream.new("stream"),
1518
+ RubyEventStore::ExpectedVersion.any
1519
+ )
1520
+
1521
+ expect(repository.read(specification.stream("stream").result).to_a).to eq([records[0], records[1], records[2], records[3]])
1522
+ expect(repository.read(specification.stream("stream").as_at.result).to_a).to eq([records[3], records[2], records[1], records[0]])
1523
+ expect(repository.read(specification.stream("stream").as_of.result).to_a).to eq([records[2], records[1], records[0], records[3]])
1524
+ end
1525
+
1526
+ specify "reading last event sorted by valid_at" do
1527
+ repository.append_to_stream(
1528
+ records = [
1529
+ RubyEventStore::SRecord.new(timestamp: with_precision(Time.new(2023, 1, 1, 12, 29, 0))),
1530
+ RubyEventStore::SRecord.new(timestamp: with_precision(Time.new(2023, 1, 1, 12, 28, 0))),
1531
+ RubyEventStore::SRecord.new(timestamp: with_precision(Time.new(2023, 1, 1, 12, 27, 0))),
1532
+ RubyEventStore::SRecord.new(timestamp: with_precision(Time.new(2023, 1, 1, 12, 26, 0)), valid_at: with_precision(Time.new(2023, 1, 1, 12, 30, 0))),
1533
+ ],
1534
+ RubyEventStore::Stream.new("stream"),
1535
+ RubyEventStore::ExpectedVersion.any
1536
+ )
1537
+
1538
+ expect(repository.read(specification.stream("stream").as_of.read_last.result)).to eq(records[3])
1539
+ end
1540
+
1541
+ specify "reading last event sorted by valid_at from global stream" do
1542
+ repository.append_to_stream(
1543
+ records = [
1544
+ SRecord.new(timestamp: with_precision(Time.new(2023, 1, 1, 12, 29, 0))),
1545
+ SRecord.new(timestamp: with_precision(Time.new(2023, 1, 1, 12, 28, 0))),
1546
+ SRecord.new(timestamp: with_precision(Time.new(2023, 1, 1, 12, 27, 0))),
1547
+ SRecord.new(timestamp: with_precision(Time.new(2023, 1, 1, 12, 26, 0)), valid_at: with_precision(Time.new(2023, 1, 1, 12, 30, 0))),
1548
+ ],
1549
+ Stream.new(GLOBAL_STREAM),
1550
+ ExpectedVersion.any
1551
+ )
1552
+
1553
+ expect(repository.read(specification.as_of.read_last.result)).to eq(records[3])
1554
+ end
1555
+
1556
+ specify "filter time by older than" do
1557
+ repository.append_to_stream(
1558
+ records = [
1559
+ SRecord.new(timestamp: with_precision(Time.utc(2023, 1, 1, 12, 29))),
1560
+ SRecord.new(timestamp: with_precision(Time.utc(2023, 1, 1, 12, 28))),
1561
+ SRecord.new(timestamp: with_precision(Time.utc(2023, 1, 1, 12, 27))),
1562
+ SRecord.new(timestamp: with_precision(Time.utc(2023, 1, 1, 12, 26)), valid_at: with_precision(Time.utc(2023, 1, 1, 12, 30))),
1563
+ ],
1564
+ Stream.new("stream"),
1565
+ ExpectedVersion.any
1566
+ )
1567
+
1568
+ expect(repository.read(specification.older_than(Time.utc(2023,1,1,12,28,1)).stream("stream").as_at.result).to_a).to eq([records[3], records[2], records[1]])
1569
+ expect(repository.read(specification.older_than(Time.utc(2023,1,1,12,28,1)).stream("stream").as_of.result).to_a).to eq([records[2], records[1]])
1570
+ end
1571
+
1572
+ private
1573
+
1574
+ def with_precision(time)
1575
+ time.round(TIMESTAMP_PRECISION)
1576
+ end
1419
1577
  end
1420
1578
 
1421
1579
  ::RSpec::Matchers.define :eq_ids do |expected_ids|
@@ -1,17 +1,17 @@
1
1
  module RubyEventStore
2
- ::RSpec.shared_examples :mapper do |mapper, domain_event|
2
+ ::RSpec.shared_examples :mapper do |mapper, event|
3
3
  specify "event_to_record returns instance of Record" do
4
- record = mapper.event_to_record(domain_event)
4
+ record = mapper.event_to_record(event)
5
5
 
6
6
  expect(record).to be_kind_of(Record)
7
- expect(record.event_id).to eq(domain_event.event_id)
8
- expect(record.event_type).to eq(domain_event.event_type)
7
+ expect(record.event_id).to eq(event.event_id)
8
+ expect(record.event_type).to eq(event.event_type)
9
9
  end
10
10
 
11
11
  specify "serialize and deserialize gives equal event" do
12
- record = mapper.event_to_record(domain_event)
12
+ record = mapper.event_to_record(event)
13
13
 
14
- expect(mapper.record_to_event(record)).to eq(domain_event)
14
+ expect(mapper.record_to_event(record)).to eq(event)
15
15
  end
16
16
  end
17
17
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RubyEventStore
4
- VERSION = "2.9.0"
4
+ VERSION = "2.9.1"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_event_store
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.9.0
4
+ version: 2.9.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Arkency
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-01-24 00:00:00.000000000 Z
11
+ date: 2023-02-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -118,7 +118,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
118
118
  - !ruby/object:Gem::Version
119
119
  version: '0'
120
120
  requirements: []
121
- rubygems_version: 3.3.26
121
+ rubygems_version: 3.3.7
122
122
  signing_key:
123
123
  specification_version: 4
124
124
  summary: Implementation of an event store in Ruby