ruby_event_store-rom 1.3.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
         |