sandthorn_driver_sequel 2.1.1 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|