sandthorn_driver_event_store 0.0.1
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 +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 +5 -0
- data/Guardfile +7 -0
- data/LICENSE.txt +22 -0
- data/README.md +42 -0
- data/Rakefile +10 -0
- data/lib/sandthorn_driver_event_store/access/event_access.rb +57 -0
- data/lib/sandthorn_driver_event_store/access.rb +18 -0
- data/lib/sandthorn_driver_event_store/errors.rb +49 -0
- data/lib/sandthorn_driver_event_store/event_query.rb +65 -0
- data/lib/sandthorn_driver_event_store/event_store.rb +48 -0
- data/lib/sandthorn_driver_event_store/event_store_driver.rb +23 -0
- data/lib/sandthorn_driver_event_store/utilities/array.rb +13 -0
- data/lib/sandthorn_driver_event_store/utilities.rb +1 -0
- data/lib/sandthorn_driver_event_store/version.rb +3 -0
- data/lib/sandthorn_driver_event_store/wrappers/event_wrapper.rb +12 -0
- data/lib/sandthorn_driver_event_store/wrappers.rb +1 -0
- data/lib/sandthorn_driver_event_store.rb +18 -0
- data/sandthorn_driver_event_store.gemspec +39 -0
- data/spec/driver_interface_spec.rb +24 -0
- data/spec/event_access_spec.rb +68 -0
- data/spec/get_events_spec.rb +129 -0
- data/spec/in_memory_es.rb +95 -0
- data/spec/in_memory_event_store_driver.rb +16 -0
- data/spec/saving_events_spec.rb +33 -0
- data/spec/spec_helper.rb +33 -0
- metadata +265 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 72f4778deae2b0d24a481a8665fcdbb3ee98b55a
|
4
|
+
data.tar.gz: b6474c0758bf60c41f95b4189229dd364dcc4bed
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a693d6007d3b25e7d685c97458cf7ef58e02a4b66e376adb27238c6a88d706fc0203c01dcc21e555d8dc77edd914a448d52d880a78207ca23342c520c5251686
|
7
|
+
data.tar.gz: 374ab395ffefc0f14d3d55922656db88ff2eaba211aafb2616785629af92d0c07e18fdfdf6aaed2f765512075ea45c21d30e2dffb3acaa484e08ab46fa938cf9
|
data/.autotest
ADDED
data/.gitignore
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
*.sqlite3
|
19
|
+
.idea
|
20
|
+
spec/db_file/test_events.csv
|
data/.rspec
ADDED
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
sandthorn_driver_event_store
|
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,42 @@
|
|
1
|
+
# Sandthorn Event Store driver
|
2
|
+
|
3
|
+
A [Event Store](geteventstore.com) driver for [Sandthorn](https://github.com/Sandthorn/sandthorn).
|
4
|
+
|
5
|
+
This driver is a write upon [http_eventstore](https://github.com/arkency/http_eventstore) from [Arkency](http://arkency.com)
|
6
|
+
|
7
|
+
Currently only a subset of functionallity is implemented contra the [sandthorn_sequel_driver](https://github.com/Sandthorn/sandthorn_sequel_driver)
|
8
|
+
|
9
|
+
* save_events
|
10
|
+
* find
|
11
|
+
|
12
|
+
## Installation
|
13
|
+
|
14
|
+
Add this line to your application's Gemfile:
|
15
|
+
|
16
|
+
gem 'sandthorn_driver_event_store'
|
17
|
+
|
18
|
+
And then execute:
|
19
|
+
|
20
|
+
$ bundle
|
21
|
+
|
22
|
+
Or install it yourself as:
|
23
|
+
|
24
|
+
$ gem install sandthorn_driver_event_store
|
25
|
+
|
26
|
+
## Usage
|
27
|
+
|
28
|
+
SandthornDriverEventStore.driver host: "localhost", port: 2113
|
29
|
+
|
30
|
+
## Todo
|
31
|
+
|
32
|
+
* All - Get all events based on Aggregate type (Class)
|
33
|
+
* Get events - Functionallity for [Sandthorn Sequel Projection](https://github.com/Sandthorn/sandthorn_sequel_projection)
|
34
|
+
* Implement snapshoting, now all event of an aggregate has to be fetched to build the aggregate.
|
35
|
+
|
36
|
+
## Contributing
|
37
|
+
|
38
|
+
1. Fork it
|
39
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
40
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
41
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
42
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
module SandthornDriverEventStore
|
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
|
+
stream_name = events.first[:aggregate_id]
|
10
|
+
|
11
|
+
event_store_events = events.map do |event|
|
12
|
+
build_event_data(timestamp, event)
|
13
|
+
end
|
14
|
+
|
15
|
+
if event_store_events.any?
|
16
|
+
expected_version = event_store_events.first[:position] > 0 ? event_store_events.first[:position]-1 : nil
|
17
|
+
storage.append_to_stream(stream_name, event_store_events, expected_version)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def find_events_by_aggregate_id(aggregate_id)
|
22
|
+
return storage.read_all_events_forward(aggregate_id).map { |event|
|
23
|
+
{
|
24
|
+
event_args: JSON.parse(event.data.to_json, symbolize_names: true),
|
25
|
+
aggregate_id: event.stream_name,
|
26
|
+
aggregate_version: event.position+1,
|
27
|
+
event_name: event.type
|
28
|
+
}
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
def get_events(*args)
|
33
|
+
query_builder = EventQuery.new(storage)
|
34
|
+
query_builder.build(*args)
|
35
|
+
wrap(query_builder.events)
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def wrap(arg)
|
41
|
+
events = Utilities.array_wrap(arg)
|
42
|
+
events.map { |e| EventWrapper.new(e.values) }
|
43
|
+
end
|
44
|
+
|
45
|
+
def build_event_data(timestamp, event)
|
46
|
+
{
|
47
|
+
event_type: event[:event_name].to_s,
|
48
|
+
data: event[:event_args],
|
49
|
+
event_id: SecureRandom.uuid,
|
50
|
+
id: event[:aggregate_id],
|
51
|
+
position: event[:aggregate_version]-1,
|
52
|
+
created_time: timestamp
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module SandthornDriverEventStore
|
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_event_store/access/event_access"
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module SandthornDriverEventStore::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,65 @@
|
|
1
|
+
module SandthornDriverEventStore
|
2
|
+
class EventQuery
|
3
|
+
def initialize(storage)
|
4
|
+
@storage = storage
|
5
|
+
end
|
6
|
+
|
7
|
+
def build(
|
8
|
+
stream_name:,
|
9
|
+
take: 0,
|
10
|
+
after_sequence_number: 0)
|
11
|
+
|
12
|
+
query = storage.events
|
13
|
+
query = add_sequence_number(query, after_sequence_number)
|
14
|
+
query = add_select(query)
|
15
|
+
query = add_limit(query, take)
|
16
|
+
@query = query.order(:sequence_number)
|
17
|
+
end
|
18
|
+
|
19
|
+
def events
|
20
|
+
@query.all
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
attr_reader :storage
|
26
|
+
|
27
|
+
def add_limit(query, take)
|
28
|
+
if take > 0
|
29
|
+
query.limit(take)
|
30
|
+
else
|
31
|
+
query
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def add_select(query)
|
36
|
+
query.select(*select_columns)
|
37
|
+
end
|
38
|
+
|
39
|
+
def select_columns
|
40
|
+
aggregate_version = Sequel.qualify(storage.events_table_name, :aggregate_version)
|
41
|
+
aggregate_id = Sequel.qualify(storage.events_table_name, :aggregate_id)
|
42
|
+
[
|
43
|
+
:aggregate_type,
|
44
|
+
aggregate_version,
|
45
|
+
aggregate_id,
|
46
|
+
:sequence_number,
|
47
|
+
:event_name,
|
48
|
+
:event_data,
|
49
|
+
:timestamp
|
50
|
+
]
|
51
|
+
end
|
52
|
+
|
53
|
+
def add_sequence_number(query, after_sequence_number)
|
54
|
+
query.where { sequence_number > after_sequence_number }
|
55
|
+
end
|
56
|
+
|
57
|
+
def add_aggregate_types(query, aggregate_types)
|
58
|
+
if aggregate_types.any?
|
59
|
+
query = query.where( :aggregate_type => aggregate_types )
|
60
|
+
end
|
61
|
+
query
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module SandthornDriverEventStore
|
2
|
+
class EventStore
|
3
|
+
|
4
|
+
attr_reader :driver
|
5
|
+
|
6
|
+
def initialize event_store_driver:
|
7
|
+
@driver = event_store_driver
|
8
|
+
driver.execute do |db|
|
9
|
+
@storage = db
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def save_events events, aggregate_id, class_name
|
14
|
+
driver.execute do |db|
|
15
|
+
event_access = get_event_access(db)
|
16
|
+
events = events.map { |event| event[:aggregate_type] = class_name; event[:aggregate_id] = aggregate_id; event;}
|
17
|
+
event_access.store_events(events)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def find aggregate_id
|
22
|
+
driver.execute do |db|
|
23
|
+
event_access = get_event_access(db)
|
24
|
+
event_access.find_events_by_aggregate_id(aggregate_id)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def all aggregate_type
|
29
|
+
raise :NotImplemented
|
30
|
+
end
|
31
|
+
|
32
|
+
def get_events(*args)
|
33
|
+
raise :NotImplemented
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def get_event_access(db)
|
40
|
+
EventAccess.new(storage(db))
|
41
|
+
end
|
42
|
+
|
43
|
+
def storage(db)
|
44
|
+
@storage
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'http_eventstore'
|
2
|
+
|
3
|
+
module SandthornDriverEventStore
|
4
|
+
class EventStoreDriver
|
5
|
+
|
6
|
+
def initialize host:, port:, page_size:
|
7
|
+
|
8
|
+
@connection = HttpEventstore::Connection.new do |config|
|
9
|
+
#default value is '127.0.0.1'
|
10
|
+
config.endpoint = host
|
11
|
+
#default value is 2113
|
12
|
+
config.port = port
|
13
|
+
#default value is 20 entries per page
|
14
|
+
config.page_size = page_size
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def execute
|
19
|
+
yield @connection
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require "sandthorn_driver_event_store/utilities/array"
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
module SandthornDriverEventStore
|
3
|
+
class EventWrapper < SimpleDelegator
|
4
|
+
|
5
|
+
[:aggregate_version, :event_name, :event_data, :timestamp, :aggregate_id, :aggregate_type].each do |attribute|
|
6
|
+
define_method(attribute) do
|
7
|
+
fetch(attribute)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require "sandthorn_driver_event_store/wrappers/event_wrapper"
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require "sandthorn_driver_event_store/version"
|
2
|
+
require "sandthorn_driver_event_store/utilities"
|
3
|
+
require "sandthorn_driver_event_store/wrappers"
|
4
|
+
require "sandthorn_driver_event_store/event_query"
|
5
|
+
require "sandthorn_driver_event_store/access"
|
6
|
+
require 'sandthorn_driver_event_store/event_store'
|
7
|
+
require 'sandthorn_driver_event_store/event_store_driver'
|
8
|
+
require 'sandthorn_driver_event_store/errors'
|
9
|
+
|
10
|
+
module SandthornDriverEventStore
|
11
|
+
class << self
|
12
|
+
def driver host:, port:, page_size: 20
|
13
|
+
driver = SandthornDriverEventStore::EventStoreDriver.new host: host, port: port, page_size: page_size
|
14
|
+
return SandthornDriverEventStore::EventStore.new event_store_driver: driver
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'sandthorn_driver_event_store/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "sandthorn_driver_event_store"
|
8
|
+
spec.version = SandthornDriverEventStore::VERSION
|
9
|
+
spec.authors = ["Morgan Hallgren"]
|
10
|
+
spec.email = ["morgan.hallgren@gmail.com"]
|
11
|
+
spec.description = %q{Event Store driver for Sandthorn}
|
12
|
+
spec.summary = %q{Event Store driver for Sandthorn}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.required_ruby_version = ">= 2.0"
|
17
|
+
|
18
|
+
spec.files = `git ls-files`.split($/)
|
19
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
20
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
21
|
+
spec.require_paths = ["lib"]
|
22
|
+
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
24
|
+
spec.add_development_dependency "rake"
|
25
|
+
|
26
|
+
spec.add_development_dependency "rspec"
|
27
|
+
spec.add_development_dependency "gem-release"
|
28
|
+
spec.add_development_dependency "pry"
|
29
|
+
spec.add_development_dependency "pry-doc"
|
30
|
+
spec.add_development_dependency "awesome_print"
|
31
|
+
spec.add_development_dependency "autotest-standalone"
|
32
|
+
spec.add_development_dependency "uuidtools"
|
33
|
+
spec.add_development_dependency "ruby-beautify"
|
34
|
+
spec.add_development_dependency "msgpack"
|
35
|
+
spec.add_development_dependency "snappy"
|
36
|
+
spec.add_development_dependency "guard-rspec"
|
37
|
+
|
38
|
+
#spec.add_runtime_dependency "http_eventstore"
|
39
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module SandthornDriverEventStore
|
4
|
+
describe EventStore do
|
5
|
+
before(:each) { prepare_for_test }
|
6
|
+
context "interface structure" do
|
7
|
+
let(:subject) { event_store }
|
8
|
+
methods = [
|
9
|
+
:save_events,
|
10
|
+
:find,
|
11
|
+
:all,
|
12
|
+
:get_events,
|
13
|
+
:driver
|
14
|
+
]
|
15
|
+
|
16
|
+
methods.each do |method|
|
17
|
+
it "responds to #{method}" do
|
18
|
+
expect(subject).to respond_to(method)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module SandthornDriverEventStore
|
4
|
+
describe EventAccess do
|
5
|
+
|
6
|
+
before do
|
7
|
+
prepare_for_test
|
8
|
+
end
|
9
|
+
|
10
|
+
let(:db) { Sequel.connect(event_store_url)}
|
11
|
+
let(:aggregate_id) { SecureRandom.uuid }
|
12
|
+
let(:aggregate) do
|
13
|
+
aggregate_access.register_aggregate(aggregate_id, "foo")
|
14
|
+
end
|
15
|
+
let(:storage) { return event_store_driver.execute { |db| return db; } }
|
16
|
+
let(:access) { EventAccess.new(storage) }
|
17
|
+
|
18
|
+
let(:events) do
|
19
|
+
[
|
20
|
+
{
|
21
|
+
aggregate_version: 1,
|
22
|
+
aggregate_id: aggregate_id,
|
23
|
+
aggregate_type: "Foo",
|
24
|
+
event_name: "new",
|
25
|
+
event_args: {test: "new_data"}
|
26
|
+
},{
|
27
|
+
aggregate_version: 2,
|
28
|
+
aggregate_id: aggregate_id,
|
29
|
+
aggregate_type: "Foo",
|
30
|
+
event_name: "foo",
|
31
|
+
event_args: {test: "foo_data"}
|
32
|
+
}
|
33
|
+
]
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "#store_events" do
|
37
|
+
|
38
|
+
it "handles both arrays and single events" do
|
39
|
+
access.store_events(events[0])
|
40
|
+
events = access.find_events_by_aggregate_id(aggregate_id)
|
41
|
+
expect(events.length).to eq(1)
|
42
|
+
end
|
43
|
+
|
44
|
+
context "when the aggregate version of an event is incorrect" do
|
45
|
+
it "throws an error" do
|
46
|
+
event = { aggregate_version: 100, aggregate_id: aggregate_id, aggregate_type: "Foo", event_name: "new", event_data: "noop" }
|
47
|
+
expect { access.store_events([event])}.to raise_error
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "#find_events_by_aggregate_id" do
|
53
|
+
context "when there are events" do
|
54
|
+
it "returns correct events" do
|
55
|
+
access.store_events(events)
|
56
|
+
|
57
|
+
stored_events = access.find_events_by_aggregate_id(aggregate_id)
|
58
|
+
expect(stored_events.size).to eq(events.size)
|
59
|
+
expect(stored_events).to all(respond_to(:merge))
|
60
|
+
stored_events.each { |event|
|
61
|
+
expect(event[:aggregate_id]).to eql aggregate_id
|
62
|
+
}
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
# require 'spec_helper'
|
2
|
+
# require 'securerandom'
|
3
|
+
|
4
|
+
# module SandthornDriverEventStore
|
5
|
+
# describe EventStore do
|
6
|
+
# before(:each) { prepare_for_test }
|
7
|
+
# let(:test_events_a) do
|
8
|
+
# e = []
|
9
|
+
# e << {aggregate_version: 1, event_name: "new", event_data: "---\n:method_name: new\n:method_args: []\n:attribute_deltas:\n- :attribute_name: :@aggregate_id\n :old_value: \n :new_value: 0a74e545-be84-4506-8b0a-73e947856327\n"}
|
10
|
+
# e << {aggregate_version: 2, event_name: "foo", event_data: "A2"}
|
11
|
+
# e << {aggregate_version: 3, event_name: "bard", event_data: "A3"}
|
12
|
+
# end
|
13
|
+
# let(:aggregate_id_a) { SecureRandom.uuid }
|
14
|
+
# let(:test_events_b) do
|
15
|
+
# e = []
|
16
|
+
# e << {aggregate_version: 1, event_name: "new", event_data: "B1" }
|
17
|
+
# e << {aggregate_version: 2, event_name: "foo", event_data: "B2"}
|
18
|
+
# e << {aggregate_version: 3, event_name: "bar", event_data: "B3"}
|
19
|
+
# end
|
20
|
+
# let(:aggregate_id_b) { SecureRandom.uuid }
|
21
|
+
# let(:test_events_c) do
|
22
|
+
# e = []
|
23
|
+
# e << {aggregate_version: 1, event_name: "new", event_data: "C1" }
|
24
|
+
# end
|
25
|
+
# let(:test_events_c_2) do
|
26
|
+
# e = []
|
27
|
+
# e << {aggregate_version: 2, event_name: "flubber", event_data: "C2" }
|
28
|
+
# end
|
29
|
+
# let(:aggregate_id_c) { SecureRandom.uuid }
|
30
|
+
# before(:each) do
|
31
|
+
# event_store.save_events test_events_a, aggregate_id_a, SandthornDriverEventStore::EventStore
|
32
|
+
# event_store.save_events test_events_c, aggregate_id_c, String
|
33
|
+
# event_store.save_events test_events_b, aggregate_id_b, SandthornDriverEventStore::EventStore
|
34
|
+
# event_store.save_events test_events_c_2, aggregate_id_c, String
|
35
|
+
# end
|
36
|
+
|
37
|
+
# let(:event) { event_store.find(aggregate_id_c).first }
|
38
|
+
|
39
|
+
# it "returns events that can be merged" do
|
40
|
+
# expect(event).to respond_to(:merge)
|
41
|
+
# end
|
42
|
+
|
43
|
+
# context "when using get_events" do
|
44
|
+
# context "and using take" do
|
45
|
+
# let(:events) {event_store.get_events stream_name: "test", after_sequence_number: nil, take: 2}
|
46
|
+
# it "should find 2 events" do
|
47
|
+
# expect(events.length).to eql 2
|
48
|
+
# end
|
49
|
+
# end
|
50
|
+
# context "and combining args" do
|
51
|
+
# let(:events) do
|
52
|
+
# all = event_store.get_events after_sequence_number: 0
|
53
|
+
# first_seq_number = all[0][:sequence_number]
|
54
|
+
# event_store.get_events after_sequence_number: first_seq_number, take: 100
|
55
|
+
# end
|
56
|
+
# it "should find 7 events" do
|
57
|
+
# expect(events.length).to eql 7
|
58
|
+
# end
|
59
|
+
|
60
|
+
# end
|
61
|
+
# context "and getting events for SandthornDriverEventStore::EventStore, and String after 0" do
|
62
|
+
# let(:events) {event_store.get_events after_sequence_number: 0, aggregate_types: [SandthornDriverEventStore::EventStore, String]}
|
63
|
+
# it "should find 5 events" do
|
64
|
+
# expect(events.length).to eql 5
|
65
|
+
# end
|
66
|
+
# it "should be in sequence_number order" do
|
67
|
+
# check = 0
|
68
|
+
# events.each { |e| expect(e[:sequence_number]).to be > check; check = e[:sequence_number] }
|
69
|
+
# end
|
70
|
+
# it "should contain only events for aggregate_id_a and aggregate_id_c" do
|
71
|
+
# events.each { |e| expect([aggregate_id_a, aggregate_id_c].include?(e[:aggregate_id])).to be_truthy }
|
72
|
+
# end
|
73
|
+
# end
|
74
|
+
# context "and getting events for SandthornDriverEventStore::EventStore after 0" do
|
75
|
+
# let(:events) {event_store.get_events after_sequence_number: 0, aggregate_types: [SandthornDriverEventStore::EventStore]}
|
76
|
+
# it "should find 3 events" do
|
77
|
+
# expect(events.length).to eql 3
|
78
|
+
# end
|
79
|
+
# it "should be in sequence_number order" do
|
80
|
+
# check = 0
|
81
|
+
# events.each { |e| expect(e[:sequence_number]).to be > check; check = e[:sequence_number] }
|
82
|
+
# end
|
83
|
+
# it "should contain only events for aggregate_id_a" do
|
84
|
+
# events.each { |e| expect(e[:aggregate_id]).to eql aggregate_id_a }
|
85
|
+
# end
|
86
|
+
# end
|
87
|
+
# end
|
88
|
+
# context "when using :get_new_events_after_event_id_matching_classname to get events" do
|
89
|
+
# context "and getting events for SandthornDriverEventStore::EventStore after 0" do
|
90
|
+
# let(:events) {event_store.get_new_events_after_event_id_matching_classname 0, SandthornDriverEventStore::EventStore}
|
91
|
+
# it "should find 3 events" do
|
92
|
+
# expect(events.length).to eql 3
|
93
|
+
# end
|
94
|
+
# it "should be in sequence_number order" do
|
95
|
+
# check = 0
|
96
|
+
# events.each { |e| expect(e[:sequence_number]).to be > check; check = e[:sequence_number] }
|
97
|
+
# end
|
98
|
+
# it "should contain only events for aggregate_id_a" do
|
99
|
+
# events.each { |e| expect(e[:aggregate_id]).to eql aggregate_id_a }
|
100
|
+
# end
|
101
|
+
# it "should be able to get events after a sequence number" do
|
102
|
+
# new_from = events[1][:sequence_number]
|
103
|
+
# ev = event_store.get_new_events_after_event_id_matching_classname new_from, SandthornDriverEventStore::EventStore
|
104
|
+
# expect(ev.last[:aggregate_version]).to eql 3
|
105
|
+
# expect(ev.length).to eql 1
|
106
|
+
# end
|
107
|
+
# it "should be able to limit the number of results" do
|
108
|
+
# ev = event_store.get_new_events_after_event_id_matching_classname 0, SandthornDriverEventStore::EventStore, take: 2
|
109
|
+
# expect(ev.length).to eql 2
|
110
|
+
# expect(ev.last[:aggregate_version]).to eql 2
|
111
|
+
# end
|
112
|
+
# end
|
113
|
+
# context "and getting events for String after 0" do
|
114
|
+
# let(:events) {event_store.get_new_events_after_event_id_matching_classname 0, "String"}
|
115
|
+
# it "should find 3 events" do
|
116
|
+
# expect(events.length).to eql 2
|
117
|
+
# end
|
118
|
+
# it "should be in sequence_number order" do
|
119
|
+
# check = 0
|
120
|
+
# events.each { |e| expect(e[:sequence_number]).to be > check; check = e[:sequence_number] }
|
121
|
+
# end
|
122
|
+
# it "should contain only events for aggregate_id_c" do
|
123
|
+
# events.each { |e| expect(e[:aggregate_id]).to eql aggregate_id_c }
|
124
|
+
# end
|
125
|
+
# end
|
126
|
+
# end
|
127
|
+
|
128
|
+
# end
|
129
|
+
# end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
#Copied from 'http_eventstore' spec
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module HttpEventstore
|
6
|
+
class InMemoryEs
|
7
|
+
|
8
|
+
def initialize(endpoint, port, page_size)
|
9
|
+
@endpoint = Endpoint.new(endpoint, port)
|
10
|
+
@page_size = page_size
|
11
|
+
@event_store = {}
|
12
|
+
end
|
13
|
+
attr_reader :endpoint, :page_size, :event_store
|
14
|
+
|
15
|
+
def append_to_stream(stream_name, event_data, expected_version = nil)
|
16
|
+
unless event_store.key?(stream_name)
|
17
|
+
event_store[stream_name] = []
|
18
|
+
end
|
19
|
+
|
20
|
+
id = event_store[stream_name].length
|
21
|
+
event_store[stream_name].unshift({'eventId' => event_data.event_id, 'data' => event_data.data.to_json, 'eventType' => event_data.type, 'positionEventNumber' => id})
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
def append_events_to_stream(stream_name, events_data=[], expected_version = nil)
|
26
|
+
unless event_store.key?(stream_name)
|
27
|
+
event_store[stream_name] = []
|
28
|
+
end
|
29
|
+
events_data.each do |event_data|
|
30
|
+
id = event_store[stream_name].length
|
31
|
+
event_store[stream_name].unshift({'eventId' => event_data.event_id, 'data' => event_data.data.to_json, 'eventType' => event_data.type, 'positionEventNumber' => id})
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def delete_stream(stream_name, hard_delete)
|
36
|
+
event_store.delete(stream_name)
|
37
|
+
end
|
38
|
+
|
39
|
+
def read_stream_page(uri)
|
40
|
+
params = uri.scan(/\/(\w+)\/(\d+)/)
|
41
|
+
stream_name = params[0][0]
|
42
|
+
last_index = params[0][1].to_i
|
43
|
+
direction = params[1][0]
|
44
|
+
count = params[1][1].to_i
|
45
|
+
if direction == 'next'
|
46
|
+
read_stream_backward(stream_name, last_index, count)
|
47
|
+
else
|
48
|
+
read_stream_forward(stream_name, last_index, count)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def read_stream_backward(stream_name, start, count)
|
53
|
+
if event_store.key?(stream_name)
|
54
|
+
start_index = start == :head ? event_store[stream_name].length - 1 : start
|
55
|
+
last_index = start_index - count
|
56
|
+
entries = event_store[stream_name].select do |event|
|
57
|
+
event['positionEventNumber'] > last_index && event['positionEventNumber'] <= start_index
|
58
|
+
end
|
59
|
+
{ 'entries' => entries, 'links' => links(last_index, stream_name, 'next', entries, count)}
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def read_stream_forward(stream_name, start_index, count, long_pool = 0)
|
64
|
+
if event_store.key?(stream_name)
|
65
|
+
last_index = start_index + count
|
66
|
+
entries = event_store[stream_name].reverse.select do |event|
|
67
|
+
event['positionEventNumber'] < last_index && event['positionEventNumber'] >= start_index
|
68
|
+
end
|
69
|
+
{ 'entries' => entries.reverse!, 'links' => links(last_index, stream_name, 'previous', entries, count)}
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def reset!
|
74
|
+
@event_store = {}
|
75
|
+
end
|
76
|
+
|
77
|
+
def endpoint
|
78
|
+
Endpoint.new('127.0.0.1', 2113)
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
def links(batch_size, stream_name, direction, entries, count)
|
84
|
+
if entries.empty? || batch_size < 0
|
85
|
+
[]
|
86
|
+
else
|
87
|
+
[{
|
88
|
+
'uri' => "http://#{endpoint.url}/streams/#{stream_name}/#{batch_size}/#{direction}/#{count}",
|
89
|
+
'relation' => direction
|
90
|
+
}]
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'http_eventstore'
|
2
|
+
require 'in_memory_es'
|
3
|
+
|
4
|
+
module SandthornDriverEventStore
|
5
|
+
class InMemoryEventStoreDriver
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@connection = HttpEventstore::Connection.new { |config| config.client = HttpEventstore::InMemoryEs.new("localhost", 2113, 20) }
|
9
|
+
end
|
10
|
+
|
11
|
+
def execute
|
12
|
+
yield @connection
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'securerandom'
|
3
|
+
|
4
|
+
module SandthornDriverEventStore
|
5
|
+
describe EventStore do
|
6
|
+
context "when saving a prefectly sane event stream" do
|
7
|
+
let(:test_events) do
|
8
|
+
e = []
|
9
|
+
e << {aggregate_version: 1, event_name: "new", event_args: {:method_name=>"new", :method_args=>[], :attribute_deltas=>[{:attribute_name=>"aggregate_id", :old_value=>nil, :new_value=>"e147e4bb-e98d-4008-ae9a-0bccce314d7b"}]}}
|
10
|
+
e << {aggregate_version: 2, event_name: "foo", event_args: {:method_name=>"foo", :method_args=>[], :attribute_deltas=>[{:attribute_name=>"aggregate_id", :old_value=>nil, :new_value=>"e147e4bb-e98d-4008-ae9a-0bccce314d7b"}]}}
|
11
|
+
e << {aggregate_version: 3, event_name: "flubber", event_args: {:method_name=>"flubber", :method_args=>["bar"], :attribute_deltas=>[{:attribute_name=>"aggregate_id", :old_value=>nil, :new_value=>"e147e4bb-e98d-4008-ae9a-0bccce314d7b"}]}}
|
12
|
+
end
|
13
|
+
|
14
|
+
let(:aggregate_id) { SecureRandom.uuid }
|
15
|
+
|
16
|
+
it "should be able to save and retrieve events on the aggregate" do
|
17
|
+
event_store.save_events test_events, aggregate_id, String
|
18
|
+
events = event_store.find aggregate_id
|
19
|
+
expect(events.length).to eql test_events.length
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should have correct keys when asking for events" do
|
23
|
+
event_store.save_events test_events, aggregate_id, String
|
24
|
+
events = event_store.find aggregate_id
|
25
|
+
event = events.first
|
26
|
+
expect(event[:event_args]).to eql(test_events.first[:event_args])
|
27
|
+
expect(event[:event_name]).to eql("new")
|
28
|
+
expect(event[:aggregate_id]).to eql aggregate_id
|
29
|
+
expect(event[:aggregate_version]).to eql 1
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'sandthorn_driver_event_store'
|
2
|
+
require 'ap'
|
3
|
+
require 'uuidtools'
|
4
|
+
require 'in_memory_event_store_driver'
|
5
|
+
|
6
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
7
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
8
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
9
|
+
# loaded once.
|
10
|
+
#
|
11
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
12
|
+
RSpec.configure do |config|
|
13
|
+
config.run_all_when_everything_filtered = true
|
14
|
+
config.filter_run :focus
|
15
|
+
config.filter_run_excluding benchmark: true
|
16
|
+
config.order = 'random'
|
17
|
+
end
|
18
|
+
def prepare_for_test context: :test
|
19
|
+
# migrator.send(:clear_for_test)
|
20
|
+
end
|
21
|
+
|
22
|
+
def event_store_driver_memory
|
23
|
+
SandthornDriverEventStore::InMemoryEventStoreDriver.new
|
24
|
+
end
|
25
|
+
|
26
|
+
def event_store_driver
|
27
|
+
event_store.driver
|
28
|
+
end
|
29
|
+
|
30
|
+
def event_store
|
31
|
+
@event_store ||= SandthornDriverEventStore.driver host: "localhost", port: 2113, page_size: 20
|
32
|
+
return @event_store
|
33
|
+
end
|
metadata
ADDED
@@ -0,0 +1,265 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sandthorn_driver_event_store
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Morgan Hallgren
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-04-25 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: gem-release
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: pry
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: pry-doc
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: awesome_print
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: autotest-standalone
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: uuidtools
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: ruby-beautify
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: msgpack
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: snappy
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - ">="
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
type: :development
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - ">="
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0'
|
181
|
+
- !ruby/object:Gem::Dependency
|
182
|
+
name: guard-rspec
|
183
|
+
requirement: !ruby/object:Gem::Requirement
|
184
|
+
requirements:
|
185
|
+
- - ">="
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
version: '0'
|
188
|
+
type: :development
|
189
|
+
prerelease: false
|
190
|
+
version_requirements: !ruby/object:Gem::Requirement
|
191
|
+
requirements:
|
192
|
+
- - ">="
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: '0'
|
195
|
+
description: Event Store driver for Sandthorn
|
196
|
+
email:
|
197
|
+
- morgan.hallgren@gmail.com
|
198
|
+
executables: []
|
199
|
+
extensions: []
|
200
|
+
extra_rdoc_files: []
|
201
|
+
files:
|
202
|
+
- ".autotest"
|
203
|
+
- ".gitignore"
|
204
|
+
- ".rspec"
|
205
|
+
- ".ruby-gemset"
|
206
|
+
- ".ruby-version"
|
207
|
+
- ".travis.yml"
|
208
|
+
- Gemfile
|
209
|
+
- Guardfile
|
210
|
+
- LICENSE.txt
|
211
|
+
- README.md
|
212
|
+
- Rakefile
|
213
|
+
- lib/sandthorn_driver_event_store.rb
|
214
|
+
- lib/sandthorn_driver_event_store/access.rb
|
215
|
+
- lib/sandthorn_driver_event_store/access/event_access.rb
|
216
|
+
- lib/sandthorn_driver_event_store/errors.rb
|
217
|
+
- lib/sandthorn_driver_event_store/event_query.rb
|
218
|
+
- lib/sandthorn_driver_event_store/event_store.rb
|
219
|
+
- lib/sandthorn_driver_event_store/event_store_driver.rb
|
220
|
+
- lib/sandthorn_driver_event_store/utilities.rb
|
221
|
+
- lib/sandthorn_driver_event_store/utilities/array.rb
|
222
|
+
- lib/sandthorn_driver_event_store/version.rb
|
223
|
+
- lib/sandthorn_driver_event_store/wrappers.rb
|
224
|
+
- lib/sandthorn_driver_event_store/wrappers/event_wrapper.rb
|
225
|
+
- sandthorn_driver_event_store.gemspec
|
226
|
+
- spec/driver_interface_spec.rb
|
227
|
+
- spec/event_access_spec.rb
|
228
|
+
- spec/get_events_spec.rb
|
229
|
+
- spec/in_memory_es.rb
|
230
|
+
- spec/in_memory_event_store_driver.rb
|
231
|
+
- spec/saving_events_spec.rb
|
232
|
+
- spec/spec_helper.rb
|
233
|
+
homepage: ''
|
234
|
+
licenses:
|
235
|
+
- MIT
|
236
|
+
metadata: {}
|
237
|
+
post_install_message:
|
238
|
+
rdoc_options: []
|
239
|
+
require_paths:
|
240
|
+
- lib
|
241
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
242
|
+
requirements:
|
243
|
+
- - ">="
|
244
|
+
- !ruby/object:Gem::Version
|
245
|
+
version: '2.0'
|
246
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
247
|
+
requirements:
|
248
|
+
- - ">="
|
249
|
+
- !ruby/object:Gem::Version
|
250
|
+
version: '0'
|
251
|
+
requirements: []
|
252
|
+
rubyforge_project:
|
253
|
+
rubygems_version: 2.4.3
|
254
|
+
signing_key:
|
255
|
+
specification_version: 4
|
256
|
+
summary: Event Store driver for Sandthorn
|
257
|
+
test_files:
|
258
|
+
- spec/driver_interface_spec.rb
|
259
|
+
- spec/event_access_spec.rb
|
260
|
+
- spec/get_events_spec.rb
|
261
|
+
- spec/in_memory_es.rb
|
262
|
+
- spec/in_memory_event_store_driver.rb
|
263
|
+
- spec/saving_events_spec.rb
|
264
|
+
- spec/spec_helper.rb
|
265
|
+
has_rdoc:
|