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 +4 -4
- data/lib/sequent/core/aggregate_repository.rb +31 -0
- data/lib/sequent/core/aggregate_root.rb +20 -0
- data/lib/sequent/core/event_store.rb +32 -1
- data/lib/version.rb +1 -1
- metadata +9 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: feea2aeb3dba28570a36615392e4ecc1037bfdfd1c2d667bcc787113e4c7fdba
|
4
|
+
data.tar.gz: 79dc60b21109885a56f3f68cf97185afee5692167f54db1934eaa89dc9d030de
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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
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.
|
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-
|
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:
|
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:
|
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:
|
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:
|
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.
|
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.
|
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.
|
446
|
+
rubygems_version: 3.3.7
|
447
447
|
signing_key:
|
448
448
|
specification_version: 4
|
449
449
|
summary: Event sourcing framework for Ruby
|