event_store_client 0.2.3 → 0.2.4
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/lib/event_store_client.rb +1 -9
- data/lib/event_store_client/broker.rb +4 -3
- data/lib/event_store_client/client.rb +13 -5
- data/lib/event_store_client/configuration.rb +36 -17
- data/lib/event_store_client/mapper/default.rb +2 -1
- data/lib/event_store_client/serializer/json.rb +2 -0
- data/lib/event_store_client/store_adapter/api/client.rb +65 -9
- data/lib/event_store_client/store_adapter/api/connection.rb +9 -5
- data/lib/event_store_client/store_adapter/in_memory.rb +40 -5
- data/lib/event_store_client/subscriptions.rb +2 -1
- data/lib/event_store_client/version.rb +1 -1
- metadata +21 -9
- data/lib/event_store_client/connection.rb +0 -112
- data/lib/event_store_client/endpoint.rb +0 -14
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: cc9b9f123804c920a08c07937465ae04afcd971d784912099f06822725742901
         | 
| 4 | 
            +
              data.tar.gz: 0e5e5e7d863180a90fa20a6c6d1d2b8e76b479cb50489910af2327a33e0d2c7f
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 04e46ab7a710fc53c7be0d22bbadd59e6a075495174b88447cb82f054de5dcfa02607a1bf7cc03392952bdabb6dffc68ec264575264bd1fb3a9d5ac32447caea
         | 
| 7 | 
            +
              data.tar.gz: 188cff27182fe3e6f83250c70a3a4a5cab9814b7ef1ce61a624af2bcd235d4cf950723e7551d8ec2612f64923b117592341ea4ada03fe44660c6f2f7713f05ce
         | 
    
        data/lib/event_store_client.rb
    CHANGED
    
    | @@ -1,27 +1,19 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 2 |  | 
| 3 3 | 
             
            module EventStoreClient
         | 
| 4 | 
            -
              def self.configure(&block)
         | 
| 5 | 
            -
                config = Configuration.instance
         | 
| 6 | 
            -
                config.configure(&block)
         | 
| 7 | 
            -
              end
         | 
| 8 4 | 
             
            end
         | 
| 9 5 |  | 
| 10 | 
            -
            require 'event_store_client/configuration'
         | 
| 11 6 | 
             
            require 'event_store_client/types'
         | 
| 12 7 | 
             
            require 'event_store_client/event'
         | 
| 13 8 | 
             
            require 'event_store_client/deserialized_event'
         | 
| 14 | 
            -
             | 
| 15 9 | 
             
            require 'event_store_client/serializer/json'
         | 
| 16 10 |  | 
| 17 11 | 
             
            require 'event_store_client/mapper'
         | 
| 18 12 |  | 
| 19 | 
            -
            require 'event_store_client/ | 
| 13 | 
            +
            require 'event_store_client/configuration'
         | 
| 20 14 |  | 
| 21 15 | 
             
            require 'event_store_client/store_adapter'
         | 
| 22 16 |  | 
| 23 | 
            -
            require 'event_store_client/connection'
         | 
| 24 | 
            -
             | 
| 25 17 | 
             
            require 'event_store_client/subscription'
         | 
| 26 18 | 
             
            require 'event_store_client/subscriptions'
         | 
| 27 19 | 
             
            require 'event_store_client/broker'
         | 
| @@ -4,9 +4,10 @@ module EventStoreClient | |
| 4 4 | 
             
              class Broker
         | 
| 5 5 | 
             
                def call(subscriptions)
         | 
| 6 6 | 
             
                  subscriptions.each do |subscription|
         | 
| 7 | 
            -
                     | 
| 8 | 
            -
                    next if  | 
| 9 | 
            -
                     | 
| 7 | 
            +
                    res = connection.consume_feed(subscription.stream, subscription.name) || []
         | 
| 8 | 
            +
                    next if res[:events].none?
         | 
| 9 | 
            +
                    res[:events].each { |event| subscription.subscriber.call(event) }
         | 
| 10 | 
            +
                    connection.ack(res[:ack_uri])
         | 
| 10 11 | 
             
                  end
         | 
| 11 12 | 
             
                end
         | 
| 12 13 |  | 
| @@ -8,13 +8,21 @@ module EventStoreClient | |
| 8 8 | 
             
                WrongExpectedEventVersion = Class.new(StandardError)
         | 
| 9 9 |  | 
| 10 10 | 
             
                def publish(stream:, events:, expected_version: nil)
         | 
| 11 | 
            -
                  connection. | 
| 11 | 
            +
                  connection.append_to_stream(stream, events, expected_version: expected_version)
         | 
| 12 12 | 
             
                rescue StoreAdapter::Api::Client::WrongExpectedEventVersion => e
         | 
