sequent 4.2.0 → 4.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b7e291ad7f19e869e7606e8dc49282a545db07d4a656f5ee44d71ed5c2e33170
4
- data.tar.gz: fb73e4b00b0f0e9ef94cab2152922c280b51d3568f5f9ecb7a9cdaa00afed97e
3
+ metadata.gz: feea2aeb3dba28570a36615392e4ecc1037bfdfd1c2d667bcc787113e4c7fdba
4
+ data.tar.gz: 79dc60b21109885a56f3f68cf97185afee5692167f54db1934eaa89dc9d030de
5
5
  SHA512:
6
- metadata.gz: df076f1efbe41c17c75c99c5331d7f1e23ff8c52607c9a0e709a9dd46504a2b6e78d471ed247dff4e5913809de28bc328a820ce00779d0a97fb64f669a10670e
7
- data.tar.gz: 552dca913ac052facd09d2602c08a38fa33c66e3d4c092d38a6fcd018dabca2683ef93d5f3ddef8b105fa043c6d99bf765be38ad2f69171a08e5af63df3783ad
6
+ metadata.gz: bb74d9c6cbb946bab9b00cb2ea73eab80caed4737d12ce2115a6c97348ca0e9452a14280b3d0de9ecba237c201fdd8b2914382751569224c89cae92128d5d3f5
7
+ data.tar.gz: 5fe084735eb4df8855b8102e68d027ca828a8dd7540d577b6e0a97616bbd22815432e684f20d48d04ad111db962fe935af4bff50afd8ebc7242f5c15f01b97a7
@@ -57,6 +57,37 @@ module Sequent
57
57
  load_aggregates([aggregate_id], clazz)[0]
58
58
  end
59
59
 
60
+ # Optimised for loading lots of events and ignore snapshot events. To get the correct historical state of an
61
+ # AggregateRoot it is necessary to be able to ignore snapshots. For a nested AggregateRoot, there will not be a
62
+ # sequence number known, so a load_until timestamp can be used instead.
63
+ #
64
+ # +aggregate_id+ The id of the aggregate to be loaded
65
+ #
66
+ # +clazz+ Optional argument that checks if aggregate is of type +clazz+
67
+ #
68
+ # +load_until+ Optional argument that defines up until what point in time the AggregateRoot will be rebuilt.
69
+ def load_aggregate_for_snapshotting(aggregate_id, clazz = nil, load_until: nil)
70
+ fail ArgumentError, 'aggregate_id is required' if aggregate_id.blank?
71
+
72
+ stream = Sequent
73
+ .configuration
74
+ .event_store
75
+ .find_event_stream(aggregate_id)
76
+ aggregate = Class.const_get(stream.aggregate_type).stream_from_history(stream)
77
+
78
+ Sequent
79
+ .configuration
80
+ .event_store
81
+ .stream_events_for_aggregate(aggregate_id, load_until: load_until) do |event_stream|
82
+ aggregate.stream_from_history(event_stream)
83
+ end
84
+
85
+ if clazz
86
+ fail TypeError, "#{aggregate.class} is not a #{clazz}" unless aggregate.class <= clazz
87
+ end
88
+ aggregate
89
+ end
90
+
60
91
  ##
61
92
  # Loads multiple aggregates at once.
62
93
  # Returns the ones in the current Unit Of Work otherwise loads it from history.
@@ -80,6 +80,26 @@ module Sequent
80
80
  events.each { |event| apply_event(event) }
81
81
  end
82
82
 
83
+ def initialize_for_streaming(stream)
84
+ @uncommitted_events = []
85
+ @sequence_number = 1
86
+ @event_stream = stream
87
+ end
88
+
89
+ def stream_from_history(stream_events)
90
+ _stream, event = stream_events
91
+ fail 'Empty history' if event.blank?
92
+
93
+ @id ||= event.aggregate_id
94
+ apply_event(event)
95
+ end
96
+
97
+ def self.stream_from_history(stream)
98
+ aggregate_root = allocate
99
+ aggregate_root.initialize_for_streaming(stream)
100
+ aggregate_root
101
+ end
102
+
83
103
  def to_s
84
104
  "#{self.class.name}: #{@id}"
85
105
  end
@@ -51,7 +51,38 @@ module Sequent
51
51
  end
52
52
 
53
53
  ##
