ruby_event_store-rom 1.2.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +2 -1
- data/lib/ruby_event_store/rom/changesets/create_events.rb +10 -18
- data/lib/ruby_event_store/rom/changesets/create_stream_entries.rb +6 -11
- data/lib/ruby_event_store/rom/changesets/update_events.rb +32 -19
- data/lib/ruby_event_store/rom/event_repository.rb +53 -51
- data/lib/ruby_event_store/rom/index_violation_detector.rb +29 -0
- data/lib/ruby_event_store/rom/mappers/event_to_serialized_record.rb +4 -4
- data/lib/ruby_event_store/rom/mappers/stream_entry_to_serialized_record.rb +5 -4
- data/lib/ruby_event_store/rom/rake_task.rb +5 -0
- data/lib/ruby_event_store/rom/relations/events.rb +81 -0
- data/lib/ruby_event_store/rom/relations/stream_entries.rb +90 -0
- data/lib/ruby_event_store/rom/repositories/events.rb +43 -29
- data/lib/ruby_event_store/rom/repositories/stream_entries.rb +7 -13
- data/lib/ruby_event_store/rom/{adapters/sql/tasks → tasks}/migration_tasks.rake +9 -9
- data/lib/ruby_event_store/rom/types.rb +2 -2
- data/lib/ruby_event_store/rom/unit_of_work.rb +29 -13
- data/lib/ruby_event_store/rom/version.rb +1 -1
- data/lib/ruby_event_store/rom.rb +29 -102
- data/lib/ruby_event_store-rom.rb +1 -1
- metadata +29 -48
- data/.rubocop.yml +0 -1
- data/.rubocop_todo.yml +0 -84
- data/CHANGELOG.md +0 -9
- data/Gemfile +0 -12
- data/Makefile +0 -57
- data/Rakefile +0 -20
- data/db/migrate/20180327044629_create_ruby_event_store_tables.rb +0 -54
- data/db/migrate/20181026152045_index_by_event_type.rb +0 -9
- data/lib/ruby_event_store/rom/adapters/memory/changesets/create_events.rb +0 -19
- data/lib/ruby_event_store/rom/adapters/memory/changesets/create_stream_entries.rb +0 -19
- data/lib/ruby_event_store/rom/adapters/memory/changesets/update_events.rb +0 -18
- data/lib/ruby_event_store/rom/adapters/memory/relations/events.rb +0 -56
- data/lib/ruby_event_store/rom/adapters/memory/relations/stream_entries.rb +0 -114
- data/lib/ruby_event_store/rom/adapters/memory/unit_of_work.rb +0 -36
- data/lib/ruby_event_store/rom/adapters/sql/changesets/create_events.rb +0 -15
- data/lib/ruby_event_store/rom/adapters/sql/changesets/update_events.rb +0 -41
- data/lib/ruby_event_store/rom/adapters/sql/index_violation_detector.rb +0 -31
- data/lib/ruby_event_store/rom/adapters/sql/rake_task.rb +0 -5
- data/lib/ruby_event_store/rom/adapters/sql/relations/events.rb +0 -27
- data/lib/ruby_event_store/rom/adapters/sql/relations/stream_entries.rb +0 -72
- data/lib/ruby_event_store/rom/memory.rb +0 -82
- data/lib/ruby_event_store/rom/sql.rb +0 -169
- data/lib/ruby_event_store/rom/tuple_uniqueness_error.rb +0 -21
- data/lib/ruby_event_store/spec/rom/event_repository_lint.rb +0 -176
- data/lib/ruby_event_store/spec/rom/relations/events_lint.rb +0 -75
- data/lib/ruby_event_store/spec/rom/relations/stream_entries_lint.rb +0 -198
- data/lib/ruby_event_store/spec/rom/spec_helper_lint.rb +0 -15
- data/lib/ruby_event_store/spec/rom/unit_of_work_lint.rb +0 -37
- data/ruby_event_store-rom.gemspec +0 -37
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 48f28d42768890a56d1b3b7656acdc5ac79c3cfe268292eccfbebc629a039c3d
|
4
|
+
data.tar.gz: ac9401345cbbfe5181822e94f87af9d0dfdabfa85b961665d66fd49f0a47a589
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f30117d5b3a3fb046bacc5c13c5c83fb9ea115647eb906bd3649a5cb1b2d8cce9b4e36f9508224c4b4a32f65ca97d4edc803572049f8dfd27e248424c0995900
|
7
|
+
data.tar.gz: b9e646749e2631f476f27afcf33033cd73e3488d19b408f04b8694436099a643e3a2474c6525f646f94dc4b924f42e057a8036e81e77077569df65d5d3130ccc
|
data/README.md
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
# RubyEventStore ROM Event Repository
|
2
2
|
|
3
|
+

