sandthorn 0.13.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +4 -2
- data/README.md +25 -147
- data/lib/sandthorn.rb +3 -33
- data/lib/sandthorn/aggregate_root_base.rb +35 -45
- data/lib/sandthorn/event.rb +3 -2
- data/lib/sandthorn/event_inspector.rb +12 -10
- data/lib/sandthorn/version.rb +1 -1
- data/sandthorn.gemspec +1 -1
- data/spec/aggregate_delta_spec.rb +4 -4
- data/spec/aggregate_events_spec.rb +2 -8
- data/spec/aggregate_root_spec.rb +8 -8
- data/spec/aggregate_snapshot_spec.rb +263 -263
- data/spec/complex_aggregate_spec.rb +2 -2
- data/spec/constructor_events_spec.rb +3 -7
- data/spec/event_spec.rb +3 -3
- data/spec/spec_helper.rb +14 -11
- data/spec/stateless_events_spec.rb +31 -15
- data/spec/tracing_spec.rb +9 -11
- metadata +5 -10
- data/spec/get_events_spec.rb +0 -74
- data/spec/sandthorn_spec.rb +0 -72
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d4f14306b2c1c46da7b99ce8409f6e69dcddf050
|
4
|
+
data.tar.gz: 87dc839602892021e7aa13b2830bedbb1cc90891
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 627da016b372e4f64e452c7bd3a6a8b69412f11e43b2f885e46b1aff6593d4cc73db78521761d5ef2f670ff238836b17a9e25d36208db37830670b38b30fea41
|
7
|
+
data.tar.gz: a6db0ce8921f77bfeccf4fca94ba3ba2228f5f00d73318c445d5b3a60f9b8d7df98e3bfca6475bc27df9ff60a5704d3e51a0f46afeb8094bb0087bcd5a2b697a
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -13,8 +13,7 @@ A ruby library for saving an object's state as a series of events.
|
|
13
13
|
|
14
14
|
## When do I need event sourcing?
|
15
15
|
|
16
|
-
|
17
|
-
|
16
|
+
When state changes made to an object is important a common technique is to store the changes in a separate history log where the log is generated in parallel with the object internal state. With event sourcing the history log is now integrated within the object and generated based on the actions made to the object. The entries in log is the facts the object is built upon.
|
18
17
|
|
19
18
|
## Why Sandthorn?
|
20
19
|
|
@@ -25,88 +24,6 @@ Check out examples of Sandthorn:
|
|
25
24
|
* [Examples](https://github.com/Sandthorn/sandthorn_examples) including a product shop and TicTacToe game.
|
26
25
|
* Live [demo](http://infinite-mesa-8629.herokuapp.com/) comparing Active Record and Sandthorn.
|
27
26
|
|
28
|
-
## How do I use Sandthorn?
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
Think of it as an object database where you store not only what the new value of an attribute is, but also when and why it changed.
|
33
|
-
_Example:_
|
34
|
-
|
35
|
-
```ruby
|
36
|
-
|
37
|
-
# Setup the Aggregate
|
38
|
-
|
39
|
-
# The one available right now
|
40
|
-
require 'sandthorn'
|
41
|
-
require 'sandthorn_driver_sequel'
|
42
|
-
|
43
|
-
class Ship
|
44
|
-
include Sandthorn::AggregateRoot
|
45
|
-
attr_reader :name
|
46
|
-
|
47
|
-
def initialize name: nil, shipping_company: nil
|
48
|
-
@name = name
|
49
|
-
end
|
50
|
-
|
51
|
-
# State-changing command
|
52
|
-
def rename! new_name: ""
|
53
|
-
unless new_name.empty? or new_name == name
|
54
|
-
@name = new_name
|
55
|
-
ship_was_renamed
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
private
|
60
|
-
|
61
|
-
# Commit the event and state-change is automatically recorded.
|
62
|
-
def ship_was_renamed
|
63
|
-
commit
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
# Configure one driver
|
68
|
-
url = "sqlite://spec/db/sequel_driver.sqlite3"
|
69
|
-
sql_event_store = SandthornDriverSequel.driver_from_url(url: url)
|
70
|
-
Sandthorn.configure do |c|
|
71
|
-
c.event_store = sql_event_store
|
72
|
-
end
|
73
|
-
|
74
|
-
# Or configure many drivers
|
75
|
-
url = "sqlite://spec/db/sequel_driver.sqlite3"
|
76
|
-
sql_event_store = SandthornDriverSequel.driver_from_url(url: url)
|
77
|
-
url_two = "sqlite://spec/db/sequel_driver_two.sqlite3"
|
78
|
-
other_store = SandthornDriverSequel.driver_from_url(url: url_two)
|
79
|
-
|
80
|
-
Sandthorn.configure do |c|
|
81
|
-
c.event_stores = {
|
82
|
-
default: sql_event_store,
|
83
|
-
other_event_store: other_store
|
84
|
-
}
|
85
|
-
end
|
86
|
-
|
87
|
-
# Assign your aggregates to a named event store
|
88
|
-
|
89
|
-
class Boat
|
90
|
-
include Sandthorn::AggregateRoot
|
91
|
-
event_store :other_event_store
|
92
|
-
end
|
93
|
-
|
94
|
-
# Aggregates with no explicit event store will use the default event store
|
95
|
-
|
96
|
-
# Migrate db schema for the sequel driver
|
97
|
-
migrator = SandthornDriverSequel::Migration.new url: url
|
98
|
-
SandthornDriverSequel.migrate_db url: url
|
99
|
-
|
100
|
-
# Usage
|
101
|
-
ship = Ship.new name: "Titanic"
|
102
|
-
ship.rename! new_name: "Vasa"
|
103
|
-
|
104
|
-
ship.save
|
105
|
-
|
106
|
-
new_ship = Ship.find ship.id
|
107
|
-
puts new_ship.name
|
108
|
-
```
|
109
|
-
|
110
27
|
# Installation
|
111
28
|
|
112
29
|
Add this line to your application's Gemfile:
|
@@ -124,79 +41,42 @@ Or install it yourself as:
|
|
124
41
|
# Configuring Sandthorn
|
125
42
|
|
126
43
|
## Driver
|
44
|
+
Sandthorn can be setup with one or more drivers. A driver is bound to a specific data store where events are saved and loaded from. The current implemented drivers are [sandthorn_driver_sequel](https://github.com/Sandthorn/sandthorn_driver_sequel) for SQL via [Sequel](https://github.com/jeremyevans/sequel) and [sandthorn_driver_event_store](https://github.com/Sandthorn/sandthorn_driver_event_store) that uses [Get Event Store](https://geteventstore.com).
|
127
45
|
|
128
|
-
|
46
|
+
This means Sandthorn can be used with any data store given that a driver exists.
|
129
47
|
|
130
|
-
|
131
|
-
|
132
|
-
gem 'sandthorn_driver_sequel'
|
133
|
-
|
134
|
-
|
135
|
-
The driver is configured when your application launches. Here's an example of how to do it using the Sequel driver and a sqlite3 database.
|
48
|
+
Here's an example of setting up Sandthorn with the Sequel driver and a sqlite3 database.
|
136
49
|
|
137
50
|
```ruby
|
138
|
-
url = "sqlite://
|
51
|
+
url = "sqlite://sql.sqlite3"
|
139
52
|
driver = SandthornDriverSequel.driver_from_url(url: url)
|
140
53
|
Sandthorn.configure do |conf|
|
141
54
|
conf.event_stores = { default: driver }
|
142
55
|
end
|
143
56
|
```
|
144
57
|
|
145
|
-
First we specify the path to the sqlite3 database in the `url` variable. Secondly, the specific driver is instantiated with the `url`. Hence, the driver could be instantiated using a different configuration, for example, an address to a Postgres database. Finally, `Sandthorn.configure` accepts a keyword list with options. It´s here the driver is bound to Sandthorn via a context.
|
146
|
-
|
147
|
-
The first time you use the Sequel driver it is necessary to install the database schema.
|
148
|
-
|
149
|
-
```ruby
|
150
|
-
url = "sqlite://spec/db/sequel_driver.sqlite3"
|
151
|
-
SandthornDriverSequel::Migration.new url: url
|
152
|
-
SandthornDriverSequel.migrate_db url: url
|
153
|
-
```
|
154
|
-
|
155
|
-
Optionally, when using Sandthorn in your tests you can configure it in a `spec_helper.rb` which is then required by your test suites [example](https://github.com/Sandthorn/sandthorn_examples/blob/master/sandthorn_tictactoe/spec/spec_helper.rb#L20-L30). Note that the Sequel driver accepts a special parameter to empty the database between each test.
|
156
|
-
|
157
|
-
The Sequel driver is the only production-ready driver to date.
|
158
|
-
|
159
|
-
|
160
58
|
## Map aggregate types to event stores
|
161
59
|
|
162
|
-
Its possible to
|
60
|
+
Its possible to save events from different classes into different stores. Below the events from class FooAggregate are stored into the sql_foo.sqlite3 database and events from class BarAggregate are stored in sql_bar.sqlite3.
|
163
61
|
|
164
62
|
```ruby
|
165
|
-
|
166
|
-
|
63
|
+
driver_foo = SandthornDriverSequel.driver_from_url(url: "sqlite://sql_foo.sqlite3")
|
64
|
+
driver_bar = SandthornDriverSequel.driver_from_url(url: "sqlite://sql_bar.sqlite3")
|
167
65
|
|
168
|
-
|
169
|
-
driver_bar = SandthornDriverSequel.driver_from_url(url: url_bar)
|
170
|
-
|
171
|
-
class AnAggregate
|
66
|
+
class FooAggregate
|
172
67
|
Include Sandthorn::AggregateRoot
|
173
68
|
end
|
174
69
|
|
175
|
-
class
|
70
|
+
class BarAggregate
|
176
71
|
Include Sandthorn::AggregateRoot
|
177
72
|
end
|
178
73
|
|
179
74
|
Sandthorn.configure do |conf|
|
180
75
|
conf.event_stores = { foo: driver_foo, bar: driver_bar }
|
181
|
-
conf.map_types = { foo: [
|
76
|
+
conf.map_types = { foo: [FooAggregate], bar: [BarAggregate] }
|
182
77
|
end
|
183
78
|
```
|
184
79
|
|
185
|
-
## Data serialization
|
186
|
-
|
187
|
-
Its possible to configure how events and snapshots are serialized. Since version `0.11.0` of Sandthorn the serialization of events and snapshots is the responsibility of the driver. This means drivers can have different serialization mechanism, independent of each other.
|
188
|
-
|
189
|
-
The default serializer of the Sequel driver is YAML.
|
190
|
-
|
191
|
-
Here's how to use the Oj gem to serialize data in the Sequel driver:
|
192
|
-
|
193
|
-
```ruby
|
194
|
-
oj_driver = SandthornDriverSequel.driver_from_connection(connection: Sequel.sqlite) { |conf|
|
195
|
-
conf.event_serializer = Proc.new { |data| Oj::dump(data) }
|
196
|
-
conf.event_deserializer = Proc.new { |data| Oj::load(data) }
|
197
|
-
}
|
198
|
-
```
|
199
|
-
|
200
80
|
# Usage
|
201
81
|
|
202
82
|
## Aggregate Root
|
@@ -217,7 +97,7 @@ All objects that include `Sandthorn::AggregateRoot` is provided with an `aggrega
|
|
217
97
|
|
218
98
|
An abstraction over `commit` that creates events methods that can be used from within a command method.
|
219
99
|
|
220
|
-
In this exampel the `events` method will generate a method called `marked`, this method take
|
100
|
+
In this exampel the `events` method will generate a method called `marked`, this method take an block that will be executed before the event is commited and is used to groups the state changes to the event. The block is optional and the state changes could have been made outside the `marked` method.
|
221
101
|
|
222
102
|
```ruby
|
223
103
|
class Board
|
@@ -227,7 +107,7 @@ class Board
|
|
227
107
|
|
228
108
|
def mark player, pos_x, pos_y
|
229
109
|
# change some state
|
230
|
-
marked(
|
110
|
+
marked() do
|
231
111
|
@pos_x = pos_x
|
232
112
|
@pos_y = pos_y
|
233
113
|
end
|
@@ -237,7 +117,7 @@ end
|
|
237
117
|
|
238
118
|
### `Sandthorn::AggregateRoot::constructor_events`
|
239
119
|
|
240
|
-
|
120
|
+
With `constructor_events` its possible to be more specific on how an aggregate came to be. The first event will now have the name `board_created` instead of the default `new`.
|
241
121
|
|
242
122
|
```ruby
|
243
123
|
class Board
|
@@ -257,9 +137,9 @@ end
|
|
257
137
|
|
258
138
|
### `Sandthorn::AggregateRoot::stateless_events`
|
259
139
|
|
260
|
-
Calling `stateless_events` creates public class methods. The first argument is an `aggregate_id
|
140
|
+
Calling `stateless_events` creates public class methods. The first argument is an `aggregate_id` and the second argument is optional but has to be a hash and is stored in the attribute_deltas of the event.
|
261
141
|
|
262
|
-
When creating a stateless event, the corresponding aggregate is never loaded
|
142
|
+
When creating a stateless event, the corresponding aggregate is never loaded and the event is saved without calling the save method.
|
263
143
|
|
264
144
|
```ruby
|
265
145
|
class Board
|
@@ -269,7 +149,7 @@ class Board
|
|
269
149
|
|
270
150
|
end
|
271
151
|
|
272
|
-
Board.player_went_to_toilet "board_aggregate_id", player_id, time
|
152
|
+
Board.player_went_to_toilet "board_aggregate_id", {player_id: "1", time: "10:12"}
|
273
153
|
```
|
274
154
|
|
275
155
|
### `Sandthorn::AggregateRoot::default_attributes`
|
@@ -286,7 +166,7 @@ end
|
|
286
166
|
|
287
167
|
### `Sandthorn::AggregateRoot.commit`
|
288
168
|
|
289
|
-
|
169
|
+
To generate an event the commit method has to be called within the aggregate. `commit` extracts the object's delta and locally caches the state changes that has been applied to the aggregate.
|
290
170
|
|
291
171
|
```ruby
|
292
172
|
def mark player, pos_x, pos_y
|
@@ -301,11 +181,11 @@ end
|
|
301
181
|
|
302
182
|
`commit` determines the state changes by monitoring the object's readable fields.
|
303
183
|
|
304
|
-
|
184
|
+
The concept `events` have been introduced to abstract away the usage of `commit`. Commit still works as before but we think that the `events` abstraction makes the aggregate more readable.
|
305
185
|
|
306
186
|
### `Sandthorn::AggregateRoot.save`
|
307
187
|
|
308
|
-
|
188
|
+
The save method store generated events, this means all commited events will be persisted via a Sandthorn driver.
|
309
189
|
|
310
190
|
```ruby
|
311
191
|
board = Board.new
|
@@ -315,7 +195,7 @@ board.save
|
|
315
195
|
|
316
196
|
### `Sandthorn::AggregateRoot.all`
|
317
197
|
|
318
|
-
|
198
|
+
Retrieve an array with all instances of a specific aggregate type.
|
319
199
|
|
320
200
|
```ruby
|
321
201
|
Board.all
|
@@ -329,20 +209,18 @@ Board.all.select { |board| board.active == true }
|
|
329
209
|
|
330
210
|
### `Sandthorn::AggregateRoot.find`
|
331
211
|
|
332
|
-
|
212
|
+
Loads a specific aggregate using it's uuid.
|
333
213
|
|
334
214
|
```ruby
|
335
215
|
uuid = '550e8400-e29b-41d4-a716-446655440000'
|
336
216
|
board = Board.find(uuid)
|
337
|
-
board.aggregate_id == uuid
|
338
217
|
```
|
339
218
|
|
340
|
-
If no aggregate with the specifid
|
341
|
-
|
219
|
+
If no aggregate with the specifid uuid is found, a `Sandthorn::Errors::AggregateNotFound` exception is raised.
|
342
220
|
|
343
221
|
### `Sandthorn::AggregateRoot.aggregate_trace`
|
344
222
|
|
345
|
-
Using `aggregate_trace` one can store meta data
|
223
|
+
Using `aggregate_trace` one can store meta data on events. The data is not aggregate specific and it can for example store who executed a specific command on the aggregate.
|
346
224
|
|
347
225
|
```ruby
|
348
226
|
board.aggregate_trace {player: "Fred"} do |aggregate|
|
@@ -353,7 +231,7 @@ end
|
|
353
231
|
|
354
232
|
`aggregate_trace` can also be specified on a class.
|
355
233
|
|
356
|
-
|
234
|
+
```ruby
|
357
235
|
Board.aggregate_trace {ip: :127.0.0.1} do
|
358
236
|
board = Board.new
|
359
237
|
board.mark :o , 0, 1
|
data/lib/sandthorn.rb
CHANGED
@@ -32,50 +32,20 @@ module Sandthorn
|
|
32
32
|
SecureRandom.uuid
|
33
33
|
end
|
34
34
|
|
35
|
-
def get_aggregate_events aggregate_type, aggregate_id
|
36
|
-
event_store_for(aggregate_type).get_aggregate_events aggregate_id
|
37
|
-
end
|
38
|
-
|
39
35
|
def save_events aggregate_events, aggregate_id, aggregate_type
|
40
36
|
event_store_for(aggregate_type).save_events aggregate_events, aggregate_id, *aggregate_type
|
41
37
|
end
|
42
38
|
|
43
|
-
def get_aggregate aggregate_id, aggregate_type
|
44
|
-
event_store_for(aggregate_type).get_aggregate_events_from_snapshot aggregate_id
|
45
|
-
end
|
46
|
-
|
47
|
-
def save_snapshot(aggregate)
|
48
|
-
event_store_for(aggregate.class).save_snapshot(aggregate)
|
49
|
-
end
|
50
|
-
|
51
|
-
def get_aggregate_list_by_type aggregate_type
|
52
|
-
event_store_for(aggregate_type).get_aggregate_ids(aggregate_type: aggregate_type)
|
53
|
-
end
|
54
|
-
|
55
39
|
def all aggregate_type
|
56
40
|
event_store_for(aggregate_type).all(aggregate_type)
|
57
41
|
end
|
58
42
|
|
59
43
|
def find aggregate_id, aggregate_type
|
60
|
-
event_store_for(aggregate_type).find(aggregate_id)
|
44
|
+
event_store_for(aggregate_type).find(aggregate_id, aggregate_type)
|
61
45
|
end
|
62
46
|
|
63
|
-
def
|
64
|
-
|
65
|
-
events = event_store.get_events aggregate_types: aggregate_types, take: take, after_sequence_number: after_sequence_number
|
66
|
-
events.map do |event|
|
67
|
-
Event.new(event)
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
def obsolete_snapshots type_names: [], min_event_distance: 0
|
72
|
-
obsolete = event_stores.flat_map { |event_store| event_store.obsolete_snapshots(aggregate_types: type_names, max_event_distance: min_event_distance) }
|
73
|
-
obsolete.map do |single_obsolete|
|
74
|
-
type = Kernel.const_get single_obsolete[:aggregate_type]
|
75
|
-
aggregate = type.aggregate_find(single_obsolete[:aggregate_id]).tap do |agg|
|
76
|
-
yield agg if block_given?
|
77
|
-
end
|
78
|
-
end
|
47
|
+
def save_snapshot(aggregate)
|
48
|
+
raise "Not Implemented"
|
79
49
|
end
|
80
50
|
|
81
51
|
def find_event_store(name)
|
@@ -42,9 +42,9 @@ module Sandthorn
|
|
42
42
|
@aggregate_trace_information = nil
|
43
43
|
end
|
44
44
|
|
45
|
-
def commit
|
45
|
+
def commit
|
46
46
|
event_name = caller_locations(1,1)[0].label.gsub(/block ?(.*) in /, "")
|
47
|
-
commit_with_event_name(event_name
|
47
|
+
commit_with_event_name(event_name)
|
48
48
|
end
|
49
49
|
|
50
50
|
def default_attributes
|
@@ -82,12 +82,17 @@ module Sandthorn
|
|
82
82
|
end
|
83
83
|
|
84
84
|
def aggregate_find aggregate_id
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
85
|
+
begin
|
86
|
+
events = Sandthorn.find(aggregate_id, self)
|
87
|
+
unless events && !events.empty?
|
88
|
+
raise Errors::AggregateNotFound
|
89
|
+
end
|
89
90
|
|
90
|
-
|
91
|
+
return aggregate_build events
|
92
|
+
rescue Exception
|
93
|
+
raise Errors::AggregateNotFound
|
94
|
+
end
|
95
|
+
|
91
96
|
end
|
92
97
|
|
93
98
|
def new *args, &block
|
@@ -100,26 +105,20 @@ module Sandthorn
|
|
100
105
|
aggregate.send :set_aggregate_id, Sandthorn.generate_aggregate_id
|
101
106
|
|
102
107
|
aggregate.aggregate_trace @@aggregate_trace_information do |aggr|
|
103
|
-
aggr.send :commit
|
108
|
+
aggr.send :commit
|
104
109
|
return aggr
|
105
110
|
end
|
106
111
|
|
107
112
|
end
|
108
113
|
|
109
114
|
def aggregate_build events
|
110
|
-
|
111
|
-
aggregate = events.first[:aggregate]
|
112
|
-
events.shift
|
113
|
-
else
|
114
|
-
aggregate = create_new_empty_aggregate
|
115
|
-
end
|
115
|
+
aggregate = create_new_empty_aggregate
|
116
116
|
|
117
117
|
if events.any?
|
118
118
|
current_aggregate_version = events.last[:aggregate_version]
|
119
119
|
aggregate.send :set_orginating_aggregate_version!, current_aggregate_version
|
120
120
|
aggregate.send :set_current_aggregate_version!, current_aggregate_version
|
121
121
|
end
|
122
|
-
|
123
122
|
attributes = build_instance_vars_from_events events
|
124
123
|
aggregate.send :clear_aggregate_events
|
125
124
|
|
@@ -130,15 +129,12 @@ module Sandthorn
|
|
130
129
|
aggregate
|
131
130
|
end
|
132
131
|
|
133
|
-
|
134
|
-
|
135
132
|
def stateless_events(*event_names)
|
136
133
|
event_names.each do |name|
|
137
134
|
define_singleton_method name do |aggregate_id, *args|
|
138
|
-
event =
|
135
|
+
event = build_stateless_event(name.to_s, args)
|
139
136
|
Sandthorn.save_events([event], aggregate_id, self)
|
140
137
|
return aggregate_id
|
141
|
-
|
142
138
|
end
|
143
139
|
end
|
144
140
|
end
|
@@ -152,7 +148,7 @@ module Sandthorn
|
|
152
148
|
aggregate.aggregate_initialize
|
153
149
|
aggregate.send :set_aggregate_id, Sandthorn.generate_aggregate_id
|
154
150
|
aggregate.instance_eval(&block) if block
|
155
|
-
aggregate.send :commit_with_event_name, name.to_s
|
151
|
+
aggregate.send :commit_with_event_name, name.to_s
|
156
152
|
return aggregate
|
157
153
|
end
|
158
154
|
|
@@ -165,7 +161,7 @@ module Sandthorn
|
|
165
161
|
event_names.each do |name|
|
166
162
|
define_method(name) do |*args, &block|
|
167
163
|
block.call() if block
|
168
|
-
commit_with_event_name(name.to_s
|
164
|
+
commit_with_event_name(name.to_s)
|
169
165
|
end
|
170
166
|
private name.to_s
|
171
167
|
end
|
@@ -173,30 +169,33 @@ module Sandthorn
|
|
173
169
|
|
174
170
|
private
|
175
171
|
|
176
|
-
def
|
172
|
+
def build_stateless_event name, args = []
|
173
|
+
|
174
|
+
formated_attribute_deltas = args.first.map do |key, value|
|
175
|
+
{
|
176
|
+
attribute_name: key.to_s,
|
177
|
+
old_value: nil,
|
178
|
+
new_value: value
|
179
|
+
}
|
180
|
+
end unless args.empty?
|
177
181
|
|
178
182
|
data = {
|
179
|
-
|
180
|
-
method_args: args,
|
181
|
-
attribute_deltas: attribute_deltas
|
183
|
+
attribute_deltas: formated_attribute_deltas
|
182
184
|
}
|
183
185
|
|
184
|
-
unless trace_information.nil? || trace_information.empty?
|
185
|
-
data.merge!({ trace: trace_information })
|
186
|
-
end
|
187
|
-
|
188
186
|
return {
|
189
|
-
aggregate_version:
|
187
|
+
aggregate_version: nil,
|
190
188
|
event_name: name,
|
191
|
-
|
189
|
+
event_data: data,
|
190
|
+
event_metadata: nil
|
192
191
|
}
|
193
192
|
|
194
193
|
end
|
195
194
|
|
196
195
|
def build_instance_vars_from_events events
|
197
196
|
events.each_with_object({}) do |event, instance_vars|
|
198
|
-
|
199
|
-
attribute_deltas =
|
197
|
+
event_data = event[:event_data]
|
198
|
+
attribute_deltas = event_data[:attribute_deltas]
|
200
199
|
unless attribute_deltas.nil?
|
201
200
|
deltas = attribute_deltas.each_with_object({}) do |delta, acc|
|
202
201
|
acc[delta[:attribute_name]] = delta[:new_value]
|
@@ -206,10 +205,6 @@ module Sandthorn
|
|
206
205
|
end
|
207
206
|
end
|
208
207
|
|
209
|
-
def first_event_snapshot? events
|
210
|
-
events.first[:aggregate]
|
211
|
-
end
|
212
|
-
|
213
208
|
def create_new_empty_aggregate
|
214
209
|
allocate
|
215
210
|
end
|
@@ -256,24 +251,19 @@ module Sandthorn
|
|
256
251
|
@aggregate_id = aggregate_id
|
257
252
|
end
|
258
253
|
|
259
|
-
def commit_with_event_name(event_name
|
254
|
+
def commit_with_event_name(event_name)
|
260
255
|
aggregate_attribute_deltas = get_delta
|
261
256
|
|
262
257
|
increase_current_aggregate_version!
|
263
258
|
data = {
|
264
|
-
method_name: event_name,
|
265
|
-
method_args: args,
|
266
259
|
attribute_deltas: aggregate_attribute_deltas
|
267
260
|
}
|
268
|
-
trace_information = @aggregate_trace_information
|
269
|
-
unless trace_information.nil? || trace_information.empty?
|
270
|
-
data.merge!({ trace: trace_information })
|
271
|
-
end
|
272
261
|
|
273
262
|
@aggregate_events << ({
|
274
263
|
aggregate_version: @aggregate_current_event_version,
|
275
264
|
event_name: event_name,
|
276
|
-
|
265
|
+
event_data: data,
|
266
|
+
event_metadata: @aggregate_trace_information
|
277
267
|
})
|
278
268
|
|
279
269
|
self
|