| 13 13 | 
             
                  raise WrongExpectedEventVersion.new(e.message)
         | 
| 14 14 | 
             
                end
         | 
| 15 15 |  | 
| 16 | 
            -
                def read(stream, direction: 'forward', start: 0, all: false)
         | 
| 17 | 
            -
                   | 
| 16 | 
            +
                def read(stream, direction: 'forward', start: 0, all: false, resolve_links: true)
         | 
| 17 | 
            +
                  if all
         | 
| 18 | 
            +
                    connection.read_all_from_stream(
         | 
| 19 | 
            +
                      stream, start: start, direction: direction, resolve_links: resolve_links
         | 
| 20 | 
            +
                    )
         | 
| 21 | 
            +
                  else
         | 
| 22 | 
            +
                    connection.read(
         | 
| 23 | 
            +
                      stream, start: start, direction: direction, resolve_links: resolve_links
         | 
| 24 | 
            +
                    )
         | 
| 25 | 
            +
                  end
         | 
| 18 26 | 
             
                end
         | 
| 19 27 |  | 
| 20 28 | 
             
                def subscribe(subscriber, to: [], polling: true)
         | 
| @@ -81,12 +89,12 @@ module EventStoreClient | |
| 81 89 | 
             
                attr_reader :subscriptions, :broker, :error_handler
         | 
| 82 90 |  | 
| 83 91 | 
             
                def config
         | 
| 84 | 
            -
                  EventStoreClient | 
| 92 | 
            +
                  EventStoreClient.config
         | 
| 85 93 | 
             
                end
         | 
| 86 94 |  | 
| 87 95 | 
             
                def initialize
         | 
| 88 96 | 
             
                  @threads = []
         | 
| 89 | 
            -
                  @connection ||=  | 
| 97 | 
            +
                  @connection ||= EventStoreClient.adapter
         | 
| 90 98 | 
             
                  @error_handler ||= config.error_handler
         | 
| 91 99 | 
             
                  @service_name ||= 'default'
         | 
| 92 100 | 
             
                  @broker ||= Broker.new(connection: connection)
         | 
| @@ -1,28 +1,47 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 2 |  | 
| 3 | 
            -
            require 'dry- | 
| 4 | 
            -
            require 'singleton'
         | 
| 3 | 
            +
            require 'dry-configurable'
         | 
| 5 4 |  | 
| 6 5 | 
             
            module EventStoreClient
         | 
| 7 | 
            -
               | 
| 8 | 
            -
                include Singleton
         | 
| 6 | 
            +
              extend Dry::Configurable
         | 
| 9 7 |  | 
| 10 | 
            -
             | 
| 8 | 
            +
              # Supported adapters: %i[api in_memory]
         | 
| 9 | 
            +
              #
         | 
| 10 | 
            +
              setting :adapter, :api
         | 
| 11 11 |  | 
| 12 | 
            -
             | 
| 13 | 
            -
             | 
| 14 | 
            -
                 | 
| 12 | 
            +
              setting :error_handler
         | 
| 13 | 
            +
              setting :eventstore_url, 'http://localhost:2113' do |value|
         | 
| 14 | 
            +
                value.is_a?(URI) ? value : URI(value)
         | 
| 15 | 
            +
              end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
              setting :eventstore_user, 'admin'
         | 
| 18 | 
            +
              setting :eventstore_password, 'changeit'
         | 
| 19 | 
            +
             | 
| 20 | 
            +
              setting :db_port, 2113
         | 
| 21 | 
            +
             | 
| 22 | 
            +
              setting :per_page, 20
         | 
| 23 | 
            +
              setting :pid_path, 'tmp/poll.pid'
         | 
| 15 24 |  | 
| 16 | 
            -
             | 
| 25 | 
            +
              setting :service_name, 'default'
         | 
| 17 26 |  | 
| 18 | 
            -
             | 
| 19 | 
            -
             | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 27 | 
            +
              setting :mapper, Mapper::Default.new
         | 
| 28 | 
            +
             | 
| 29 | 
            +
              def self.configure
         | 
| 30 | 
            +
                yield(config) if block_given?
         | 
| 31 | 
            +
              end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
              def self.adapter
         | 
| 34 | 
            +
                case config.adapter
         | 
| 35 | 
            +
                when :api
         | 
| 36 | 
            +
                  StoreAdapter::Api::Client.new(
         | 
| 37 | 
            +
                    config.eventstore_url,
         | 
| 38 | 
            +
                    per_page: config.per_page,
         | 
| 39 | 
            +
                    mapper: config.mapper,
         | 
| 40 | 
            +
                    connection_options: {}
         | 
| 41 | 
            +
                  )
         | 
