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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d205c3b770d2f9e6df066e3c28bcb8cb690978e5
4
- data.tar.gz: 9fdaf52d4a30f3d1e5e40967ffdfa6554179962c
3
+ metadata.gz: bce877362844db909c0b8d1d6548ad29c41750e5
4
+ data.tar.gz: d6ad4a8929b306e4a962eb1195db49d0bbfd9de9
5
5
  SHA512:
6
- metadata.gz: 44c1d90a3247da4deaf51f811f2005b7b86ec55dd14cf1a9cd8a0124f36a8344f523dfb917a63b65a8d64b38e2afc4b99ecb3542b37cc33dc409c5f5688c60ec
7
- data.tar.gz: 0b4614730ab5f124e3f3133fefae5985d06c298312e1f4066f3af9ee78ba70709643783b97c6b4b5a4947ce7cd8b65a54d10bd854f2d92d3b56f0002dc4d7459
6
+ metadata.gz: 7b1294dc014cac377927b4e74c72270258b4b85ef4cd0a420971408d12f6536da71df03239c69328ae0c57a914556d1304c29845ca581485c8005f9f068223da
7
+ data.tar.gz: 67a03daf9055212d0d0d9610df5cc49ec6a7d51e779ce7036206861aa1e0e226b5710f0923e727e2916d50e7602b8c13e528d99343743df5ca23f1e175c31a30
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- ruby-2.1
1
+ ruby-2.0
data/.travis.yml CHANGED
@@ -1,4 +1,5 @@
1
1
  language: ruby
2
2
  rvm:
3
+ - 2.2.3
3
4
  - 2.1.0
4
- - 2.0.0
5
+ - 2.0.0
data/README.md CHANGED
@@ -20,7 +20,36 @@ Or install it yourself as:
20
20
 
21
21
  ## Usage
22
22
 
23
- TODO: Write usage instructions here
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,3 +1,5 @@
1
+ require "sandthorn_driver_sequel/access"
2
+
1
3
  module SandthornDriverSequel
2
4
  class AggregateAccess < Access::Base
3
5
 
@@ -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
- aggregate_table_id: aggregate.id,
57
- aggregate_version: aggregate.aggregate_version,
58
- event_name: event.event_name,
59
- event_data: event.event_data,
60
- timestamp: timestamp
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
- aggregate = aggregates.find_by_aggregate_id(aggregate_id)
6
- storage.snapshots.first(aggregate_table_id: aggregate.id)
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
- storage.snapshots[snapshot_id]
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(aggregate_id, snapshot_data)
14
- aggregate = aggregates.find_by_aggregate_id!(aggregate_id)
15
- previous_snapshot = find_by_aggregate_id(aggregate_id)
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?(aggregate, snapshot)
42
- return true if snapshot.nil?
43
- snapshot = SnapshotWrapper.new(snapshot)
44
- aggregate.aggregate_version > snapshot.aggregate_version
45
- end
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(aggregate, snapshot_data)
76
+ insert_snapshot(snapshot, aggregate_table_id)
53
77
  end
54
78
  end
55
79
 
56
- def insert_snapshot(aggregate, snapshot_data)
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
- snapshot_data: snapshot_data.data,
66
- aggregate_version: snapshot_data.aggregate_version
82
+ snapshot_data: serialize(aggregate),
83
+ aggregate_version: aggregate.aggregate_version
67
84
  }
68
85
  end
69
86
 
70
- def valid_snapshot?(snapshot)
71
- snapshot && snapshot[:snapshot_data]
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, snapshot_data)
75
- data = build_snapshot(snapshot_data)
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 check_snapshot_version!(aggregate, snapshot_data)
80
- snapshot = SnapshotWrapper.new(snapshot_data)
81
- if aggregate.aggregate_version < snapshot.aggregate_version
82
- raise Errors::WrongSnapshotVersionError.new(aggregate, snapshot.aggregate_version)
83
- end
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
@@ -14,7 +14,3 @@ module SandthornDriverSequel
14
14
  end
15
15
  end
16
16
  end
17
-
18
- require "sandthorn_driver_sequel/access/aggregate_access"
19
- require "sandthorn_driver_sequel/access/event_access"
20
- require "sandthorn_driver_sequel/access/snapshot_access"
@@ -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, :url
10
+ attr_reader :driver, :context
6
11
 
7
- def initialize url: nil, context: nil
8
- @driver = SequelDriver.new url: url
12
+ def initialize connection, configuration, context = nil
13
+ @driver = connection
9
14
  @context = context
10
- @url = url
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 aggregate_snapshot, aggregate_id
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(aggregate_id, aggregate_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
- aggregate_version: snapshot[:aggregate_version],
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
- transform_snapshot(snapshot)
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 url: url
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 args = {}
7
- @url = args.fetch(:url)
6
+ def initialize(args = {})
8
7
  Sequel.default_timezone = :utc
9
- @db = Sequel.connect(@url)
8
+ @db = args.fetch(:connection) {
9
+ Sequel.connect(args.fetch(:url))
10
+ }
10
11
  end
11
12
 
12
13
  def execute
@@ -1,3 +1,3 @@
1
1
  module SandthornDriverSequel
2
- VERSION = "2.1.1"
2
+ VERSION = "3.0.0"
3
3
  end
@@ -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[:event_data]
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
- def driver_from_url url: nil, context: nil
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