event_sorcerer 0.1.2 → 0.1.3
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/event_sorcerer/aggregate.rb +78 -54
- data/lib/event_sorcerer/aggregate_loader.rb +3 -3
- data/lib/event_sorcerer/aggregate_proxy.rb +5 -5
- data/lib/event_sorcerer/no_unit_of_work.rb +1 -1
- data/lib/event_sorcerer/unit_of_work.rb +9 -6
- data/lib/event_sorcerer/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 12872b11f0ed0ab93b3223cfc0c2e3ec9d03412d
|
4
|
+
data.tar.gz: 4e63ccf41e6f96e20c5852409ebe44371d0f6ecc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1e11b7fd1cca67145850336cfb78f04c910e316a2b0e820443bcc8e68dca3448635776fc5453bd1b3189f3ea64c34f974e6a33d2dddc41cb61412ef9f9c5df0e
|
7
|
+
data.tar.gz: d3006f46d56580237e33278ddfc86500ae57bdf0799846a781e919672d61dc2659b844ea2dd0676eb4915a06473a990927d9978aa11813dff188aa3355c14a0c
|
@@ -23,17 +23,25 @@ module EventSorcerer
|
|
23
23
|
#
|
24
24
|
# Returns an Array of AggregateProxy objects.
|
25
25
|
def all
|
26
|
-
|
27
|
-
|
26
|
+
all_loaders_for_type.map do |loader|
|
27
|
+
cached = unit_of_work.fetch_aggregate(to_s, loader.id)
|
28
|
+
|
29
|
+
next cached if cached
|
30
|
+
|
31
|
+
loader.load.tap do |aggregate|
|
28
32
|
unit_of_work.store_aggregate(aggregate)
|
29
33
|
end
|
30
34
|
end
|
31
35
|
end
|
32
36
|
|
33
37
|
# Public: An array of symbols representing the names of the methods which
|
34
|
-
# are events.
|
38
|
+
# are events. Includes event methods of superclass.
|
35
39
|
def event_methods
|
36
|
-
|
40
|
+
if superclass.respond_to? :event_methods
|
41
|
+
_event_methods.concat(superclass.event_methods).uniq
|
42
|
+
else
|
43
|
+
_event_methods
|
44
|
+
end
|
37
45
|
end
|
38
46
|
|
39
47
|
# Public: Methods defined within this block will have their method symbol
|
@@ -51,26 +59,26 @@ module EventSorcerer
|
|
51
59
|
!starting_methods.include? method
|
52
60
|
end
|
53
61
|
|
54
|
-
|
62
|
+
_event_methods.concat new_events
|
55
63
|
class_eval(&block)
|
56
64
|
|
57
65
|
self
|
58
66
|
end
|
59
67
|
|
60
|
-
# Public: Load an aggregate out of the event store.
|
68
|
+
# Public: Load an aggregate(s) out of the event store.
|
61
69
|
#
|
62
|
-
#
|
70
|
+
# id_or_ids - the ID of the aggregate to load or an array of the same.
|
63
71
|
#
|
64
|
-
# Returns an AggregateProxy object.
|
65
|
-
def find(
|
66
|
-
if
|
67
|
-
|
72
|
+
# Returns an AggregateProxy object or an array of the same.
|
73
|
+
def find(id_or_ids)
|
74
|
+
return find_many(id_or_ids) if id_or_ids.respond_to?(:each)
|
75
|
+
|
76
|
+
if unit_of_work.fetch_aggregate(to_s, id_or_ids)
|
77
|
+
return unit_of_work.fetch_aggregate(to_s, id_or_ids)
|
68
78
|
end
|
69
79
|
|
70
|
-
|
71
|
-
|
72
|
-
unit_of_work.store_aggregate(aggregate)
|
73
|
-
end
|
80
|
+
loader_for_id(id_or_ids).load.tap do |aggregate|
|
81
|
+
unit_of_work.store_aggregate(aggregate)
|
74
82
|
end
|
75
83
|
end
|
76
84
|
|
@@ -80,14 +88,12 @@ module EventSorcerer
|
|
80
88
|
#
|
81
89
|
# Returns an AggregateProxy object.
|
82
90
|
def find_or_new(id)
|
83
|
-
if unit_of_work.fetch_aggregate(id)
|
84
|
-
return unit_of_work.fetch_aggregate(id)
|
91
|
+
if unit_of_work.fetch_aggregate(to_s, id)
|
92
|
+
return unit_of_work.fetch_aggregate(to_s, id)
|
85
93
|
end
|
86
94
|
|
87
|
-
|
88
|
-
|
89
|
-
unit_of_work.store_aggregate(aggregate)
|
90
|
-
end
|
95
|
+
loader_for_id(id, false).load.tap do |aggregate|
|
96
|
+
unit_of_work.store_aggregate(aggregate)
|
91
97
|
end
|
92
98
|
end
|
93
99
|
|
@@ -104,56 +110,74 @@ module EventSorcerer
|
|
104
110
|
|
105
111
|
private
|
106
112
|
|
107
|
-
# Private:
|
108
|
-
#
|
109
|
-
|
110
|
-
|
113
|
+
# Private: An array of symbols representing the names of the methods
|
114
|
+
# which are events.
|
115
|
+
def _event_methods
|
116
|
+
@_event_methods ||= []
|
117
|
+
end
|
118
|
+
|
119
|
+
# Private: Creates an AggregateLoader for each persisted aggregate.
|
111
120
|
#
|
112
121
|
# Returns the return value of the given block.
|
113
|
-
def
|
114
|
-
|
122
|
+
def all_loaders_for_type
|
123
|
+
event_store.read_event_streams_for_type(name).map do |stream|
|
124
|
+
AggregateLoader.new(self, stream.id, stream.events,
|
125
|
+
stream.current_version, true)
|
126
|
+
end
|
115
127
|
end
|
116
128
|
|
117
|
-
# Private:
|
118
|
-
#
|
129
|
+
# Private: Maps an array of IDs replacing with cached aggregate if
|
130
|
+
# available.
|
119
131
|
#
|
120
|
-
#
|
121
|
-
# block - the block to yield the event stream to.
|
132
|
+
# ids - the IDs of the aggregates to check the cache from.
|
122
133
|
#
|
123
|
-
# Returns
|
124
|
-
def
|
125
|
-
|
126
|
-
|
127
|
-
AggregateLoader.new(self, stream.id, stream.events,
|
128
|
-
stream.current_version, prohibit_new)
|
129
|
-
end
|
134
|
+
# Returns a mixed Array of AggregateProxy objects and IDs.
|
135
|
+
def perform_cache_pass(ids)
|
136
|
+
ids.map do |id|
|
137
|
+
cached = unit_of_work.fetch_aggregate(to_s, id)
|
130
138
|
|
131
|
-
|
139
|
+
cached ? cached : id
|
132
140
|
end
|
133
141
|
end
|
134
142
|
|
135
|
-
# Private:
|
136
|
-
# block.
|
143
|
+
# Private: Loads an array of aggregates out of the event store.
|
137
144
|
#
|
138
|
-
#
|
139
|
-
# block - the block to yield the event stream to.
|
145
|
+
# ids - the IDs of the aggregates to load.
|
140
146
|
#
|
141
|
-
# Returns
|
142
|
-
def
|
143
|
-
|
147
|
+
# Returns an Array of AggregateProxy objects.
|
148
|
+
def find_many(ids)
|
149
|
+
aggregates = perform_cache_pass(ids)
|
150
|
+
|
151
|
+
uncached_ids = aggregates.reject { |a| a.is_a? self }
|
152
|
+
|
153
|
+
uncached = loaders_for_ids(uncached_ids).reduce({}) do |hash, loader|
|
154
|
+
aggregate = loader.load
|
155
|
+
unit_of_work.store_aggregate(aggregate)
|
156
|
+
|
157
|
+
hash.merge aggregate.id => aggregate
|
158
|
+
end
|
159
|
+
|
160
|
+
aggregates.map do |id_or_agg|
|
161
|
+
uncached[id_or_agg] ? uncached[id_or_agg] : id_or_agg
|
162
|
+
end
|
144
163
|
end
|
145
164
|
|
146
|
-
|
147
|
-
|
165
|
+
def loader_for_id(id, prohibit_new = true)
|
166
|
+
stream = event_store.read_event_stream(id, name)
|
167
|
+
|
168
|
+
AggregateLoader.new(self, stream.id, stream.events,
|
169
|
+
stream.current_version, prohibit_new)
|
170
|
+
end
|
171
|
+
|
172
|
+
# Private: Creates an AggregateLoader for each given ID.
|
148
173
|
#
|
149
174
|
# id - the ID of the aggregate to get the event stream for.
|
150
|
-
# block - the block to yield the event stream to.
|
151
175
|
#
|
152
|
-
# Returns
|
153
|
-
def
|
154
|
-
|
155
|
-
|
156
|
-
|
176
|
+
# Returns an Array of AggregateLoader instances.
|
177
|
+
def loaders_for_ids(ids, prohibit_new = true)
|
178
|
+
event_store.read_multiple_event_streams(ids, name).map do |stream|
|
179
|
+
AggregateLoader.new(self, stream.id, stream.events,
|
180
|
+
stream.current_version, prohibit_new)
|
157
181
|
end
|
158
182
|
end
|
159
183
|
end
|
@@ -1,6 +1,9 @@
|
|
1
1
|
module EventSorcerer
|
2
2
|
# Public: Service class for loading aggregates from the event store.
|
3
3
|
class AggregateLoader
|
4
|
+
# Public: Returns the id for the aggregate to be loaded.
|
5
|
+
attr_reader :id
|
6
|
+
|
4
7
|
# Public: Creates a new AggregateLoader instance.
|
5
8
|
#
|
6
9
|
# klass - class for the aggregate to be loaded.
|
@@ -29,9 +32,6 @@ module EventSorcerer
|
|
29
32
|
# Private: Returns array of Events to hydrate with.
|
30
33
|
attr_reader :events
|
31
34
|
|
32
|
-
# Private: Returns the id for the aggregate to be loaded.
|
33
|
-
attr_reader :id
|
34
|
-
|
35
35
|
# Private: Returns the class for the aggregate to be loaded.3
|
36
36
|
attr_reader :klass
|
37
37
|
|
@@ -60,6 +60,8 @@ module EventSorcerer
|
|
60
60
|
# Private: Handles the serialization of event arguments and pushes the
|
61
61
|
# Event object onto the _dirty_events array. Increments the local
|
62
62
|
# version number for the aggregate.
|
63
|
+
#
|
64
|
+
# Returns argument hash.
|
63
65
|
def add_dirty_event!(time, method_sym, *arguments)
|
64
66
|
increment_version!
|
65
67
|
|
@@ -69,7 +71,7 @@ module EventSorcerer
|
|
69
71
|
details = ArgumentHashifier.hashify(method.parameters, arguments.dup)
|
70
72
|
@_dirty_events << Event.new(method_sym, time, details)
|
71
73
|
|
72
|
-
|
74
|
+
details
|
73
75
|
end
|
74
76
|
|
75
77
|
# Private: Decrements the wrapped aggregates local version by one.
|
@@ -104,12 +106,10 @@ module EventSorcerer
|
|
104
106
|
fail EventArgumentError if block
|
105
107
|
|
106
108
|
time = Time.now
|
107
|
-
add_dirty_event!(time, method_sym, *arguments)
|
108
|
-
|
109
|
-
expected_args = arguments.slice(0, @_aggregate.method(method_sym).arity)
|
109
|
+
details = add_dirty_event!(time, method_sym, *arguments)
|
110
110
|
|
111
111
|
EventSorcerer.with_time(time) do
|
112
|
-
|
112
|
+
Invokr.invoke method: method_sym, on: @_aggregate, using: details
|
113
113
|
end
|
114
114
|
rescue StandardError => e
|
115
115
|
undo_dirty_event!
|
@@ -41,12 +41,15 @@ module EventSorcerer
|
|
41
41
|
|
42
42
|
# Public: Fetches an aggregate via it's ID from the identity map.
|
43
43
|
#
|
44
|
-
#
|
44
|
+
# type - the type for the aggregate.
|
45
|
+
# id - the ID for the aggregate.
|
45
46
|
#
|
46
47
|
# Returns nil if not found.
|
47
48
|
# Returns Aggregate if found.
|
48
|
-
def fetch_aggregate(id)
|
49
|
-
identity_map[
|
49
|
+
def fetch_aggregate(type, id)
|
50
|
+
return unless identity_map[type]
|
51
|
+
|
52
|
+
identity_map[type][id]
|
50
53
|
end
|
51
54
|
|
52
55
|
def handle_save(save)
|
@@ -61,9 +64,9 @@ module EventSorcerer
|
|
61
64
|
#
|
62
65
|
# Returns self.
|
63
66
|
def store_aggregate(aggregate)
|
64
|
-
|
65
|
-
|
66
|
-
identity_map[aggregate.id] = aggregate
|
67
|
+
type = aggregate.class.to_s
|
68
|
+
identity_map[type] ||= {}
|
69
|
+
identity_map[type][aggregate.id] = aggregate
|
67
70
|
|
68
71
|
self
|
69
72
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: event_sorcerer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sebastian Edwards
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-12-
|
11
|
+
date: 2014-12-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|