| 42 | 
            +
                else
         | 
| 43 | 
            +
                  StoreAdapter::InMemory.new(
         | 
| 44 | 
            +
                    mapper: config.mapper, per_page: config.per_page
         | 
| 26 45 | 
             
                  )
         | 
| 27 46 | 
             
                end
         | 
| 28 47 | 
             
              end
         | 
| @@ -5,7 +5,8 @@ module EventStoreClient | |
| 5 5 | 
             
                class Default
         | 
| 6 6 | 
             
                  def serialize(event)
         | 
| 7 7 | 
             
                    Event.new(
         | 
| 8 | 
            -
                       | 
| 8 | 
            +
                      id: event.respond_to?(:id) ? event.id : nil,
         | 
| 9 | 
            +
                      type: (event.respond_to?(:type) ? event.type : nil) || event.class.to_s,
         | 
| 9 10 | 
             
                      data: serializer.serialize(event.data),
         | 
| 10 11 | 
             
                      metadata: serializer.serialize(event.metadata)
         | 
| 11 12 | 
             
                    )
         | 
| @@ -7,14 +7,16 @@ module EventStoreClient | |
| 7 7 | 
             
                    WrongExpectedEventVersion = Class.new(StandardError)
         | 
| 8 8 |  | 
| 9 9 | 
             
                    def append_to_stream(stream_name, events, expected_version: nil)
         | 
| 10 | 
            +
                      serialized_events = events.map { |event| mapper.serialize(event) }
         | 
| 10 11 | 
             
                      headers = {
         | 
| 11 12 | 
             
                        'ES-ExpectedVersion' => expected_version&.to_s
         | 
| 12 13 | 
             
                      }.reject { |_key, val| val.nil? || val.empty? }
         | 
| 13 14 |  | 
| 14 | 
            -
                      data = build_events_data( | 
| 15 | 
            +
                      data = build_events_data(serialized_events)
         | 
| 15 16 | 
             
                      response = make_request(:post, "/streams/#{stream_name}", body: data, headers: headers)
         | 
| 16 17 | 
             
                      validate_response(response, expected_version)
         | 
| 17 18 | 
             
                      response
         | 
| 19 | 
            +
                      serialized_events
         | 
| 18 20 | 
             
                    end
         | 
| 19 21 |  | 
| 20 22 | 
             
                    def delete_stream(stream_name, hard_delete: false)
         | 
| @@ -31,11 +33,39 @@ module EventStoreClient | |
| 31 33 | 
             
                        'Accept' => 'application/vnd.eventstore.atom+json'
         | 
| 32 34 | 
             
                      }
         | 
| 33 35 |  | 
| 34 | 
            -
                      make_request(
         | 
| 36 | 
            +
                      response = make_request(
         | 
| 35 37 | 
             
                        :get,
         | 
| 36 38 | 
             
                        "/streams/#{stream_name}/#{start}/#{direction}/#{count}",
         | 
| 37 39 | 
             
                        headers: headers
         | 
| 38 40 | 
             
                      )
         | 
| 41 | 
            +
                      return [] if response.body.nil? || response.body.empty?
         | 
| 42 | 
            +
                      JSON.parse(response.body)['entries'].map do |entry|
         | 
| 43 | 
            +
                        deserialize_event(entry)
         | 
| 44 | 
            +
                      end.reverse
         | 
| 45 | 
            +
                    end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                    def read_all_from_stream(stream, start: 0, resolve_links: true)
         | 
| 48 | 
            +
                      count = per_page
         | 
| 49 | 
            +
                      events = []
         | 
| 50 | 
            +
                      failed_requests_count = 0
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                      while failed_requests_count < 3
         | 
| 53 | 
            +
                        begin
         | 
| 54 | 
            +
                          response =
         | 
| 55 | 
            +
                            read(stream, start: start, direction: 'forward', resolve_links: resolve_links)
         | 
| 56 | 
            +
                          failed_requests_count += 1 && next unless response.success? || response.status == 404
         | 
| 57 | 
            +
                        rescue Faraday::ConnectionFailed
         | 
| 58 | 
            +
                          failed_requests_count += 1
         | 
| 59 | 
            +
                          next
         | 
| 60 | 
            +
                        end
         | 
| 61 | 
            +
                        failed_requests_count = 0
         | 
| 62 | 
            +
                        break if response.body.nil? || response.body.empty?
         | 
| 63 | 
            +
                        entries = JSON.parse(response.body)['entries']
         | 
| 64 | 
            +
                        break if entries.empty?
         | 
| 65 | 
            +
                        events += entries.map { |entry| deserialize_event(entry) }.reverse
         | 
| 66 | 
            +
                        start += count
         | 
| 67 | 
            +
                      end
         | 
| 68 | 
            +
                      events
         | 
| 39 69 | 
             
                    end
         | 
| 40 70 |  | 
| 41 71 | 
             
                    def join_streams(name, streams)
         | 
| @@ -79,18 +109,31 @@ module EventStoreClient | |
| 79 109 | 
             
                      subscription_name,
         | 
| 80 110 | 
             
                      count: 1,
         | 
| 81 111 | 
             
                      long_poll: 0,
         | 
| 82 | 
            -
                      resolve_links: true
         | 
| 112 | 
            +
                      resolve_links: true,
         | 
| 113 | 
            +
                      per_page: 20
         | 
| 83 114 | 
             
                    )
         | 
