sandthorn_driver_sequel 2.1.1 → 3.0.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/.ruby-version +1 -1
- data/.travis.yml +2 -1
- data/README.md +30 -1
- data/lib/sandthorn_driver_sequel/access/aggregate_access.rb +2 -0
- data/lib/sandthorn_driver_sequel/access/event_access.rb +22 -5
- data/lib/sandthorn_driver_sequel/access/snapshot_access.rb +58 -40
- data/lib/sandthorn_driver_sequel/access.rb +0 -4
- data/lib/sandthorn_driver_sequel/event_store.rb +24 -14
- data/lib/sandthorn_driver_sequel/migration.rb +3 -2
- data/lib/sandthorn_driver_sequel/sequel_driver.rb +4 -3
- data/lib/sandthorn_driver_sequel/version.rb +1 -1
- data/lib/sandthorn_driver_sequel/wrappers/event_wrapper.rb +1 -1
- data/lib/sandthorn_driver_sequel/wrappers/snapshot_wrapper.rb +10 -2
- data/lib/sandthorn_driver_sequel.rb +89 -5
- data/sandthorn_driver_sequel.gemspec +0 -2
- data/spec/asking_for_aggregates_to_snapshot_spec.rb +8 -6
- data/spec/benchmark_spec.rb +5 -5
- data/spec/configuration_spec.rb +102 -0
- data/spec/driver_interface_spec.rb +0 -1
- data/spec/event_access_spec.rb +15 -8
- data/spec/event_store_with_context_spec.rb +5 -5
- data/spec/get_events_spec.rb +8 -8
- data/spec/saving_events_spec.rb +13 -30
- data/spec/saving_snapshot_spec.rb +12 -20
- data/spec/snapshot_access_spec.rb +35 -44
- data/spec/spec_helper.rb +5 -2
- metadata +38 -64
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bce877362844db909c0b8d1d6548ad29c41750e5
|
4
|
+
data.tar.gz: d6ad4a8929b306e4a962eb1195db49d0bbfd9de9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7b1294dc014cac377927b4e74c72270258b4b85ef4cd0a420971408d12f6536da71df03239c69328ae0c57a914556d1304c29845ca581485c8005f9f068223da
|
7
|
+
data.tar.gz: 67a03daf9055212d0d0d9610df5cc49ec6a7d51e779ce7036206861aa1e0e226b5710f0923e727e2916d50e7602b8c13e528d99343743df5ca23f1e175c31a30
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
ruby-2.
|
1
|
+
ruby-2.0
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -20,7 +20,36 @@ Or install it yourself as:
|
|
20
20
|
|
21
21
|
## Usage
|
22
22
|
|
23
|
-
|
23
|
+
### `SandthornDriverSequel.configure`
|
24
|
+
|
25
|
+
Change the global configuration, the default data serialization for events and snapshots are YAML.
|
26
|
+
|
27
|
+
Change the serialization of events and snapshots to Oj.
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
SandthornDriverSequel.configure { |conf|
|
31
|
+
conf.event_serializer = Proc.new { |data| Oj::dump(data) }
|
32
|
+
conf.event_deserializer = Proc.new { |data| Oj::load(data) }
|
33
|
+
conf.snapshot_serializer = Proc.new { |data| Oj::dump(data) }
|
34
|
+
conf.snapshot_deserializer = Proc.new { |data| Oj::dump(data) }
|
35
|
+
}
|
36
|
+
```
|
37
|
+
|
38
|
+
### `SandthornDriverSequel.driver_from_connection`
|
39
|
+
|
40
|
+
Creates a driver from a Sequel connection. Its possible to send in a block like the one for `configure` to chage configuration for the driver.
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
driver = SandthornDriverSequel.driver_from_connection(connection: Sequel.sqlite)
|
44
|
+
```
|
45
|
+
|
46
|
+
### `SandthornDriverSequel.driver_from_url`
|
47
|
+
|
48
|
+
Creates a driver from a Sequel url. Its possible to send in a block like the one for `configure` to change configuration for the driver.
|
49
|
+
|
50
|
+
```ruby
|
51
|
+
driver = SandthornDriverSequel.driver_from_connection(url: "<sequel url string>")
|
52
|
+
```
|
24
53
|
|
25
54
|
## Contributing
|
26
55
|
|
@@ -1,8 +1,16 @@
|
|
1
|
+
require "sandthorn_driver_sequel/access"
|
2
|
+
|
1
3
|
module SandthornDriverSequel
|
2
4
|
class EventAccess < Access::Base
|
3
5
|
# = EventAccess
|
4
6
|
# Reads and writes events.
|
5
7
|
|
8
|
+
def initialize storage, serializer, deserializer
|
9
|
+
@serializer = serializer
|
10
|
+
@deserializer = deserializer
|
11
|
+
super storage
|
12
|
+
end
|
13
|
+
|
6
14
|
def store_events(aggregate, events)
|
7
15
|
events = Utilities.array_wrap(events)
|
8
16
|
timestamp = Time.now.utc
|
@@ -48,16 +56,25 @@ module SandthornDriverSequel
|
|
48
56
|
|
49
57
|
def wrap(arg)
|
50
58
|
events = Utilities.array_wrap(arg)
|
59
|
+
events.each { |e| e[:event_args] = deserialize(e[:event_data]) }
|
51
60
|
events.map { |e| EventWrapper.new(e.values) }
|
52
61
|
end
|
53
62
|
|
63
|
+
def deserialize event_data
|
64
|
+
@deserializer.call(event_data)
|
65
|
+
end
|
66
|
+
|
67
|
+
def serialize event_args
|
68
|
+
@serializer.call(event_args)
|
69
|
+
end
|
70
|
+
|
54
71
|
def build_event_data(aggregate, timestamp, event)
|
55
72
|
{
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
73
|
+
aggregate_table_id: aggregate.id,
|
74
|
+
aggregate_version: aggregate.aggregate_version,
|
75
|
+
event_name: event.event_name,
|
76
|
+
event_data: serialize(event.event_args),
|
77
|
+
timestamp: timestamp
|
61
78
|
}
|
62
79
|
end
|
63
80
|
|
@@ -1,21 +1,50 @@
|
|
1
|
+
require "sandthorn_driver_sequel/access"
|
2
|
+
|
1
3
|
module SandthornDriverSequel
|
2
4
|
class SnapshotAccess < Access::Base
|
3
5
|
|
6
|
+
def initialize storage, serializer, deserializer
|
7
|
+
@serializer = serializer
|
8
|
+
@deserializer = deserializer
|
9
|
+
super storage
|
10
|
+
end
|
11
|
+
|
4
12
|
def find_by_aggregate_id(aggregate_id)
|
5
|
-
|
6
|
-
|
13
|
+
|
14
|
+
aggregate_from_table = aggregates.find_by_aggregate_id(aggregate_id)
|
15
|
+
return nil if aggregate_from_table.nil?
|
16
|
+
snapshot = storage.snapshots.first(aggregate_table_id: aggregate_from_table.id)
|
17
|
+
if snapshot
|
18
|
+
aggregate = deserialize(snapshot[:snapshot_data])
|
19
|
+
|
20
|
+
snapshot_data = {
|
21
|
+
aggregate: aggregate,
|
22
|
+
snapshot_id: snapshot.id,
|
23
|
+
aggregate_table_id: snapshot[:aggregate_table_id]
|
24
|
+
}
|
25
|
+
return SnapshotWrapper.new(snapshot_data)
|
26
|
+
end
|
27
|
+
|
28
|
+
return nil
|
7
29
|
end
|
8
30
|
|
9
31
|
def find(snapshot_id)
|
10
|
-
|
32
|
+
|
33
|
+
snapshot = storage.snapshots[snapshot_id]
|
34
|
+
aggregate = deserialize(snapshot[:snapshot_data])
|
35
|
+
|
36
|
+
snapshot_data = {
|
37
|
+
aggregate: aggregate,
|
38
|
+
snapshot_id: snapshot_id,
|
39
|
+
aggregate_table_id: snapshot[:aggregate_table_id]
|
40
|
+
}
|
41
|
+
|
42
|
+
SnapshotWrapper.new(snapshot_data)
|
11
43
|
end
|
12
44
|
|
13
|
-
def record_snapshot(
|
14
|
-
|
15
|
-
|
16
|
-
if perform_snapshot?(aggregate, previous_snapshot)
|
17
|
-
perform_snapshot(aggregate, previous_snapshot, snapshot_data)
|
18
|
-
end
|
45
|
+
def record_snapshot(aggregate)
|
46
|
+
aggregate_from_table = aggregates.find_by_aggregate_id!(aggregate.aggregate_id)
|
47
|
+
perform_snapshot(aggregate, aggregate_from_table.id)
|
19
48
|
end
|
20
49
|
|
21
50
|
def obsolete(aggregate_types: [], max_event_distance: 100)
|
@@ -38,49 +67,38 @@ module SandthornDriverSequel
|
|
38
67
|
@aggregates ||= AggregateAccess.new(storage)
|
39
68
|
end
|
40
69
|
|
41
|
-
def perform_snapshot
|
42
|
-
|
43
|
-
snapshot =
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
def perform_snapshot(aggregate, snapshot, snapshot_data)
|
48
|
-
check_snapshot_version!(aggregate, snapshot_data)
|
49
|
-
if valid_snapshot?(snapshot)
|
50
|
-
update_snapshot(snapshot, snapshot_data)
|
70
|
+
def perform_snapshot(aggregate, aggregate_table_id)
|
71
|
+
current_snapshot = storage.snapshots.first(aggregate_table_id: aggregate_table_id)
|
72
|
+
snapshot = build_snapshot(aggregate)
|
73
|
+
if current_snapshot
|
74
|
+
update_snapshot(snapshot, current_snapshot.id)
|
51
75
|
else
|
52
|
-
insert_snapshot(
|
76
|
+
insert_snapshot(snapshot, aggregate_table_id)
|
53
77
|
end
|
54
78
|
end
|
55
79
|
|
56
|
-
def
|
57
|
-
data = build_snapshot(snapshot_data)
|
58
|
-
data[:aggregate_table_id] = aggregate.id
|
59
|
-
storage.snapshots.insert(data)
|
60
|
-
end
|
61
|
-
|
62
|
-
def build_snapshot(snapshot_data)
|
63
|
-
snapshot_data = SnapshotWrapper.new(snapshot_data)
|
80
|
+
def build_snapshot(aggregate)
|
64
81
|
{
|
65
|
-
|
66
|
-
|
82
|
+
snapshot_data: serialize(aggregate),
|
83
|
+
aggregate_version: aggregate.aggregate_version
|
67
84
|
}
|
68
85
|
end
|
69
86
|
|
70
|
-
def
|
71
|
-
snapshot
|
87
|
+
def insert_snapshot(snapshot, id)
|
88
|
+
snapshot[:aggregate_table_id] = id
|
89
|
+
storage.snapshots.insert(snapshot)
|
72
90
|
end
|
73
91
|
|
74
|
-
def update_snapshot(snapshot,
|
75
|
-
|
76
|
-
storage.snapshots.where(id: snapshot.id).update(data)
|
92
|
+
def update_snapshot(snapshot, id)
|
93
|
+
storage.snapshots.where(id: id).update(snapshot)
|
77
94
|
end
|
78
95
|
|
79
|
-
def
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
96
|
+
def serialize aggregate
|
97
|
+
@serializer.call(aggregate)
|
98
|
+
end
|
99
|
+
|
100
|
+
def deserialize snapshot_data
|
101
|
+
@deserializer.call(snapshot_data)
|
84
102
|
end
|
85
103
|
|
86
104
|
end
|
@@ -1,13 +1,25 @@
|
|
1
|
+
require "sandthorn_driver_sequel/access/aggregate_access"
|
2
|
+
require "sandthorn_driver_sequel/access/event_access"
|
3
|
+
require "sandthorn_driver_sequel/access/snapshot_access"
|
4
|
+
require "sandthorn_driver_sequel/storage"
|
5
|
+
|
1
6
|
module SandthornDriverSequel
|
2
7
|
class EventStore
|
3
8
|
include EventStoreContext
|
4
9
|
|
5
|
-
attr_reader :driver, :context
|
10
|
+
attr_reader :driver, :context
|
6
11
|
|
7
|
-
def initialize
|
8
|
-
@driver =
|
12
|
+
def initialize connection, configuration, context = nil
|
13
|
+
@driver = connection
|
9
14
|
@context = context
|
10
|
-
@
|
15
|
+
@event_serializer = configuration.event_serializer
|
16
|
+
@event_deserializer = configuration.event_deserializer
|
17
|
+
@snapshot_serializer = configuration.snapshot_serializer
|
18
|
+
@snapshot_deserializer = configuration.snapshot_deserializer
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.from_url url, configuration, context = nil
|
22
|
+
new(SequelDriver.new(url: url), configuration, context)
|
11
23
|
end
|
12
24
|
|
13
25
|
def save_events events, aggregate_id, class_name
|
@@ -26,10 +38,10 @@ module SandthornDriverSequel
|
|
26
38
|
end
|
27
39
|
end
|
28
40
|
|
29
|
-
def save_snapshot
|
41
|
+
def save_snapshot aggregate
|
30
42
|
driver.execute_in_transaction do |db|
|
31
43
|
snapshot_access = get_snapshot_access(db)
|
32
|
-
snapshot_access.record_snapshot(
|
44
|
+
snapshot_access.record_snapshot(aggregate)
|
33
45
|
end
|
34
46
|
end
|
35
47
|
|
@@ -53,9 +65,7 @@ module SandthornDriverSequel
|
|
53
65
|
|
54
66
|
def build_snapshot_event(snapshot)
|
55
67
|
{
|
56
|
-
|
57
|
-
event_data: snapshot[:snapshot_data],
|
58
|
-
event_name: "aggregate_set_from_snapshot"
|
68
|
+
aggregate: snapshot.data,
|
59
69
|
}
|
60
70
|
end
|
61
71
|
|
@@ -87,7 +97,7 @@ module SandthornDriverSequel
|
|
87
97
|
driver.execute do |db|
|
88
98
|
snapshots = get_snapshot_access(db)
|
89
99
|
snapshot = snapshots.find_by_aggregate_id(aggregate_id)
|
90
|
-
|
100
|
+
snapshot.data
|
91
101
|
end
|
92
102
|
end
|
93
103
|
|
@@ -119,19 +129,19 @@ module SandthornDriverSequel
|
|
119
129
|
end
|
120
130
|
|
121
131
|
def get_aggregate_access(db)
|
122
|
-
AggregateAccess.new(storage(db))
|
132
|
+
@aggregate_access ||= AggregateAccess.new(storage(db))
|
123
133
|
end
|
124
134
|
|
125
135
|
def get_event_access(db)
|
126
|
-
EventAccess.new(storage(db))
|
136
|
+
@event_access ||= EventAccess.new(storage(db), @event_serializer, @event_deserializer)
|
127
137
|
end
|
128
138
|
|
129
139
|
def get_snapshot_access(db)
|
130
|
-
SnapshotAccess.new(storage(db))
|
140
|
+
@snapshot_access ||= SnapshotAccess.new(storage(db), @snapshot_serializer, @snapshot_deserializer)
|
131
141
|
end
|
132
142
|
|
133
143
|
def storage(db)
|
134
|
-
Storage.new(db, context)
|
144
|
+
@storage ||= Storage.new(db, @context)
|
135
145
|
end
|
136
146
|
|
137
147
|
end
|
@@ -3,8 +3,9 @@ module SandthornDriverSequel
|
|
3
3
|
class Migration
|
4
4
|
include EventStoreContext
|
5
5
|
attr_reader :driver, :context
|
6
|
-
def initialize url: nil, context: nil
|
7
|
-
@driver = SequelDriver.new
|
6
|
+
def initialize url: nil, connection: nil, context: nil
|
7
|
+
@driver = SequelDriver.new connection: connection if connection
|
8
|
+
@driver = SequelDriver.new url: url if url
|
8
9
|
@context = context
|
9
10
|
end
|
10
11
|
def migrate!
|
@@ -3,10 +3,11 @@ require 'sequel'
|
|
3
3
|
module SandthornDriverSequel
|
4
4
|
class SequelDriver
|
5
5
|
|
6
|
-
def initialize
|
7
|
-
@url = args.fetch(:url)
|
6
|
+
def initialize(args = {})
|
8
7
|
Sequel.default_timezone = :utc
|
9
|
-
@db =
|
8
|
+
@db = args.fetch(:connection) {
|
9
|
+
Sequel.connect(args.fetch(:url))
|
10
|
+
}
|
10
11
|
end
|
11
12
|
|
12
13
|
def execute
|
@@ -2,7 +2,7 @@ require 'delegate'
|
|
2
2
|
module SandthornDriverSequel
|
3
3
|
class EventWrapper < SimpleDelegator
|
4
4
|
|
5
|
-
[:aggregate_version, :event_name, :event_data, :timestamp, :aggregate_table_id].each do |attribute|
|
5
|
+
[:aggregate_version, :event_name, :event_data, :event_args, :timestamp, :aggregate_table_id].each do |attribute|
|
6
6
|
define_method(attribute) do
|
7
7
|
fetch(attribute)
|
8
8
|
end
|
@@ -1,11 +1,19 @@
|
|
1
1
|
module SandthornDriverSequel
|
2
2
|
class SnapshotWrapper < SimpleDelegator
|
3
3
|
def aggregate_version
|
4
|
-
self[:aggregate_version
|
4
|
+
self[:aggregate].aggregate_version
|
5
5
|
end
|
6
6
|
|
7
7
|
def data
|
8
|
-
self[:
|
8
|
+
self[:aggregate]
|
9
|
+
end
|
10
|
+
|
11
|
+
def snapshot_id
|
12
|
+
self[:snapshot_id]
|
13
|
+
end
|
14
|
+
|
15
|
+
def aggregate_table_id
|
16
|
+
self[:aggregate_table_id]
|
9
17
|
end
|
10
18
|
end
|
11
19
|
end
|
@@ -3,20 +3,104 @@ require "sandthorn_driver_sequel/utilities"
|
|
3
3
|
require "sandthorn_driver_sequel/wrappers"
|
4
4
|
require "sandthorn_driver_sequel/event_query"
|
5
5
|
require "sandthorn_driver_sequel/event_store_context"
|
6
|
-
require "sandthorn_driver_sequel/access"
|
7
|
-
require "sandthorn_driver_sequel/storage"
|
8
6
|
require 'sandthorn_driver_sequel/event_store'
|
9
7
|
require 'sandthorn_driver_sequel/errors'
|
10
8
|
require 'sandthorn_driver_sequel/migration'
|
9
|
+
require 'yaml'
|
11
10
|
|
12
11
|
module SandthornDriverSequel
|
13
12
|
class << self
|
14
|
-
|
15
|
-
EventStore.new url: url, context: context
|
16
|
-
end
|
13
|
+
|
17
14
|
def migrate_db url: nil, context: nil
|
18
15
|
migrator = Migration.new url: url, context: context
|
19
16
|
migrator.migrate!
|
20
17
|
end
|
18
|
+
|
19
|
+
def driver_from_url url: nil, context: nil
|
20
|
+
|
21
|
+
if block_given?
|
22
|
+
configuration = Configuration.new
|
23
|
+
yield(configuration)
|
24
|
+
else
|
25
|
+
configuration = self.configuration
|
26
|
+
end
|
27
|
+
|
28
|
+
EventStore.from_url(url, configuration, context)
|
29
|
+
end
|
30
|
+
|
31
|
+
def driver_from_connection connection: nil, context: nil
|
32
|
+
if block_given?
|
33
|
+
configuration = Configuration.new
|
34
|
+
yield(configuration)
|
35
|
+
else
|
36
|
+
configuration = self.configuration
|
37
|
+
end
|
38
|
+
EventStore.new(SequelDriver.new(connection: connection), configuration, context)
|
39
|
+
end
|
40
|
+
|
41
|
+
def configure
|
42
|
+
yield(configuration) if block_given?
|
43
|
+
end
|
44
|
+
|
45
|
+
def configuration
|
46
|
+
@configuration ||= Configuration.new
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
class Configuration
|
52
|
+
|
53
|
+
#event
|
54
|
+
def event_serializer=(block)
|
55
|
+
@event_serializer = block
|
56
|
+
end
|
57
|
+
|
58
|
+
def event_deserializer=(block)
|
59
|
+
@event_deserializer = block
|
60
|
+
end
|
61
|
+
|
62
|
+
def event_serializer
|
63
|
+
@event_serializer || default_event_serializer
|
64
|
+
end
|
65
|
+
|
66
|
+
def event_deserializer
|
67
|
+
@event_deserializer || default_event_deserializer
|
68
|
+
end
|
69
|
+
|
70
|
+
def default_event_serializer
|
71
|
+
-> (data) { YAML.dump(data) }
|
72
|
+
end
|
73
|
+
|
74
|
+
def default_event_deserializer
|
75
|
+
-> (data) { YAML.load(data) }
|
76
|
+
end
|
77
|
+
|
78
|
+
#snapshot
|
79
|
+
def snapshot_serializer=(block)
|
80
|
+
@snapshot_serializer = block
|
81
|
+
end
|
82
|
+
|
83
|
+
def snapshot_deserializer=(block)
|
84
|
+
@snapshot_deserializer = block
|
85
|
+
end
|
86
|
+
|
87
|
+
def snapshot_serializer
|
88
|
+
@snapshot_serializer || default_snapshot_serializer
|
89
|
+
end
|
90
|
+
|
91
|
+
def snapshot_deserializer
|
92
|
+
@snapshot_deserializer || default_snapshot_deserializer
|
93
|
+
end
|
94
|
+
|
95
|
+
def default_snapshot_serializer
|
96
|
+
-> (data) { YAML.dump(data) }
|
97
|
+
end
|
98
|
+
|
99
|
+
def default_snapshot_deserializer
|
100
|
+
-> (data) { YAML.load(data) }
|
101
|
+
end
|
102
|
+
|
103
|
+
|
104
|
+
end
|
21
105
|
end
|
22
106
|
end
|