sandthorn_driver_sequel_2 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.autotest +3 -0
- data/.gitignore +20 -0
- data/.rspec +2 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +4 -0
- data/Gemfile +4 -0
- data/Guardfile +7 -0
- data/LICENSE.txt +22 -0
- data/README.md +37 -0
- data/Rakefile +10 -0
- data/lib/sandthorn_driver_sequel_2/access/event_access.rb +94 -0
- data/lib/sandthorn_driver_sequel_2/access/snapshot_access.rb +88 -0
- data/lib/sandthorn_driver_sequel_2/access.rb +19 -0
- data/lib/sandthorn_driver_sequel_2/errors.rb +49 -0
- data/lib/sandthorn_driver_sequel_2/event_query.rb +68 -0
- data/lib/sandthorn_driver_sequel_2/event_store.rb +138 -0
- data/lib/sandthorn_driver_sequel_2/event_store_context.rb +15 -0
- data/lib/sandthorn_driver_sequel_2/file_output_wrappers/events.rb +37 -0
- data/lib/sandthorn_driver_sequel_2/migration.rb +81 -0
- data/lib/sandthorn_driver_sequel_2/sequel_driver.rb +23 -0
- data/lib/sandthorn_driver_sequel_2/storage.rb +43 -0
- data/lib/sandthorn_driver_sequel_2/utilities/array.rb +13 -0
- data/lib/sandthorn_driver_sequel_2/utilities.rb +1 -0
- data/lib/sandthorn_driver_sequel_2/version.rb +3 -0
- data/lib/sandthorn_driver_sequel_2/wrappers/event_wrapper.rb +12 -0
- data/lib/sandthorn_driver_sequel_2/wrappers/snapshot_wrapper.rb +11 -0
- data/lib/sandthorn_driver_sequel_2/wrappers.rb +2 -0
- data/lib/sandthorn_driver_sequel_2.rb +24 -0
- data/sandthorn_driver_sequel_2.gemspec +41 -0
- data/spec/asking_for_aggregates_to_snapshot_spec.rb +64 -0
- data/spec/benchmark_spec.rb +125 -0
- data/spec/db/.keep +0 -0
- data/spec/driver_interface_spec.rb +31 -0
- data/spec/event_access_spec.rb +100 -0
- data/spec/event_store_file_output_spec.rb +44 -0
- data/spec/event_store_with_context_spec.rb +25 -0
- data/spec/get_events_spec.rb +128 -0
- data/spec/migration_specifying_domain_spec.rb +32 -0
- data/spec/saving_events_spec.rb +90 -0
- data/spec/saving_snapshot_spec.rb +77 -0
- data/spec/snapshot_access_spec.rb +125 -0
- data/spec/spec_helper.rb +31 -0
- data/spec/storage_spec.rb +66 -0
- data/spec/storage_to_file_spec.rb +53 -0
- metadata +334 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8ad8b0f35cb67c5dfa7f950eed9c8d3f2a592a4c
|
4
|
+
data.tar.gz: c3834db70856e0baaf045907d01c457f42eeae5d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8ce499a3eb979ba4c263662afc0475588e74c85f05ca8481d60e7a718ff9ec865838b76c0fcdf78236f0bd75cef593d2fa4af018a69096b5449568b5de4c8d77
|
7
|
+
data.tar.gz: 96b6174602519e18fb8bad0d80393fe40cb40973180c93494d06dadbe85d39e1bc1484f848dd84cc682d6f2b1e2f3ebaa16812b593146f37f3344afe36321993
|
data/.autotest
ADDED
data/.gitignore
ADDED
data/.rspec
ADDED
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
sandthorn_driver_sequel
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby-2.1
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Morgan Hallgren
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
[![Code Climate](https://codeclimate.com/github/Sandthorn/sandthorn_driver_sequel.png)](https://codeclimate.com/github/Sandthorn/sandthorn_driver_sequel)
|
2
|
+
|
3
|
+
# Sandthorn Sequel-driver 2
|
4
|
+
|
5
|
+
A SQL database driver for [Sandthorn](https://github.com/Sandthorn/sandthorn), made with [Sequel](http://sequel.jeremyevans.net/).
|
6
|
+
|
7
|
+
This sequel driver is a rewrite from [sandthorn_driver_sequel](https://github.com/Sandthorn/sandthorn_driver_sequel) and its purpous is to speed up batch imports.
|
8
|
+
|
9
|
+
It has removed the aggregate table and store all aggregate and event data in the events table. Its now possible to output the event data to file and import it to the database after a batch import with the COPY command. This speeds up the import of larger dataset by a magnitude of alot. A note is that the aggregate_version checks has been removed and the user has to make sure that no other write of events are written during batch import.
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
Add this line to your application's Gemfile:
|
14
|
+
|
15
|
+
gem 'sandthorn_driver_sequel_2'
|
16
|
+
|
17
|
+
And then execute:
|
18
|
+
|
19
|
+
$ bundle
|
20
|
+
|
21
|
+
Or install it yourself as:
|
22
|
+
|
23
|
+
$ gem install sandthorn_driver_sequel_2
|
24
|
+
|
25
|
+
## Usage
|
26
|
+
|
27
|
+
Its possible to setup the EventStore with the events_file_path option, this will make the EventStore output all its events to this file path.
|
28
|
+
|
29
|
+
SandthornDriverSequel2.driver_from_url(url: event_store_url, events_file_path: "../events.csv")
|
30
|
+
|
31
|
+
## Contributing
|
32
|
+
|
33
|
+
1. Fork it
|
34
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
35
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
36
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
37
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
module SandthornDriverSequel2
|
2
|
+
class EventAccess < Access::Base
|
3
|
+
# = EventAccess
|
4
|
+
# Reads and writes events.
|
5
|
+
|
6
|
+
def store_events(events)
|
7
|
+
events = Utilities.array_wrap(events)
|
8
|
+
timestamp = Time.now.utc
|
9
|
+
events.each do |event|
|
10
|
+
store_event(timestamp, event)
|
11
|
+
end
|
12
|
+
#puts aggregate.inspect
|
13
|
+
# aggregate.save
|
14
|
+
end
|
15
|
+
|
16
|
+
def find_events_by_aggregate_id(aggregate_id)
|
17
|
+
#aggregate_version = Sequel.qualify(storage.events_table_name, :aggregate_version)
|
18
|
+
#aggregate_aggregate_id = Sequel.qualify(storage.aggregates_table_name, :aggregate_id)
|
19
|
+
#events_aggregate_id = Sequel.qualify(storage.events_table_name, :aggregate_id)
|
20
|
+
wrap(storage.events.where(:aggregate_id => aggregate_id)
|
21
|
+
.select(
|
22
|
+
:sequence_number,
|
23
|
+
:aggregate_id,
|
24
|
+
:aggregate_version,
|
25
|
+
:aggregate_type,
|
26
|
+
:event_name,
|
27
|
+
:event_data,
|
28
|
+
:timestamp)
|
29
|
+
.order(:sequence_number)
|
30
|
+
.all)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Returns events that occurred after the given snapshot
|
34
|
+
def after_snapshot(snapshot)
|
35
|
+
_aggregate_version = snapshot.aggregate_version
|
36
|
+
aggregate_id = snapshot.aggregate_id
|
37
|
+
wrap(storage.events
|
38
|
+
.where(aggregate_id: aggregate_id)
|
39
|
+
.where { aggregate_version > _aggregate_version }.all)
|
40
|
+
end
|
41
|
+
|
42
|
+
def get_events(*args)
|
43
|
+
query_builder = EventQuery.new(storage)
|
44
|
+
query_builder.build(*args)
|
45
|
+
wrap(query_builder.events)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Returns aggregate ids.
|
49
|
+
# @param aggregate_type, optional,
|
50
|
+
def aggregate_ids(aggregate_type: nil)
|
51
|
+
events = storage.events
|
52
|
+
if aggregate_type
|
53
|
+
events = events.where(aggregate_type: aggregate_type.to_s)
|
54
|
+
end
|
55
|
+
events.select_map(:aggregate_id).uniq
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def wrap(arg)
|
61
|
+
events = Utilities.array_wrap(arg)
|
62
|
+
events.map { |e| EventWrapper.new(e.values) }
|
63
|
+
end
|
64
|
+
|
65
|
+
def build_event_data(timestamp, event)
|
66
|
+
{
|
67
|
+
aggregate_id: event.aggregate_id,
|
68
|
+
aggregate_version: event.aggregate_version,
|
69
|
+
aggregate_type: event.aggregate_type.to_s,
|
70
|
+
event_name: event.event_name,
|
71
|
+
event_data: event.event_data,
|
72
|
+
timestamp: timestamp
|
73
|
+
}
|
74
|
+
end
|
75
|
+
|
76
|
+
def check_versions!(aggregate, event)
|
77
|
+
version = aggregate.aggregate_version
|
78
|
+
if version != event[:aggregate_version]
|
79
|
+
raise Errors::ConcurrencyError.new(event, aggregate)
|
80
|
+
end
|
81
|
+
rescue TypeError
|
82
|
+
raise Errors::EventFormatError, "Event has wrong format: #{event.inspect}"
|
83
|
+
end
|
84
|
+
|
85
|
+
def store_event(timestamp, event)
|
86
|
+
event = EventWrapper.new(event)
|
87
|
+
#aggregate.aggregate_version += 1
|
88
|
+
#check_versions!(aggregate, event)
|
89
|
+
data = build_event_data(timestamp, event)
|
90
|
+
storage.events.insert(data)
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module SandthornDriverSequel2
|
2
|
+
class SnapshotAccess < Access::Base
|
3
|
+
|
4
|
+
def find_by_aggregate_id(aggregate_id)
|
5
|
+
#aggregate = aggregates.find_by_aggregate_id(aggregate_id)
|
6
|
+
storage.snapshots.first(aggregate_id: aggregate_id)
|
7
|
+
end
|
8
|
+
|
9
|
+
def find(snapshot_id)
|
10
|
+
storage.snapshots[snapshot_id]
|
11
|
+
end
|
12
|
+
|
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_id, previous_snapshot, snapshot_data)
|
18
|
+
#end
|
19
|
+
end
|
20
|
+
|
21
|
+
def obsolete(aggregate_types: [], max_event_distance: 100)
|
22
|
+
aggregate_types.map!(&:to_s)
|
23
|
+
snapshot_version = Sequel.qualify(storage.snapshots_table_name, :aggregate_version)
|
24
|
+
aggregate_version = Sequel.qualify(storage.aggregates_table_name, :aggregate_version)
|
25
|
+
aggregate_id = Sequel.qualify(storage.aggregates_table_name, :aggregate_id)
|
26
|
+
query = storage.aggregates.left_outer_join(storage.snapshots, aggregate_id: :aggregate_id)
|
27
|
+
query = query.select { (aggregate_version - snapshot_version).as(distance) }
|
28
|
+
query = query.select_append(aggregate_id, :aggregate_type)
|
29
|
+
query = query.where { (aggregate_version - coalesce(snapshot_version, 0)) > max_event_distance }
|
30
|
+
if aggregate_types.any?
|
31
|
+
query = query.where(aggregate_type: aggregate_types)
|
32
|
+
end
|
33
|
+
query.all
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def aggregates
|
39
|
+
@aggregates ||= AggregateAccess.new(storage)
|
40
|
+
end
|
41
|
+
|
42
|
+
def perform_snapshot?(aggregate, snapshot)
|
43
|
+
return true if snapshot.nil?
|
44
|
+
snapshot = SnapshotWrapper.new(snapshot)
|
45
|
+
aggregate.aggregate_version > snapshot.aggregate_version
|
46
|
+
end
|
47
|
+
|
48
|
+
def perform_snapshot(aggregate_id, previous_snapshot, snapshot_data)
|
49
|
+
#check_snapshot_version!(aggregate, snapshot_data)
|
50
|
+
if valid_snapshot?(previous_snapshot)
|
51
|
+
update_snapshot(previous_snapshot, snapshot_data)
|
52
|
+
else
|
53
|
+
insert_snapshot(aggregate_id, snapshot_data)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def insert_snapshot(aggregate_id, snapshot_data)
|
58
|
+
data = build_snapshot(snapshot_data)
|
59
|
+
data[:aggregate_id] = aggregate_id
|
60
|
+
storage.snapshots.insert(data)
|
61
|
+
end
|
62
|
+
|
63
|
+
def build_snapshot(snapshot_data)
|
64
|
+
snapshot_data = SnapshotWrapper.new(snapshot_data)
|
65
|
+
{
|
66
|
+
snapshot_data: snapshot_data.data,
|
67
|
+
aggregate_version: snapshot_data.aggregate_version
|
68
|
+
}
|
69
|
+
end
|
70
|
+
|
71
|
+
def valid_snapshot?(snapshot)
|
72
|
+
snapshot && snapshot[:snapshot_data]
|
73
|
+
end
|
74
|
+
|
75
|
+
def update_snapshot(snapshot, snapshot_data)
|
76
|
+
data = build_snapshot(snapshot_data)
|
77
|
+
storage.snapshots.where(aggregate_id: snapshot.id).update(data)
|
78
|
+
end
|
79
|
+
|
80
|
+
def check_snapshot_version!(aggregate, snapshot_data)
|
81
|
+
snapshot = SnapshotWrapper.new(snapshot_data)
|
82
|
+
if aggregate.aggregate_version < snapshot.aggregate_version
|
83
|
+
raise Errors::WrongSnapshotVersionError.new(aggregate, snapshot.aggregate_version)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module SandthornDriverSequel2
|
2
|
+
module Access
|
3
|
+
class Base
|
4
|
+
# = Access::Base
|
5
|
+
# Inheriting classes use +storage+ to provide access to a
|
6
|
+
# particular database model/table.
|
7
|
+
def initialize(storage)
|
8
|
+
@storage = storage
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
attr_reader :storage
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
require "sandthorn_driver_sequel_2/access/event_access"
|
19
|
+
require "sandthorn_driver_sequel_2/access/snapshot_access"
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module SandthornDriverSequel2::Errors
|
2
|
+
Error = Class.new(StandardError)
|
3
|
+
InternalError = Class.new(Error)
|
4
|
+
NoAggregateError = Class.new(Error)
|
5
|
+
EventFormatError = Class.new(Error)
|
6
|
+
|
7
|
+
class ConcurrencyError < Error
|
8
|
+
attr_reader :event, :aggregate
|
9
|
+
def initialize(event, aggregate)
|
10
|
+
@event = event
|
11
|
+
@aggregate = aggregate
|
12
|
+
super(create_message)
|
13
|
+
end
|
14
|
+
|
15
|
+
def create_message
|
16
|
+
"#{aggregate.aggregate_type} with id #{aggregate.aggregate_id}: " +
|
17
|
+
"expected event with version #{aggregate.aggregate_version}, but got #{event.aggregate_version}"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class WrongAggregateVersionError < Error;
|
22
|
+
def initialize(aggregate, version)
|
23
|
+
@aggregate = aggregate
|
24
|
+
@version = version
|
25
|
+
super(create_message)
|
26
|
+
end
|
27
|
+
|
28
|
+
def create_message
|
29
|
+
"#{@aggregate[:aggregate_type]} with id #{@aggregate[:aggregate_id]}" +
|
30
|
+
" should be at version #{@version}" +
|
31
|
+
" but was #{@aggregate[:aggregate_version]} in the event store."
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class WrongSnapshotVersionError < Error
|
36
|
+
attr_reader :aggregate, :version
|
37
|
+
def initialize(aggregate, version)
|
38
|
+
@aggregate = aggregate
|
39
|
+
@version = version
|
40
|
+
super(create_message)
|
41
|
+
end
|
42
|
+
|
43
|
+
def create_message
|
44
|
+
"#{aggregate[:aggregate_type]} with id #{aggregate[:aggregate_id]}: tried to save snapshot with version "+
|
45
|
+
"#{version}, but current version is at #{aggregate[:aggregate_version]}"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module SandthornDriverSequel2
|
2
|
+
class EventQuery
|
3
|
+
def initialize(storage)
|
4
|
+
@storage = storage
|
5
|
+
end
|
6
|
+
|
7
|
+
def build(
|
8
|
+
aggregate_types: [],
|
9
|
+
take: 0,
|
10
|
+
after_sequence_number: 0)
|
11
|
+
|
12
|
+
aggregate_types.map!(&:to_s)
|
13
|
+
|
14
|
+
query = storage.events
|
15
|
+
query = add_aggregate_types(query, aggregate_types)
|
16
|
+
query = add_sequence_number(query, after_sequence_number)
|
17
|
+
query = add_select(query)
|
18
|
+
query = add_limit(query, take)
|
19
|
+
@query = query.order(:sequence_number)
|
20
|
+
end
|
21
|
+
|
22
|
+
def events
|
23
|
+
@query.all
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
attr_reader :storage
|
29
|
+
|
30
|
+
def add_limit(query, take)
|
31
|
+
if take > 0
|
32
|
+
query.limit(take)
|
33
|
+
else
|
34
|
+
query
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def add_select(query)
|
39
|
+
query.select(*select_columns)
|
40
|
+
end
|
41
|
+
|
42
|
+
def select_columns
|
43
|
+
aggregate_version = Sequel.qualify(storage.events_table_name, :aggregate_version)
|
44
|
+
aggregate_id = Sequel.qualify(storage.events_table_name, :aggregate_id)
|
45
|
+
[
|
46
|
+
:aggregate_type,
|
47
|
+
aggregate_version,
|
48
|
+
aggregate_id,
|
49
|
+
:sequence_number,
|
50
|
+
:event_name,
|
51
|
+
:event_data,
|
52
|
+
:timestamp
|
53
|
+
]
|
54
|
+
end
|
55
|
+
|
56
|
+
def add_sequence_number(query, after_sequence_number)
|
57
|
+
query.where { sequence_number > after_sequence_number }
|
58
|
+
end
|
59
|
+
|
60
|
+
def add_aggregate_types(query, aggregate_types)
|
61
|
+
if aggregate_types.any?
|
62
|
+
query = query.where( :aggregate_type => aggregate_types )
|
63
|
+
end
|
64
|
+
query
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
module SandthornDriverSequel2
|
2
|
+
class EventStore
|
3
|
+
include EventStoreContext
|
4
|
+
|
5
|
+
attr_reader :driver, :context, :url
|
6
|
+
|
7
|
+
def initialize url: nil, context: nil, events_file_path: nil
|
8
|
+
@driver = SequelDriver.new url: url
|
9
|
+
@context = context
|
10
|
+
@url = url
|
11
|
+
|
12
|
+
driver.execute do |db|
|
13
|
+
@storage = Storage.new(db, context, events_file_path)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def save_events events, aggregate_id, class_name
|
18
|
+
driver.execute_in_transaction do |db|
|
19
|
+
event_access = get_event_access(db)
|
20
|
+
events = events.map { |event| event[:aggregate_type] = class_name; event[:aggregate_id] = aggregate_id; event;}
|
21
|
+
event_access.store_events(events)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def get_aggregate_events(aggregate_id)
|
26
|
+
driver.execute do |db|
|
27
|
+
events = get_event_access(db)
|
28
|
+
events.find_events_by_aggregate_id(aggregate_id)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def save_snapshot aggregate_snapshot, aggregate_id
|
33
|
+
driver.execute_in_transaction do |db|
|
34
|
+
snapshot_access = get_snapshot_access(db)
|
35
|
+
snapshot_access.record_snapshot(aggregate_id, aggregate_snapshot)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# If the aggregate has a snapshot, return events starting from the snapshots.
|
40
|
+
# Otherwise, return all events.
|
41
|
+
# TODO: needs a better name
|
42
|
+
def get_aggregate_events_from_snapshot(aggregate_id)
|
43
|
+
driver.execute do |db|
|
44
|
+
#snapshots = get_snapshot_access(db)
|
45
|
+
event_access = get_event_access(db)
|
46
|
+
snapshot = false#snapshots.find_by_aggregate_id(aggregate_id)
|
47
|
+
if snapshot
|
48
|
+
events = event_access.after_snapshot(snapshot)
|
49
|
+
snapshot_event = build_snapshot_event(snapshot)
|
50
|
+
events.unshift(snapshot_event)
|
51
|
+
else
|
52
|
+
event_access.find_events_by_aggregate_id(aggregate_id)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def build_snapshot_event(snapshot)
|
58
|
+
{
|
59
|
+
aggregate_version: snapshot[:aggregate_version],
|
60
|
+
event_data: snapshot[:snapshot_data],
|
61
|
+
event_name: "aggregate_set_from_snapshot"
|
62
|
+
}
|
63
|
+
end
|
64
|
+
|
65
|
+
def get_aggregate aggregate_id, *class_name
|
66
|
+
warn(":get_aggregate is deprecated. Use :get_aggregate_events_from_snapshot")
|
67
|
+
get_aggregate_events_from_snapshot(aggregate_id)
|
68
|
+
end
|
69
|
+
|
70
|
+
def get_aggregate_ids(aggregate_type: nil)
|
71
|
+
driver.execute do |db|
|
72
|
+
access = get_event_access(db)
|
73
|
+
access.aggregate_ids(aggregate_type: aggregate_type)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def get_aggregate_list_by_typename(type)
|
78
|
+
warn(":get_aggregate_list_by_typenames is deprecated. Use :get_aggregate_ids")
|
79
|
+
get_aggregate_ids(type: type)
|
80
|
+
end
|
81
|
+
|
82
|
+
# def get_all_types
|
83
|
+
# driver.execute do |db|
|
84
|
+
# access = get_aggregate_access(db)
|
85
|
+
# access.aggregate_types
|
86
|
+
# end
|
87
|
+
# end
|
88
|
+
|
89
|
+
def get_snapshot aggregate_id
|
90
|
+
driver.execute do |db|
|
91
|
+
snapshots = get_snapshot_access(db)
|
92
|
+
snapshot = snapshots.find_by_aggregate_id(aggregate_id)
|
93
|
+
transform_snapshot(snapshot)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def get_events(*args)
|
98
|
+
driver.execute do |db|
|
99
|
+
event_access = get_event_access(db)
|
100
|
+
event_access.get_events(*args)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def get_new_events_after_event_id_matching_classname event_id, class_name, take: 0
|
105
|
+
get_events(after_sequence_number: event_id, aggregate_types: Utilities.array_wrap(class_name), take: take)
|
106
|
+
end
|
107
|
+
|
108
|
+
def obsolete_snapshots(*args)
|
109
|
+
driver.execute do |db|
|
110
|
+
snapshots = get_snapshot_access(db)
|
111
|
+
snapshots.obsolete(*args)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
private
|
116
|
+
|
117
|
+
def transform_snapshot(snapshot)
|
118
|
+
{
|
119
|
+
aggregate_version: snapshot.aggregate_version,
|
120
|
+
event_data: snapshot.snapshot_data
|
121
|
+
}
|
122
|
+
end
|
123
|
+
|
124
|
+
def get_event_access(db)
|
125
|
+
EventAccess.new(storage(db))
|
126
|
+
end
|
127
|
+
|
128
|
+
def get_snapshot_access(db)
|
129
|
+
SnapshotAccess.new(storage(db))
|
130
|
+
end
|
131
|
+
|
132
|
+
def storage(db)
|
133
|
+
@storage
|
134
|
+
#Storage.new(db, context, file_output: @file_output)
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module SandthornDriverSequel2
|
2
|
+
module EventStoreContext
|
3
|
+
attr_reader :context
|
4
|
+
def events_table_name
|
5
|
+
with_context_if_exists :events
|
6
|
+
end
|
7
|
+
def snapshots_table_name
|
8
|
+
with_context_if_exists :snapshots
|
9
|
+
end
|
10
|
+
def with_context_if_exists name
|
11
|
+
name = "#{context}_#{name}".to_sym if context
|
12
|
+
name
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
module SandthornDriverSequel2
|
4
|
+
module FileOutputWrapper
|
5
|
+
class Events
|
6
|
+
extend Forwardable
|
7
|
+
def initialize event_file, sequence_number
|
8
|
+
@event_file = event_file
|
9
|
+
@sequence_number = sequence_number
|
10
|
+
end
|
11
|
+
|
12
|
+
def events sequel
|
13
|
+
@sequel = sequel
|
14
|
+
self
|
15
|
+
end
|
16
|
+
|
17
|
+
def insert *args
|
18
|
+
args.each do |event|
|
19
|
+
@sequence_number += 1
|
20
|
+
event_data = String.new("#{event[:event_data]}")
|
21
|
+
event_data = " #{event_data}" if event_data =~ /^[\n\r]/
|
22
|
+
@event_file.puts "#{@sequence_number};#{event[:aggregate_id]};#{event[:aggregate_version]};#{event[:aggregate_type]};#{event[:event_name]};#{event_data};#{event[:timestamp]}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def_delegators :@sequel, :first, :where, :join, :select, :all
|
27
|
+
|
28
|
+
def save *args
|
29
|
+
@event_file.write args
|
30
|
+
end
|
31
|
+
|
32
|
+
def flush
|
33
|
+
@event_file.flush
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|