| 84 115 | 
             
                      headers = long_poll.positive? ? { 'ES-LongPoll' => long_poll.to_s } : {}
         | 
| 85 116 | 
             
                      headers['Content-Type'] = 'application/vnd.eventstore.competingatom+json'
         | 
| 86 117 | 
             
                      headers['Accept'] = 'application/vnd.eventstore.competingatom+json'
         | 
| 87 118 | 
             
                      headers['ES-ResolveLinktos'] = resolve_links.to_s
         | 
| 88 119 |  | 
| 89 | 
            -
                      make_request(
         | 
| 120 | 
            +
                      response = make_request(
         | 
| 90 121 | 
             
                        :get,
         | 
| 91 122 | 
             
                        "/subscriptions/#{stream_name}/#{subscription_name}/#{count}",
         | 
| 92 123 | 
             
                        headers: headers
         | 
| 93 124 | 
             
                      )
         | 
| 125 | 
            +
             | 
| 126 | 
            +
                      return [] if response.body || response.body.empty?
         | 
| 127 | 
            +
             | 
| 128 | 
            +
                      body = JSON.parse(response.body)
         | 
| 129 | 
            +
             | 
| 130 | 
            +
                      ack_info = body['links'].find { |link| link['relation'] == 'ackAll' }
         | 
| 131 | 
            +
                      return unless ack_info
         | 
| 132 | 
            +
                      ack_uri = ack_info['uri']
         | 
| 133 | 
            +
                      events = body['entries'].map do |entry|
         | 
| 134 | 
            +
                        deserialize_event(entry)
         | 
| 135 | 
            +
                      end
         | 
| 136 | 
            +
                      { ack_uri: ack_uri, events: events }
         | 
| 94 137 | 
             
                    end
         | 
| 95 138 |  | 
| 96 139 | 
             
                    def link_to(stream_name, events, expected_version: nil)
         | 
| @@ -106,7 +149,7 @@ module EventStoreClient | |
| 106 149 | 
             
                        headers: headers
         | 
| 107 150 | 
             
                      )
         | 
| 108 151 | 
             
                      validate_response(response, expected_version)
         | 
| 109 | 
            -
                       | 
| 152 | 
            +
                      true
         | 
| 110 153 | 
             
                    end
         | 
| 111 154 |  | 
| 112 155 | 
             
                    def ack(url)
         | 
| @@ -115,11 +158,12 @@ module EventStoreClient | |
| 115 158 |  | 
| 116 159 | 
             
                    private
         | 
| 117 160 |  | 
| 118 | 
            -
                    attr_reader : | 
| 161 | 
            +
                    attr_reader :uri, :per_page, :connection_options, :mapper
         | 