|
4
|
+
|
3
5
|
A Ruby Object Model (ROM) implementation of events repository for [Ruby Event Store](https://github.com/RailsEventStore/rails_event_store).
|
4
6
|
|
5
7
|
This version of the ROM adapter supports [rom-sql](https://github.com/rom-rb/rom-sql) at this time. It is an alternative to the ActiveRecord `EventRepository` implementation used in `rails_event_store` gem.
|
6
8
|
|
7
9
|
[Read the docs to get started.](http://railseventstore.org/docs/repository/)
|
8
10
|
|
9
|
-
_Additonal backing stores via ROM are being tracked here: [#299](https://github.com/RailsEventStore/rails_event_store/issues/299)._
|
@@ -4,27 +4,19 @@ module RubyEventStore
|
|
4
4
|
module ROM
|
5
5
|
module Changesets
|
6
6
|
class CreateEvents < ::ROM::Changeset::Create
|
7
|
-
|
8
|
-
def self.included(base)
|
9
|
-
base.class_eval do
|
10
|
-
relation :events
|
7
|
+
relation :events
|
11
8
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
end
|
19
|
-
|
20
|
-
map do |tuple|
|
21
|
-
Hash(created_at: RubyEventStore::ROM::Types::DateTime.call(nil)).merge(tuple)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
9
|
+
map(&:to_h)
|
10
|
+
map do
|
11
|
+
rename_keys timestamp: :created_at
|
12
|
+
map_value :created_at, ->(time) { Time.iso8601(time).localtime }
|
13
|
+
map_value :valid_at, ->(time) { Time.iso8601(time).localtime }
|
14
|
+
accept_keys %i[event_id data metadata event_type created_at valid_at]
|
25
15
|
end
|
26
16
|
|
27
|
-
|
17
|
+
def commit
|
18
|
+
relation.multi_insert(to_a)
|
19
|
+
end
|
28
20
|
end
|
29
21
|
end
|
30
22
|
end
|
@@ -4,19 +4,14 @@ module RubyEventStore
|
|
4
4
|
module ROM
|
5
5
|
module Changesets
|
6
6
|
class CreateStreamEntries < ::ROM::Changeset::Create
|
7
|
-
|
8
|
-
def self.included(base)
|
9
|
-
base.class_eval do
|
10
|
-
relation :stream_entries
|
7
|
+
relation :stream_entries
|
11
8
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
9
|
+
map do |tuple|
|
10
|
+
Hash(created_at: RubyEventStore::ROM::Types::DateTime.call(nil)).merge(tuple)
|
11
|
+
end
|
12
|
+
map do
|
13
|
+
map_value :created_at, ->(datetime) { datetime.to_time.localtime }
|
17
14
|
end
|
18
|
-
|
19
|
-
include Defaults
|
20
15
|
end
|
21
16
|
end
|
22
17
|
end
|
@@ -4,27 +4,40 @@ module RubyEventStore
|
|
4
4
|
module ROM
|
5
5
|
module Changesets
|
6
6
|
class UpdateEvents < ::ROM::Changeset::Update
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
7
|
+
relation :events
|
8
|
+
|
9
|
+
map(&:to_h)
|
10
|
+
map do
|
11
|
+
rename_keys timestamp: :created_at
|
12
|
+
map_value :created_at, ->(time) { Time.iso8601(time).localtime }
|
13
|
+
map_value :valid_at, ->(time) { Time.iso8601(time).localtime }
|
14
|
+
accept_keys %i[event_id data metadata event_type created_at valid_at]
|
15
|
+
end
|
16
|
+
|
17
|
+
UPSERT_COLUMNS = %i[event_type data metadata valid_at].freeze
|
18
|
+
|
19
|
+
def commit
|
20
|
+
supports_on_duplicate_key_update? ? commit_on_duplicate_key_update : commit_insert_conflict_update
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def supports_on_duplicate_key_update?
|
26
|
+
relation.dataset.db.adapter_scheme =~ /mysql/
|
27
|
+
end
|
28
|
+
|
29
|
+
def commit_on_duplicate_key_update
|
30
|
+
relation.dataset.on_duplicate_key_update(*UPSERT_COLUMNS).multi_insert(to_a)
|
25
31
|
end
|
26
32
|
|
27
|
-
|
33
|
+
def commit_insert_conflict_update
|
34
|
+
relation.dataset.insert_conflict(
|
35
|
+
target: :event_id,
|
36
|
+
update: UPSERT_COLUMNS.each_with_object({}) do |column, memo|
|
37
|
+
memo[column] = Sequel[:excluded][column]
|
38
|
+
end
|
39
|
+
).multi_insert(to_a)
|
40
|
+
end
|
28
41
|
end
|
29
42
|
end
|
30
43
|
end
|
@@ -1,40 +1,26 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'ruby_event_store/rom/unit_of_work'
|
4
|
-
require 'forwardable'
|
5
|
-
|
6
3
|
module RubyEventStore
|
7
4
|
module ROM
|
8
5
|
class EventRepository
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
def initialize(rom: ROM.env)
|
15
|
-
raise ArgumentError, 'Must specify rom' unless rom && rom.instance_of?(Env)
|
16
|
-
|
17
|
-
@rom = rom
|
18
|
-
@events = Repositories::Events.new(rom.rom_container)
|
19
|
-
@stream_entries = Repositories::StreamEntries.new(rom.rom_container)
|
6
|
+
def initialize(rom:, serializer:)
|
7
|
+
@serializer = serializer
|
8
|
+
@events = Repositories::Events.new(rom)
|
9
|
+
@stream_entries = Repositories::StreamEntries.new(rom)
|
10
|
+
@unit_of_work = UnitOfWork.new(rom.gateways.fetch(:default))
|
20
11
|
end
|
21
12
|
|
22
|
-
def append_to_stream(
|
23
|
-
|
24
|
-
event_ids
|
25
|
-
|
26
|
-
|
27
|
-
unit_of_work do |changesets|
|
28
|
-
|
29
|
-
# we want to find the last position (a.k.a. version)
|
30
|
-
# again if the transaction is retried due to a
|
31
|
-
# deadlock in MySQL
|
32
|
-
changesets << @events.create_changeset(events)
|
13
|
+
def append_to_stream(records, stream, expected_version)
|
14
|
+
serialized_records = records.map { |record| record.serialize(@serializer) }
|
15
|
+
event_ids = records.map(&:event_id)
|
16
|
+
|
17
|
+
handle_unique_violation do
|
18
|
+
@unit_of_work.call do |changesets|
|
19
|
+
changesets << @events.create_changeset(serialized_records)
|
33
20
|
changesets << @stream_entries.create_changeset(
|
34
21
|
event_ids,
|
35
22
|
stream,
|
36
|
-
@stream_entries.resolve_version(stream, expected_version)
|
37
|
-
global_stream: true
|
23
|
+
@stream_entries.resolve_version(stream, expected_version)
|
38
24
|
)
|
39
25
|
end
|
40
26
|
end
|
@@ -43,15 +29,10 @@ module RubyEventStore
|
|
43
29
|
end
|
44
30
|
|
45
31
|
def link_to_stream(event_ids, stream, expected_version)
|
46
|
-
|
32
|
+
validate_event_ids(event_ids)
|
47
33
|
|
48
|
-
|
49
|
-
|
50
|
-
.find_nonexistent_pks(event_ids)
|
51
|
-
.each { |id| raise EventNotFound, id }
|
52
|
-
|
53
|
-
guard_for(:unique_violation) do
|
54
|
-
unit_of_work do |changesets|
|
34
|
+
handle_unique_violation do
|
35
|
+
@unit_of_work.call do |changesets|
|
55
36
|
changesets << @stream_entries.create_changeset(
|
56
37
|
event_ids,
|
57
38
|
stream,
|
@@ -63,44 +44,65 @@ module RubyEventStore
|
|
63
44
|
self
|
64
45
|
end
|
65
46
|
|
47
|
+
def position_in_stream(event_id, stream)
|
48
|
+
@stream_entries.position_in_stream(event_id, stream)
|
49
|
+
end
|
50
|
+
|
51
|
+
def global_position(event_id)
|
52
|
+
@events.global_position(event_id)
|
53
|
+
end
|
54
|
+
|
66
55
|
def delete_stream(stream)
|
67
56
|
@stream_entries.delete(stream)
|
68
57
|
end
|
69
58
|
|
70
59
|
def has_event?(event_id)
|
71
|
-
|
60
|
+
@events.exist?(event_id)
|
61
|
+
rescue Sequel::DatabaseError => doh
|
62
|
+
raise doh unless doh.message =~ /PG::InvalidTextRepresentation.*uuid/
|
63
|
+
false
|
72
64
|
end
|
73
65
|
|
74
66
|
def last_stream_event(stream)
|
75
|
-
@events.last_stream_event(stream)
|
67
|
+
@events.last_stream_event(stream, @serializer)
|
76
68
|
end
|
77
69
|
|
78
70
|
def read(specification)
|
79
|
-
|
80
|
-
|
81
|
-
@events.read(specification)
|
71
|
+
@events.read(specification, @serializer)
|
82
72
|
end
|
83
73
|
|
84
74
|
def count(specification)
|
85
|
-
raise ReservedInternalName if specification.stream.name.eql?(@stream_entries.stream_entries.class::SERIALIZED_GLOBAL_STREAM_NAME)
|
86
|
-
|
87
75
|
@events.count(specification)
|
88
76
|
end
|
89
77
|
|
90
|
-
def update_messages(
|
91
|
-
|
92
|
-
@events
|
93
|
-
.find_nonexistent_pks(messages.map(&:event_id))
|
94
|
-
.each { |id| raise EventNotFound, id }
|
78
|
+
def update_messages(records)
|
79
|
+
validate_event_ids(records.map(&:event_id))
|
95
80
|
|
96
|
-
unit_of_work do |changesets|
|
97
|
-
|
81
|
+
@unit_of_work.call do |changesets|
|
82
|
+
serialized_records = records.map { |record| record.serialize(@serializer) }
|
83
|
+
changesets << @events.update_changeset(serialized_records)
|
98
84
|
end
|
99
85
|
end
|
100
86
|
|
101
87
|
def streams_of(event_id)
|
102
|
-
@stream_entries
|
103
|
-
|
88
|
+
@stream_entries
|
89
|
+
.streams_of(event_id)
|
90
|
+
.map { |name| Stream.new(name) }
|
91
|
+
end
|
92
|
+
|
93
|
+
private
|
94
|
+
|
95
|
+
def validate_event_ids(event_ids)
|
96
|
+
@events
|
97
|
+
.find_nonexistent_pks(event_ids)
|
98
|
+
.each { |id| raise EventNotFound, id }
|
99
|
+
end
|
100
|
+
|
101
|
+
def handle_unique_violation
|
102
|
+
yield
|
103
|
+
rescue ::ROM::SQL::UniqueConstraintError, Sequel::UniqueConstraintViolation => doh
|
104
|
+
raise ::RubyEventStore::EventDuplicatedInStream if IndexViolationDetector.new.detect(doh.message)
|
105
|
+
raise ::RubyEventStore::WrongExpectedEventVersion
|
104
106
|
end
|
105
107
|
end
|
106
108
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RubyEventStore
|
4
|
+
module ROM
|
5
|
+
class IndexViolationDetector
|
6
|
+
MYSQL5_PKEY_ERROR = "for key 'index_event_store_events_on_event_id'".freeze
|
7
|
+
MYSQL8_PKEY_ERROR = "for key 'event_store_events.index_event_store_events_on_event_id'".freeze
|
8
|
+
POSTGRES_PKEY_ERROR = "Key (event_id)".freeze
|
9
|
+
SQLITE3_PKEY_ERROR = "event_store_events.event_id".freeze
|
10
|
+
|
11
|
+
MYSQL5_INDEX_ERROR = "for key 'index_event_store_events_in_streams_on_stream_and_event_id'".freeze
|
12
|
+
MYSQL8_INDEX_ERROR = "for key 'event_store_events_in_streams.index_event_store_events_in_streams_on_stream_and_event_id'".freeze
|
13
|
+
POSTGRES_INDEX_ERROR = "Key (stream, event_id)".freeze
|
14
|
+
SQLITE3_INDEX_ERROR = "event_store_events_in_streams.stream, event_store_events_in_streams.event_id".freeze
|
15
|
+
|
16
|
+
def detect(message)
|
17
|
+
message.include?(MYSQL5_PKEY_ERROR) ||
|
18
|
+
message.include?(MYSQL8_PKEY_ERROR) ||
|
19
|
+
message.include?(POSTGRES_PKEY_ERROR) ||
|
20
|
+
message.include?(SQLITE3_PKEY_ERROR) ||
|
21
|
+
|
22
|
+
message.include?(MYSQL5_INDEX_ERROR) ||
|
23
|
+
message.include?(MYSQL8_INDEX_ERROR) ||
|
24
|
+
message.include?(POSTGRES_INDEX_ERROR) ||
|
25
|
+
message.include?(SQLITE3_INDEX_ERROR)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'rom/transformer'
|
4
|
-
|
5
3
|
module RubyEventStore
|
6
4
|
module ROM
|
7
5
|
module Mappers
|
@@ -10,8 +8,10 @@ module RubyEventStore
|
|
10
8
|
register_as :event_to_serialized_record
|
11
9
|
|
12
10
|
map_array do
|
13
|
-
|
14
|
-
|
11
|
+
map_value :created_at, ->(time) { time.iso8601(TIMESTAMP_PRECISION) }
|
12
|
+
map_value :valid_at, ->(time) { time.iso8601(TIMESTAMP_PRECISION) }
|
13
|
+
rename_keys created_at: :timestamp
|
14
|
+
accept_keys %i[event_id data metadata event_type timestamp valid_at]
|
15
15
|
constructor_inject RubyEventStore::SerializedRecord
|
16
16
|
end
|
17
17
|
end
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'rom/transformer'
|
4
|
-
|
5
3
|
module RubyEventStore
|
6
4
|
module ROM
|
7
5
|
module Mappers
|
@@ -10,8 +8,11 @@ module RubyEventStore
|
|
10
8
|
register_as :stream_entry_to_serialized_record
|
11
9
|
|
12
10
|
map_array do
|
13
|
-
unwrap :event, %i[data metadata event_type]
|
14
|
-
|
11
|
+
unwrap :event, %i[event_id data metadata event_type created_at valid_at]
|
12
|
+
map_value :created_at, ->(time) { time.iso8601(TIMESTAMP_PRECISION) }
|
13
|
+
map_value :valid_at, ->(time) { time.iso8601(TIMESTAMP_PRECISION) }
|
14
|
+
rename_keys created_at: :timestamp
|
15
|
+
accept_keys %i[event_id data metadata event_type timestamp valid_at]
|
15
16
|
constructor_inject RubyEventStore::SerializedRecord
|
16
17
|
end
|
17
18
|
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RubyEventStore
|
4
|
+
module ROM
|
5
|
+
module Relations
|
6
|
+
class Events < ::ROM::Relation[:sql]
|
7
|
+
schema(:event_store_events, as: :events, infer: true) do
|
8
|
+
attribute :event_id, ::ROM::Types::String
|
9
|
+
attribute :data, RubyEventStore::ROM::Types::RecordSerializer,
|
10
|
+
read: RubyEventStore::ROM::Types::RecordDeserializer
|
11
|
+
attribute :metadata, RubyEventStore::ROM::Types::RecordSerializer,
|
12
|
+
read: RubyEventStore::ROM::Types::RecordDeserializer
|
13
|
+
attribute :created_at, RubyEventStore::ROM::Types::DateTime
|
14
|
+
attribute :valid_at, RubyEventStore::ROM::Types::DateTime
|
15
|
+
|
16
|
+
primary_key :event_id
|
17
|
+
end
|
18
|
+
|
19
|
+
alias take limit
|
20
|
+
|
21
|
+
def create_changeset(tuples)
|
22
|
+
events.changeset(Changesets::CreateEvents, tuples)
|
23
|
+
end
|
24
|
+
|
25
|
+
def update_changeset(tuples)
|
26
|
+
events.changeset(Changesets::UpdateEvents, tuples)
|
27
|
+
end
|
28
|
+
|
29
|
+
def by_event_id(event_id)
|
30
|
+
where(event_id: event_id)
|
31
|
+
end
|
32
|
+
|
33
|
+
def by_event_type(types)
|
34
|
+
where(event_type: types)
|
35
|
+
end
|
36
|
+
|
37
|
+
def newer_than(time)
|
38
|
+
where { |r| r.events[:created_at] > time.localtime }
|
39
|
+
end
|
40
|
+
|
41
|
+
def newer_than_or_equal(time)
|
42
|
+
where { |r| r.events[:created_at] >= time.localtime }
|
43
|
+
end
|
44
|
+
|
45
|
+
def older_than(time)
|
46
|
+
where { |r| r.events[:created_at] < time.localtime }
|
47
|
+
end
|
48
|
+
|
49
|
+
def older_than_or_equal(time)
|
50
|
+
where { |r| r.events[:created_at] <= time.localtime }
|
51
|
+
end
|
52
|
+
|
53
|
+
DIRECTION_MAP = {
|
54
|
+
forward: %i[asc > <],
|
55
|
+
backward: %i[desc < >]
|
56
|
+
}.freeze
|
57
|
+
|
58
|
+
def ordered(direction, offset_entry_id = nil, stop_entry_id = nil, time_sort_by = nil)
|
59
|
+
order, operator_offset, operator_stop = DIRECTION_MAP[direction]
|
60
|
+
|
61
|
+
raise ArgumentError, "Direction must be :forward or :backward" if order.nil?
|
62
|
+
|
63
|
+
event_order_columns = [:id]
|
64
|
+
|
65
|
+
case time_sort_by
|
66
|
+
when :as_at
|
67
|
+
event_order_columns.unshift :created_at
|
68
|
+
when :as_of
|
69
|
+
event_order_columns.unshift :valid_at
|
70
|
+
end
|
71
|
+
|
72
|
+
query = self
|
73
|
+
query = query.where { id.public_send(operator_offset, offset_entry_id) } if offset_entry_id
|
74
|
+
query = query.where { id.public_send(operator_stop, stop_entry_id) } if stop_entry_id
|
75
|
+
|
76
|
+
query.order(*event_order_columns.map { |c| events[c].public_send(order) })
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RubyEventStore
|
4
|
+
module ROM
|
5
|
+
module Relations
|
6
|
+
class StreamEntries < ::ROM::Relation[:sql]
|
7
|
+
schema(:event_store_events_in_streams, as: :stream_entries, infer: true) do
|
8
|
+
attribute :created_at, RubyEventStore::ROM::Types::DateTime
|
9
|
+
|
10
|
+
associations do
|
11
|
+
belongs_to :events, as: :event, foreign_key: :event_id
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
alias take limit
|
16
|
+
|
17
|
+
def create_changeset(tuples)
|
18
|
+
changeset(ROM::Changesets::CreateStreamEntries, tuples)
|
19
|
+
end
|
20
|
+
|
21
|
+
def by_stream(stream)
|
22
|
+
where(stream: stream.name)
|
23
|
+
end
|
24
|
+
|
25
|
+
def by_event_id(event_id)
|
26
|
+
where(event_id: event_id)
|
27
|
+
end
|
28
|
+
|
29
|
+
def by_event_type(types)
|
30
|
+
join(:events).where(event_type: types)
|
31
|
+
end
|
32
|
+
|
33
|
+
def by_stream_and_event_id(stream, event_id)
|
34
|
+
where(stream: stream.name, event_id: event_id).one!
|
35
|
+
end
|
36
|
+
|
37
|
+
def max_position(stream)
|
38
|
+
by_stream(stream).select(:position).order(Sequel.desc(:position)).first
|
39
|
+
end
|
40
|
+
|
41
|
+
def newer_than(time)
|
42
|
+
join(:events).where { |r| r.events[:created_at] > time.localtime }
|
43
|
+
end
|
44
|
+
|
45
|
+
def newer_than_or_equal(time)
|
46
|
+
join(:events).where { |r| r.events[:created_at] >= time.localtime }
|
47
|
+
end
|
48
|
+
|
49
|
+
def older_than(time)
|
50
|
+
join(:events).where { |r| r.events[:created_at] < time.localtime }
|
51
|
+
end
|
52
|
+
|
53
|
+
def older_than_or_equal(time)
|
54
|
+
join(:events).where { |r| r.events[:created_at] <= time.localtime }
|
55
|
+
end
|
56
|
+
|
57
|
+
DIRECTION_MAP = {
|
58
|
+
forward: %i[asc > <],
|
59
|
+
backward: %i[desc < >]
|
60
|
+
}.freeze
|
61
|
+
|
62
|
+
def ordered(direction, stream, offset_entry_id = nil, stop_entry_id = nil, time_sort_by = nil)
|
63
|
+
order, operator_offset, operator_stop = DIRECTION_MAP[direction]
|
64
|
+
|
65
|
+
raise ArgumentError, "Direction must be :forward or :backward" if order.nil?
|
66
|
+
|
67
|
+
event_order_columns = []
|
68
|
+
stream_order_columns = %i[id]
|
69
|
+
|
70
|
+
case time_sort_by
|
71
|
+
when :as_at
|
72
|
+
event_order_columns.unshift :created_at
|
73
|
+
when :as_of
|
74
|
+
event_order_columns.unshift :valid_at
|
75
|
+
end
|
76
|
+
|
77
|
+
query = by_stream(stream)
|
78
|
+
query = query.where { id.public_send(operator_offset, offset_entry_id) } if offset_entry_id
|
79
|
+
query = query.where { id.public_send(operator_stop, stop_entry_id) } if stop_entry_id
|
80
|
+
|
81
|
+
if event_order_columns.empty?
|
82
|
+
query.order { |r| stream_order_columns.map { |c| r[:stream_entries][c].public_send(order) } }
|
83
|
+
else
|
84
|
+
query.join(:events).order { |r| event_order_columns.map { |c| r.events[c].public_send(order) } }
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|