event_sorcerer 0.1.2 → 0.1.3

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
  SHA1:
3
- metadata.gz: 1a30a15c744e7f3f861840bbdc3cfb822a5b8a88
4
- data.tar.gz: 11012f39e7e59b80349a947f63216cec5f28657a
3
+ metadata.gz: 12872b11f0ed0ab93b3223cfc0c2e3ec9d03412d
4
+ data.tar.gz: 4e63ccf41e6f96e20c5852409ebe44371d0f6ecc
5
5
  SHA512:
6
- metadata.gz: 1a2db2aaa933ed7280f7cebe9d6544bcd767a605ddc78108ed2e1911481d2efb5f7ebf2b364358b82e8777357a01190dab8e3bc11371db3b6f81844287e3c0a9
7
- data.tar.gz: de9da895801ddd797276efdd48c55cccad6342a822eea80b6451a2e864f7b2c97bc59825c43f2387dc0137840639a65e1b31d2e92345f172a06949d2660b1d93
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
- with_all_loaders_for_type do |loaders|
27
- loaders.map(&:load).each do |aggregate|
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
- @event_methods ||= []
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
- event_methods.concat new_events
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
- # id - the ID of the aggregate to load.
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(id)
66
- if unit_of_work.fetch_aggregate(id)
67
- return unit_of_work.fetch_aggregate(id)
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
- with_loader_for_id(id) do |loader|
71
- loader.load.tap do |aggregate|
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
- with_loader_for_id(id, false) do |loader|
88
- loader.load.tap do |aggregate|
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: Grabs the event streams for the aggregate class and yields
108
- # them to a given block.
109
- #
110
- # block - the block to yield the event stream to.
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 with_all_event_streams_for_type
114
- yield event_store.read_event_streams_for_type(name)
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: Creates AggregateLoaders for an ID and yields it to a given
118
- # block.
129
+ # Private: Maps an array of IDs replacing with cached aggregate if
130
+ # available.
119
131
  #
120
- # prohibit_new - value of the prohibit_new flag to be passed to loaders.
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 the return value of the given block.
124
- def with_all_loaders_for_type(prohibit_new = true)
125
- with_all_event_streams_for_type do |streams|
126
- loaders = streams.map do |stream|
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
- yield loaders
139
+ cached ? cached : id
132
140
  end
133
141
  end
134
142
 
135
- # Private: Grabs the event stream for an ID and yields it to a given
136
- # block.
143
+ # Private: Loads an array of aggregates out of the event store.
137
144
  #
138
- # id - the ID of the aggregate to get the event stream for.
139
- # block - the block to yield the event stream to.
145
+ # ids - the IDs of the aggregates to load.
140
146
  #
141
- # Returns the return value of the given block.
142
- def with_event_stream_for_id(id)
143
- yield event_store.read_event_stream(id, name)
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
- # Private: Creates an AggregateLoader for an ID and yields it to a given
147
- # block.
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 the return value of the given block.
153
- def with_loader_for_id(id, prohibit_new = true)
154
- with_event_stream_for_id(id) do |stream|
155
- yield AggregateLoader.new(self, stream.id, stream.events,
156
- stream.current_version, prohibit_new)
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
- self
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
- @_aggregate.send method_sym, *expected_args
112
+ Invokr.invoke method: method_sym, on: @_aggregate, using: details
113
113
  end
114
114
  rescue StandardError => e
115
115
  undo_dirty_event!
@@ -8,7 +8,7 @@ module EventSorcerer
8
8
  delegates :EventSorcerer, :message_bus
9
9
 
10
10
  # Public: Returns nil.
11
- def fetch_aggregate(_id)
11
+ def fetch_aggregate(_type, _id)
12
12
  nil
13
13
  end
14
14
 
@@ -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
- # id - the ID for the aggregate.
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[id]
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
- return self if fetch_aggregate(aggregate.id)
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
@@ -1,4 +1,4 @@
1
1
  # Public: Defines a constant for the current version number.
2
2
  module EventSorcerer
3
- VERSION = '0.1.2'
3
+ VERSION = '0.1.3'
4
4
  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.2
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-04 00:00:00.000000000 Z
11
+ date: 2014-12-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler