sequent 4.2.0 → 4.3.0

Sign up to get free protection for your applications and to get access to all the features.
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