54
- # Returns all events for the aggregate ordered by sequence_number
54
+ # Returns all events for the AggregateRoot ordered by sequence_number, disregarding snapshot events.
55
+ #
56
+ # This streaming is done in batches to prevent loading many events in memory all at once. A usecase for ignoring
57
+ # the snapshots is when events of a nested AggregateRoot need to be loaded up until a certain moment in time.
58
+ #
59
+ # @param aggregate_id Aggregate id of the AggregateRoot
60
+ # @param load_until The timestamp up until which you want to built the aggregate. Optional.
61
+ # @param &block Block that should be passed to handle the batches returned from this method
62
+ def stream_events_for_aggregate(aggregate_id, load_until: nil, &block)
63
+ stream = find_event_stream(aggregate_id)
64
+ fail ArgumentError, 'no stream found for this aggregate' if stream.blank?
65
+
66
+ q = Sequent
67
+ .configuration
68
+ .event_record_class
69
+ .where(aggregate_id: aggregate_id)
70
+ .where.not(event_type: Sequent.configuration.snapshot_event_class.name)
71
+ .order(:sequence_number)
72
+ q = q.where('created_at < ?', load_until) if load_until.present?
73
+ has_events = false
74
+
75
+ q.select('event_type, event_json').each_row do |event_hash|
76
+ has_events = true
77
+ event = deserialize_event(event_hash)
78
+ block.call([stream, event])
79
+ end
80
+ fail ArgumentError, 'no events for this aggregate' unless has_events
81
+ end
82
+
83
+ ##
84
+ # Returns all events for the aggregate ordered by sequence_number, loading them from the latest snapshot
85
+ # event onwards, if a snapshot is present
55
86
  #
56
87
  def load_events(aggregate_id)
57
88
  load_events_for_aggregates([aggregate_id])[0]
data/lib/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sequent
4
- VERSION = '4.2.0'
4
+ VERSION = '4.3.0'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sequent
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.2.0
4
+ version: 4.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lars Vonk
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2022-01-30 00:00:00.000000000 Z
15
+ date: 2022-03-21 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: activemodel
@@ -23,7 +23,7 @@ dependencies:
23
23
  version: '5.0'
24
24
  - - "<="
25
25
  - !ruby/object:Gem::Version
26
- version: 6.1.4.4
26
+ version: 7.0.2
27
27
  type: :runtime
28
28
  prerelease: false
29
29
  version_requirements: !ruby/object:Gem::Requirement
@@ -33,7 +33,7 @@ dependencies:
33
33
  version: '5.0'
34
34
  - - "<="
35
35
  - !ruby/object:Gem::Version
36
- version: 6.1.4.4
36
+ version: 7.0.2
37
37
  - !ruby/object:Gem::Dependency
38
38
  name: activerecord
39
39
  requirement: !ruby/object:Gem::Requirement
@@ -43,7 +43,7 @@ dependencies:
43
43
  version: '5.0'
44
44
  - - "<="
45
45
  - !ruby/object:Gem::Version
46
- version: 6.1.4.4
46
+ version: 7.0.2
47
47
  type: :runtime
48
48
  prerelease: false
49
49
  version_requirements: !ruby/object:Gem::Requirement
@@ -53,7 +53,7 @@ dependencies:
53
53
  version: '5.0'
54
54
  - - "<="
55
55
  - !ruby/object:Gem::Version
56
- version: 6.1.4.4
56
+ version: 7.0.2
57
57
  - !ruby/object:Gem::Dependency
58
58
  name: bcrypt
59
59
  requirement: !ruby/object:Gem::Requirement
@@ -119,7 +119,7 @@ dependencies:
119
119
  version: 2.6.5
120
120
  - - "<"
121
121
  - !ruby/object:Gem::Version
122
- version: '3.1'
122
+ version: '3.2'
123
123
  type: :runtime
124
124
  prerelease: false
125
125
  version_requirements: !ruby/object:Gem::Requirement
@@ -129,7 +129,7 @@ dependencies:
129
129
  version: 2.6.5
130
130
  - - "<"
131
131
  - !ruby/object:Gem::Version
132
- version: '3.1'
132
+ version: '3.2'
133
133
  - !ruby/object:Gem::Dependency
134
134
  name: pg
135
135
  requirement: !ruby/object:Gem::Requirement
@@ -443,7 +443,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
443
443
  - !ruby/object:Gem::Version
444
444
  version: '0'
445
445
  requirements: []
446
- rubygems_version: 3.2.3
446
+ rubygems_version: 3.3.7
447
447
  signing_key:
448
448
  specification_version: 4
449
449
  summary: Event sourcing framework for Ruby