| 119 162 |  | 
| 120 | 
            -
                    def initialize( | 
| 121 | 
            -
                      @ | 
| 163 | 
            +
                    def initialize(uri, per_page: 20, mapper:, connection_options: {})
         | 
| 164 | 
            +
                      @uri = uri
         | 
| 122 165 | 
             
                      @per_page = per_page
         | 
| 166 | 
            +
                      @mapper = mapper
         | 
| 123 167 | 
             
                      @connection_options = connection_options
         | 
| 124 168 | 
             
                    end
         | 
| 125 169 |  | 
| @@ -154,7 +198,7 @@ module EventStoreClient | |
| 154 198 | 
             
                    end
         | 
| 155 199 |  | 
| 156 200 | 
             
                    def connection
         | 
| 157 | 
            -
                      @connection ||= Api::Connection.new( | 
| 201 | 
            +
                      @connection ||= Api::Connection.new(uri, connection_options).call
         | 
| 158 202 | 
             
                    end
         | 
| 159 203 |  | 
| 160 204 | 
             
                    def validate_response(resp, expected_version)
         | 
| @@ -164,6 +208,18 @@ module EventStoreClient | |
| 164 208 | 
             
                        "expected: #{expected_version}"
         | 
| 165 209 | 
             
                      )
         | 
| 166 210 | 
             
                    end
         | 
| 211 | 
            +
             | 
| 212 | 
            +
                    def deserialize_event(entry)
         | 
| 213 | 
            +
                      event = EventStoreClient::Event.new(
         | 
| 214 | 
            +
                        id: entry['eventId'],
         | 
| 215 | 
            +
                        title: entry['title'],
         | 
| 216 | 
            +
                        type: entry['eventType'],
         | 
| 217 | 
            +
                        data: entry['data'] || '{}',
         | 
| 218 | 
            +
                        metadata: entry['isMetaData'] ? entry['metaData'] : '{}'
         | 
| 219 | 
            +
                      )
         | 
| 220 | 
            +
             | 
| 221 | 
            +
                      mapper.deserialize(event)
         | 
| 222 | 
            +
                    end
         | 
| 167 223 | 
             
                  end
         | 
| 168 224 | 
             
                end
         | 
| 169 225 | 
             
              end
         | 
| @@ -9,23 +9,27 @@ module EventStoreClient | |
| 9 9 | 
             
                    def call
         | 
| 10 10 | 
             
                      Faraday.new(
         | 
| 11 11 | 
             
                        {
         | 
| 12 | 
            -
                          url:  | 
| 12 | 
            +
                          url: uri.to_s,
         | 
| 13 13 | 
             
                          headers: DEFAULT_HEADERS
         | 
| 14 14 | 
             
                        }.merge(options)
         | 
| 15 15 | 
             
                      ) do |conn|
         | 
| 16 | 
            -
                        conn.basic_auth( | 
| 16 | 
            +
                        conn.basic_auth(config.eventstore_user, config.eventstore_password)
         | 
| 17 17 | 
             
                        conn.adapter Faraday.default_adapter
         | 
| 18 18 | 
             
                      end
         | 
| 19 19 | 
             
                    end
         | 
| 20 20 |  | 
| 21 21 | 
             
                    private
         | 
| 22 22 |  | 
| 23 | 
            -
                    def  | 
| 24 | 
            -
                       | 
| 23 | 
            +
                    def config
         | 
| 24 | 
            +
                      EventStoreClient.config
         | 
| 25 | 
            +
                    end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                    def initialize(uri, options = {})
         | 
| 28 | 
            +
                      @uri = uri
         | 
| 25 29 | 
             
                      @options = options
         | 
| 26 30 | 
             
                    end
         | 
| 27 31 |  | 
| 28 | 
            -
                    attr_reader : | 
| 32 | 
            +
                    attr_reader :uri, :options
         | 
| 29 33 |  | 
| 30 34 | 
             
                    DEFAULT_HEADERS = {
         | 
| 31 35 | 
             
                      'Content-Type' => 'application/vnd.eventstore.events+json'
         | 
| @@ -33,7 +33,27 @@ module EventStoreClient | |
| 33 33 | 
             
                        read_stream_backward(stream_name, start: start)
         | 
| 34 34 | 
             
                      end
         | 
| 35 35 |  | 
| 36 | 
            -
                    Response.new(response.to_json, 200)
         | 
| 36 | 
            +
                    res = Response.new(response.to_json, 200)
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                    return [] if res.body.nil? || res.body.empty?
         | 
| 39 | 
            +
                    JSON.parse(res.body)['entries'].map do |entry|
         | 
| 40 | 
            +
                      deserialize_event(entry)
         | 
| 41 | 
            +
                    end.reverse
         | 
| 42 | 
            +
                  end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                  def read_all_from_stream(stream_name, direction: 'forward', start: 0, resolve_links: true)
         | 
| 45 | 
            +
                    response =
         | 
| 46 | 
            +
                      if direction == 'forward'
         | 
| 47 | 
            +
                        read_stream_forward(stream_name, start: start)
         | 
| 48 | 
            +
                      else
         | 
| 49 | 
            +
                        read_stream_backward(stream_name, start: start)
         | 
| 50 | 
            +
                      end
         | 
| 51 | 
            +
                    res = Response.new(response.to_json, 200)
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                    return [] if res.body.nil? || res.body.empty?
         | 
| 54 | 
            +
                      JSON.parse(res.body)['entries'].map do |entry|
         | 
| 55 | 
            +
                        deserialize_event(entry)
         | 
| 56 | 
            +
                      end.reverse
         | 
| 37 57 | 
             
                  end
         | 
| 38 58 |  | 
| 39 59 | 
             
                  def subscribe_to_stream(stream_name, subscription_name, **)
         | 
| @@ -54,6 +74,7 @@ module EventStoreClient | |
| 54 74 |  | 
| 55 75 | 
             
                  def link_to(stream_name, events, **)
         | 
| 56 76 | 
             
                    append_to_stream(stream_name, events)
         | 
| 77 | 
            +
                    events
         | 
| 57 78 | 
             
                  end
         | 
| 58 79 |  | 
| 59 80 | 
             
                  def ack(url)
         | 
| @@ -64,11 +85,11 @@ module EventStoreClient | |
| 64 85 |  | 
| 65 86 | 
             
                  private
         | 
| 66 87 |  | 
| 67 | 
            -
                  attr_reader : | 
| 88 | 
            +
                  attr_reader :per_page, :mapper
         | 
| 68 89 |  | 
| 69 | 
            -
                  def initialize( | 
| 70 | 
            -
                    @endpoint = Endpoint.new(host: host, port: port)
         | 
| 90 | 
            +
                  def initialize(mapper:, per_page: 20)
         | 
| 71 91 | 
             
                    @per_page = per_page
         | 
| 92 | 
            +
                    @mapper = mapper
         | 
| 72 93 | 
             
                    @event_store = {}
         | 
| 73 94 | 
             
                  end
         | 
| 74 95 |  | 
| @@ -115,11 +136,25 @@ module EventStoreClient | |
| 115 136 | 
             
                    else
         | 
| 116 137 | 
             
                      [{
         | 
| 117 138 | 
             
                        'uri' =>
         | 
| 118 | 
            -
                          " | 
| 139 | 
            +
                          "/streams/#{stream_name}/#{batch_size}/#{direction}/#{count}",
         | 
| 119 140 | 
             
                        'relation' => direction
         | 
| 120 141 | 
             
                      }]
         | 
| 121 142 | 
             
                    end
         | 
| 122 143 | 
             
                  end
         | 
| 144 | 
            +
             | 
| 145 | 
            +
                  private
         | 
| 146 | 
            +
             | 
| 147 | 
            +
                  def deserialize_event(entry)
         | 
| 148 | 
            +
                    event = EventStoreClient::Event.new(
         | 
| 149 | 
            +
                      id: entry['eventId'],
         | 
| 150 | 
            +
                      title: entry['title'],
         | 
| 151 | 
            +
                      type: entry['eventType'],
         | 
| 152 | 
            +
                      data: entry['data'] || '{}',
         | 
| 153 | 
            +
                      metadata: entry['isMetaData'] ? entry['metaData'] : '{}'
         | 
| 154 | 
            +
                    )
         | 
| 155 | 
            +
             | 
| 156 | 
            +
                    mapper.deserialize(event)
         | 
| 157 | 
            +
                  end
         | 
| 123 158 | 
             
                end
         | 
| 124 159 | 
             
              end
         | 
| 125 160 | 
             
            end
         | 
| @@ -25,8 +25,9 @@ module EventStoreClient | |
| 25 25 | 
             
                private
         | 
| 26 26 |  | 
| 27 27 | 
             
                def create_subscription(subscription)
         | 
| 28 | 
            +
                  # store position somewhere.
         | 
| 28 29 | 
             
                  connection.join_streams(subscription.name, subscription.observed_streams)
         | 
| 29 | 
            -
                  connection. | 
| 30 | 
            +
                  connection.subscribe_to_stream(subscription.stream, name: subscription.name)
         | 
| 30 31 | 
             
                end
         | 
| 31 32 |  | 
| 32 33 | 
             
                attr_reader :connection, :subscriptions, :service
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: event_store_client
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.2. | 
| 4 | 
            +
              version: 0.2.4
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Sebastian Wilgosz
         | 
| 8 8 | 
             
            autorequire:
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2020- | 
| 11 | 
            +
            date: 2020-12-16 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: dry-schema
         | 
| @@ -42,16 +42,16 @@ dependencies: | |
| 42 42 | 
             
              name: faraday
         | 
| 43 43 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 44 44 | 
             
                requirements:
         | 
| 45 | 
            -
                - - " | 
| 45 | 
            +
                - - "~>"
         | 
| 46 46 | 
             
                  - !ruby/object:Gem::Version
         | 
| 47 | 
            -
                    version:  | 
| 47 | 
            +
                    version: '1.0'
         | 
| 48 48 | 
             
              type: :runtime
         | 
| 49 49 | 
             
              prerelease: false
         | 
| 50 50 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 51 51 | 
             
                requirements:
         | 
| 52 | 
            -
                - - " | 
| 52 | 
            +
                - - "~>"
         | 
| 53 53 | 
             
                  - !ruby/object:Gem::Version
         | 
| 54 | 
            -
                    version:  | 
| 54 | 
            +
                    version: '1.0'
         | 
| 55 55 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 56 56 | 
             
              name: rss
         | 
| 57 57 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -66,6 +66,20 @@ dependencies: | |
| 66 66 | 
             
                - - ">="
         | 
| 67 67 | 
             
                  - !ruby/object:Gem::Version
         | 
| 68 68 | 
             
                    version: 0.2.8
         | 
| 69 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 70 | 
            +
              name: dry-configurable
         | 
| 71 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 72 | 
            +
                requirements:
         | 
| 73 | 
            +
                - - ">="
         | 
| 74 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 75 | 
            +
                    version: '0.11'
         | 
| 76 | 
            +
              type: :runtime
         | 
| 77 | 
            +
              prerelease: false
         | 
| 78 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 79 | 
            +
                requirements:
         | 
| 80 | 
            +
                - - ">="
         | 
| 81 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 82 | 
            +
                    version: '0.11'
         | 
| 69 83 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 70 84 | 
             
              name: rspec
         | 
| 71 85 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -108,12 +122,10 @@ files: | |
| 108 122 | 
             
            - lib/event_store_client/broker.rb
         | 
| 109 123 | 
             
            - lib/event_store_client/client.rb
         | 
| 110 124 | 
             
            - lib/event_store_client/configuration.rb
         | 
| 111 | 
            -
            - lib/event_store_client/connection.rb
         | 
| 112 125 | 
             
            - lib/event_store_client/data_decryptor.rb
         | 
| 113 126 | 
             
            - lib/event_store_client/data_encryptor.rb
         | 
| 114 127 | 
             
            - lib/event_store_client/deserialized_event.rb
         | 
| 115 128 | 
             
            - lib/event_store_client/encryption_metadata.rb
         | 
| 116 | 
            -
            - lib/event_store_client/endpoint.rb
         | 
| 117 129 | 
             
            - lib/event_store_client/event.rb
         | 
| 118 130 | 
             
            - lib/event_store_client/mapper.rb
         | 
| 119 131 | 
             
            - lib/event_store_client/mapper/default.rb
         | 
| @@ -148,7 +160,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 148 160 | 
             
                - !ruby/object:Gem::Version
         | 
| 149 161 | 
             
                  version: '0'
         | 
| 150 162 | 
             
            requirements: []
         | 
| 151 | 
            -
            rubygems_version: 3. | 
| 163 | 
            +
            rubygems_version: 3.1.4
         | 
| 152 164 | 
             
            signing_key:
         | 
| 153 165 | 
             
            specification_version: 4
         | 
| 154 166 | 
             
            summary: Ruby integration for https://eventstore.org
         | 
| @@ -1,112 +0,0 @@ | |
| 1 | 
            -
            # frozen_string_literal: true
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            module EventStoreClient
         | 
| 4 | 
            -
              class Connection
         | 
| 5 | 
            -
                def publish(stream:, events:, expected_version: nil)
         | 
| 6 | 
            -
                  serialized_events = events.map { |event| mapper.serialize(event) }
         | 
| 7 | 
            -
                  client.append_to_stream(
         | 
| 8 | 
            -
                    stream, serialized_events, expected_version: expected_version
         | 
| 9 | 
            -
                  )
         | 
| 10 | 
            -
                  serialized_events
         | 
| 11 | 
            -
                end
         | 
| 12 | 
            -
             | 
| 13 | 
            -
                def read(stream, direction:, start:, all:, resolve_links: true)
         | 
| 14 | 
            -
                  return read_all_from_stream(stream, start: start, resolve_links: resolve_links) if all
         | 
| 15 | 
            -
                  read_from_stream(
         | 
| 16 | 
            -
                    stream, direction: direction, start: start, resolve_links: resolve_links
         | 
| 17 | 
            -
                  )
         | 
| 18 | 
            -
                end
         | 
| 19 | 
            -
             | 
| 20 | 
            -
                def delete_stream(stream); end
         | 
| 21 | 
            -
             | 
| 22 | 
            -
                def join_streams(name, streams)
         | 
| 23 | 
            -
                  client.join_streams(name, streams)
         | 
| 24 | 
            -
                end
         | 
| 25 | 
            -
             | 
| 26 | 
            -
                def subscribe(stream, name:)
         | 
| 27 | 
            -
                  client.subscribe_to_stream(stream, name)
         | 
| 28 | 
            -
                end
         | 
| 29 | 
            -
             | 
| 30 | 
            -
                def consume_feed(stream, subscription)
         | 
| 31 | 
            -
                  response = client.consume_feed(stream, subscription)
         | 
| 32 | 
            -
                  return [] unless response.body
         | 
| 33 | 
            -
                  body = JSON.parse(response.body)
         | 
| 34 | 
            -
             | 
| 35 | 
            -
                  ack = body['links'].find { |link| link['relation'] == 'ackAll' }
         | 
| 36 | 
            -
                  return unless ack
         | 
| 37 | 
            -
                  ack_uri = ack['uri']
         | 
| 38 | 
            -
                  events = body['entries'].map do |entry|
         | 
| 39 | 
            -
                    deserialize_event(entry)
         | 
| 40 | 
            -
                  end
         | 
| 41 | 
            -
                  client.ack(ack_uri)
         | 
| 42 | 
            -
                  events
         | 
| 43 | 
            -
                end
         | 
| 44 | 
            -
             | 
| 45 | 
            -
                def link_to(stream, events, expected_version: nil)
         | 
| 46 | 
            -
                  client.link_to(stream, events, expected_version: expected_version)
         | 
| 47 | 
            -
             | 
| 48 | 
            -
                  true
         | 
| 49 | 
            -
                end
         | 
| 50 | 
            -
             | 
| 51 | 
            -
                private
         | 
| 52 | 
            -
             | 
| 53 | 
            -
                attr_reader :mapper, :per_page, :client
         | 
| 54 | 
            -
             | 
| 55 | 
            -
                def config
         | 
| 56 | 
            -
                  EventStoreClient::Configuration.instance
         | 
| 57 | 
            -
                end
         | 
| 58 | 
            -
             | 
| 59 | 
            -
                def initialize
         | 
| 60 | 
            -
                  @per_page = config.per_page
         | 
| 61 | 
            -
                  @mapper = config.mapper
         | 
| 62 | 
            -
                  @client = config.adapter
         | 
| 63 | 
            -
                end
         | 
| 64 | 
            -
             | 
| 65 | 
            -
                def read_from_stream(stream, direction:, start:, resolve_links:)
         | 
| 66 | 
            -
                  response =
         | 
| 67 | 
            -
                    client.read(
         | 
| 68 | 
            -
                      stream, start: start, direction: direction, resolve_links: resolve_links
         | 
| 69 | 
            -
                    )
         | 
| 70 | 
            -
                  return [] if response.body.nil? || response.body.empty?
         | 
| 71 | 
            -
                  JSON.parse(response.body)['entries'].map do |entry|
         | 
| 72 | 
            -
                    deserialize_event(entry)
         | 
| 73 | 
            -
                  end.reverse
         | 
| 74 | 
            -
                end
         | 
| 75 | 
            -
             | 
| 76 | 
            -
                def read_all_from_stream(stream, start:, resolve_links:)
         | 
| 77 | 
            -
                  count = per_page
         | 
| 78 | 
            -
                  events = []
         | 
| 79 | 
            -
                  failed_requests_count = 0
         | 
| 80 | 
            -
             | 
| 81 | 
            -
                  while failed_requests_count < 3
         | 
| 82 | 
            -
                    begin
         | 
| 83 | 
            -
                      response =
         | 
| 84 | 
            -
                        client.read(stream, start: start, direction: 'forward', resolve_links: resolve_links)
         | 
| 85 | 
            -
                      failed_requests_count += 1 && next unless response.success? || response.status == 404
         | 
| 86 | 
            -
                    rescue Faraday::ConnectionFailed
         | 
| 87 | 
            -
                      failed_requests_count += 1
         | 
| 88 | 
            -
                      next
         | 
| 89 | 
            -
                    end
         | 
| 90 | 
            -
                    failed_requests_count = 0
         | 
| 91 | 
            -
                    break if response.body.nil? || response.body.empty?
         | 
| 92 | 
            -
                    entries = JSON.parse(response.body)['entries']
         | 
| 93 | 
            -
                    break if entries.empty?
         | 
| 94 | 
            -
                    events += entries.map { |entry| deserialize_event(entry) }.reverse
         | 
| 95 | 
            -
                    start += count
         | 
| 96 | 
            -
                  end
         | 
| 97 | 
            -
                  events
         | 
| 98 | 
            -
                end
         | 
| 99 | 
            -
             | 
| 100 | 
            -
                def deserialize_event(entry)
         | 
| 101 | 
            -
                  event = EventStoreClient::Event.new(
         | 
| 102 | 
            -
                    id: entry['eventId'],
         | 
| 103 | 
            -
                    title: entry['title'],
         | 
| 104 | 
            -
                    type: entry['eventType'],
         | 
| 105 | 
            -
                    data: entry['data'] || '{}',
         | 
| 106 | 
            -
                    metadata: entry['isMetaData'] ? entry['metaData'] : '{}'
         | 
| 107 | 
            -
                  )
         | 
| 108 | 
            -
             | 
| 109 | 
            -
                  mapper.deserialize(event)
         | 
| 110 | 
            -
                end
         | 
| 111 | 
            -
              end
         | 
| 112 | 
            -
            end
         |