evt-event_source-event_store-http 0.1.1.0 → 0.2.0.0.pre1
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_source/event_store/http.rb +10 -9
- data/lib/event_source/event_store/http/controls.rb +23 -3
- data/lib/event_source/event_store/http/controls/cluster_members.rb +9 -0
- data/lib/event_source/event_store/http/controls/event_data/write.rb +1 -0
- data/lib/event_source/event_store/http/controls/expected_version.rb +31 -0
- data/lib/event_source/event_store/http/controls/hostname.rb +13 -0
- data/lib/event_source/event_store/http/controls/hostname/cluster.rb +15 -0
- data/lib/event_source/event_store/http/controls/ip_address/cluster.rb +25 -0
- data/lib/event_source/event_store/http/controls/{category.rb → port.rb} +1 -1
- data/lib/event_source/event_store/http/controls/resolve_host.rb +9 -0
- data/lib/event_source/event_store/http/controls/session/request/require_leader.rb +41 -0
- data/lib/event_source/event_store/http/controls/session/request/write_event.rb +17 -0
- data/lib/event_source/event_store/http/controls/settings.rb +9 -0
- data/lib/event_source/event_store/http/controls/settings/cluster.rb +19 -0
- data/lib/event_source/event_store/http/controls/write.rb +9 -27
- data/lib/event_source/event_store/http/log.rb +0 -1
- data/lib/event_source/event_store/http/request.rb +27 -0
- data/lib/event_source/event_store/http/request/get.rb +64 -0
- data/lib/event_source/event_store/http/request/post.rb +79 -0
- data/lib/event_source/event_store/http/session.rb +63 -113
- data/lib/event_source/event_store/http/session/build.rb +28 -0
- data/lib/event_source/event_store/http/session/configure.rb +22 -0
- data/lib/event_source/event_store/http/session/defaults.rb +19 -0
- data/lib/event_source/event_store/http/session/log_text.rb +41 -0
- data/lib/event_source/event_store/http/session/substitute.rb +20 -30
- data/lib/event_source/event_store/http/session/telemetry.rb +61 -12
- data/lib/event_source/event_store/http/settings.rb +1 -21
- metadata +23 -21
- data/lib/event_source/event_store/http/session/net_http.rb +0 -100
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 6df13c6a49692d92c120afdb88275ad362527ef1
         | 
| 4 | 
            +
              data.tar.gz: 409562ee8c2c8893f87e3bceeecd9966502e9bd7
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: f83a2e956dbd796a73f69f368408496816d270b6d87b0d14e88af0f498c7eb5fb330f73a07c1e796d48815ba04e15bb8c439160982f17610c3d3e1b504a4871e
         | 
| 7 | 
            +
              data.tar.gz: b82c62cf7c53332336722f1af0bed906ecd9efa2a3b0feec9e936da636a92bfbd0e580efe7747a3ba9e89b7fc8343b2dae214c06e0da1e6d2e41ae058a16a84e
         | 
| @@ -1,17 +1,18 @@ | |
| 1 | 
            -
            require 'net/http'
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            require 'configure'; Configure.activate
         | 
| 4 1 | 
             
            require 'event_source'
         | 
| 5 | 
            -
            require ' | 
| 6 | 
            -
            require 'settings'; Settings.activate
         | 
| 2 | 
            +
            require 'event_store/cluster/leader_status'
         | 
| 7 3 |  | 
| 8 4 | 
             
            require 'event_source/event_store/http/log'
         | 
| 9 | 
            -
             | 
| 10 5 | 
             
            require 'event_source/event_store/http/media_types'
         | 
| 6 | 
            +
            require 'event_source/event_store/http/settings'
         | 
| 11 7 |  | 
| 12 | 
            -
            require 'event_source/event_store/http/session/ | 
| 13 | 
            -
            require 'event_source/event_store/http/session/ | 
| 8 | 
            +
            require 'event_source/event_store/http/session/build'
         | 
| 9 | 
            +
            require 'event_source/event_store/http/session/configure'
         | 
| 10 | 
            +
            require 'event_source/event_store/http/session/defaults'
         | 
| 11 | 
            +
            require 'event_source/event_store/http/session/log_text'
         | 
| 14 12 | 
             
            require 'event_source/event_store/http/session/substitute'
         | 
| 13 | 
            +
            require 'event_source/event_store/http/session/telemetry'
         | 
| 15 14 | 
             
            require 'event_source/event_store/http/session'
         | 
| 16 15 |  | 
| 17 | 
            -
            require 'event_source/event_store/http/ | 
| 16 | 
            +
            require 'event_source/event_store/http/request'
         | 
| 17 | 
            +
            require 'event_source/event_store/http/request/get'
         | 
| 18 | 
            +
            require 'event_source/event_store/http/request/post'
         | 
| @@ -1,13 +1,33 @@ | |
| 1 1 | 
             
            require 'identifier/uuid/controls'
         | 
| 2 2 | 
             
            require 'event_source/controls'
         | 
| 3 | 
            +
            require 'event_store/cluster/leader_status/controls'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            require 'event_source/event_store/http/controls/uuid'
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            require 'event_source/event_store/http/controls/media_type'
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            require 'event_source/event_store/http/controls/resolve_host'
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            require 'event_source/event_store/http/controls/cluster_members'
         | 
| 12 | 
            +
            require 'event_source/event_store/http/controls/hostname'
         | 
| 13 | 
            +
            require 'event_source/event_store/http/controls/hostname/cluster'
         | 
| 14 | 
            +
            require 'event_source/event_store/http/controls/ip_address/cluster'
         | 
| 15 | 
            +
            require 'event_source/event_store/http/controls/port'
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            require 'event_source/event_store/http/controls/settings'
         | 
| 18 | 
            +
            require 'event_source/event_store/http/controls/settings/cluster'
         | 
| 19 | 
            +
             | 
| 20 | 
            +
            require 'event_source/event_store/http/controls/session/request/require_leader'
         | 
| 21 | 
            +
            require 'event_source/event_store/http/controls/session/request/write_event'
         | 
| 3 22 |  | 
| 4 | 
            -
            require 'event_source/event_store/http/controls/category'
         | 
| 5 23 | 
             
            require 'event_source/event_store/http/controls/event_data'
         | 
| 6 24 | 
             
            require 'event_source/event_store/http/controls/event_data/event_id'
         | 
| 7 25 | 
             
            require 'event_source/event_store/http/controls/event_data/write'
         | 
| 8 | 
            -
             | 
| 26 | 
            +
             | 
| 9 27 | 
             
            require 'event_source/event_store/http/controls/stream'
         | 
| 10 28 | 
             
            require 'event_source/event_store/http/controls/stream_name'
         | 
| 11 29 | 
             
            require 'event_source/event_store/http/controls/uri/path'
         | 
| 12 | 
            -
             | 
| 30 | 
            +
             | 
| 31 | 
            +
            require 'event_source/event_store/http/controls/expected_version'
         | 
| 32 | 
            +
             | 
| 13 33 | 
             
            require 'event_source/event_store/http/controls/write'
         | 
| @@ -0,0 +1,31 @@ | |
| 1 | 
            +
            module EventSource
         | 
| 2 | 
            +
              module EventStore
         | 
| 3 | 
            +
                module HTTP
         | 
| 4 | 
            +
                  module Controls
         | 
| 5 | 
            +
                    module ExpectedVersion
         | 
| 6 | 
            +
                      def self.example
         | 
| 7 | 
            +
                        11
         | 
| 8 | 
            +
                      end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                      module Header
         | 
| 11 | 
            +
                        def self.example
         | 
| 12 | 
            +
                          '11'
         | 
| 13 | 
            +
                        end
         | 
| 14 | 
            +
                      end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                      module NoStream
         | 
| 17 | 
            +
                        def self.example
         | 
| 18 | 
            +
                          :no_stream
         | 
| 19 | 
            +
                        end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                        module Header
         | 
| 22 | 
            +
                          def self.example
         | 
| 23 | 
            +
                            '-1'
         | 
| 24 | 
            +
                          end
         | 
| 25 | 
            +
                        end
         | 
| 26 | 
            +
                      end
         | 
| 27 | 
            +
                    end
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
            end
         | 
| @@ -0,0 +1,25 @@ | |
| 1 | 
            +
            module EventSource
         | 
| 2 | 
            +
              module EventStore
         | 
| 3 | 
            +
                module HTTP
         | 
| 4 | 
            +
                  module Controls
         | 
| 5 | 
            +
                    module IPAddress
         | 
| 6 | 
            +
                      def self.example
         | 
| 7 | 
            +
                        '127.0.0.1'
         | 
| 8 | 
            +
                      end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                      Cluster = ::EventStore::Cluster::LeaderStatus::Controls::IPAddress
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                      module Cluster
         | 
| 13 | 
            +
                        module Leader
         | 
| 14 | 
            +
                          def self.get
         | 
| 15 | 
            +
                            leader_ip_address, * = ::EventStore::Cluster::LeaderStatus::Controls::CurrentMembers.get
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                            leader_ip_address
         | 
| 18 | 
            +
                          end
         | 
| 19 | 
            +
                        end
         | 
| 20 | 
            +
                      end
         | 
| 21 | 
            +
                    end
         | 
| 22 | 
            +
                  end
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
            end
         | 
| @@ -0,0 +1,41 @@ | |
| 1 | 
            +
            module EventSource
         | 
| 2 | 
            +
              module EventStore
         | 
| 3 | 
            +
                module HTTP
         | 
| 4 | 
            +
                  module Controls
         | 
| 5 | 
            +
                    module Session
         | 
| 6 | 
            +
                      module Request
         | 
| 7 | 
            +
                        module WriteEvent
         | 
| 8 | 
            +
                          def self.example(data: nil, metadata: nil, type: nil, stream_name: nil, headers: nil)
         | 
| 9 | 
            +
                            stream_name ||= StreamName.example
         | 
| 10 | 
            +
                            headers ||= {}
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                            event_data = EventData::Write.example(
         | 
| 13 | 
            +
                              type: type,
         | 
| 14 | 
            +
                              data: data,
         | 
| 15 | 
            +
                              metadata: metadata
         | 
| 16 | 
            +
                            )
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                            request_body = JSON.pretty_generate [
         | 
| 19 | 
            +
                              {
         | 
| 20 | 
            +
                                'eventId' => Identifier::UUID::Random.get,
         | 
| 21 | 
            +
                                'eventType' => event_data.type,
         | 
| 22 | 
            +
                                'data' => event_data.data,
         | 
| 23 | 
            +
                                'metadata' => event_data.metadata
         | 
| 24 | 
            +
                              }
         | 
| 25 | 
            +
                            ]
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                            headers['Content-Type'] ||= MediaTypes.vnd_event_store_events_json
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                            path = "/streams/#{stream_name}"
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                            post = Net::HTTP::Post.new path, headers
         | 
| 32 | 
            +
                            post.body = request_body
         | 
| 33 | 
            +
                            post
         | 
| 34 | 
            +
                          end
         | 
| 35 | 
            +
                        end
         | 
| 36 | 
            +
                      end
         | 
| 37 | 
            +
                    end
         | 
| 38 | 
            +
                  end
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
              end
         | 
| 41 | 
            +
            end
         | 
| @@ -0,0 +1,17 @@ | |
| 1 | 
            +
            module EventSource
         | 
| 2 | 
            +
              module EventStore
         | 
| 3 | 
            +
                module HTTP
         | 
| 4 | 
            +
                  module Controls
         | 
| 5 | 
            +
                    module Session
         | 
| 6 | 
            +
                      module Request
         | 
| 7 | 
            +
                        module RequireLeader
         | 
| 8 | 
            +
                          def self.example
         | 
| 9 | 
            +
                            WriteEvent.example headers: { 'ES-RequireMaster' => 'true' }
         | 
| 10 | 
            +
                          end
         | 
| 11 | 
            +
                        end
         | 
| 12 | 
            +
                      end
         | 
| 13 | 
            +
                    end
         | 
| 14 | 
            +
                  end
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
            end
         | 
| @@ -0,0 +1,19 @@ | |
| 1 | 
            +
            module EventSource
         | 
| 2 | 
            +
              module EventStore
         | 
| 3 | 
            +
                module HTTP
         | 
| 4 | 
            +
                  module Controls
         | 
| 5 | 
            +
                    module Settings
         | 
| 6 | 
            +
                      module Cluster
         | 
| 7 | 
            +
                        def self.example
         | 
| 8 | 
            +
                          host = ::EventStore::Cluster::LeaderStatus::Controls::Hostname.example
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                          HTTP::Settings.build({
         | 
| 11 | 
            +
                            :host => host
         | 
| 12 | 
            +
                          })
         | 
| 13 | 
            +
                        end
         | 
| 14 | 
            +
                      end
         | 
| 15 | 
            +
                    end
         | 
| 16 | 
            +
                  end
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
            end
         | 
| @@ -7,34 +7,15 @@ module EventSource | |
| 7 7 | 
             
                        event_count ||= 1
         | 
| 8 8 | 
             
                        stream_name ||= StreamName.example
         | 
| 9 9 |  | 
| 10 | 
            -
                         | 
| 11 | 
            -
             | 
| 10 | 
            +
                        ::EventStore::HTTP::Connect.() do |http|
         | 
| 11 | 
            +
                          post = Session::Request::WriteEvent.example(
         | 
| 12 | 
            +
                            type: type,
         | 
| 13 | 
            +
                            data: data,
         | 
| 14 | 
            +
                            metadata: metadata,
         | 
| 15 | 
            +
                            stream_name: stream_name
         | 
| 16 | 
            +
                          )
         | 
| 12 17 |  | 
| 13 | 
            -
             | 
| 14 | 
            -
                          type: type,
         | 
| 15 | 
            -
                          data: data,
         | 
| 16 | 
            -
                          metadata: metadata
         | 
| 17 | 
            -
                        )
         | 
| 18 | 
            -
             | 
| 19 | 
            -
                        Net::HTTP.start host, port do |http|
         | 
| 20 | 
            -
                          event_datum = (0...event_count).map do
         | 
| 21 | 
            -
                            event_id = Identifier::UUID::Random.get
         | 
| 22 | 
            -
             | 
| 23 | 
            -
                            {
         | 
| 24 | 
            -
                              'eventId' => event_id,
         | 
| 25 | 
            -
                              'eventType' => event_data.type,
         | 
| 26 | 
            -
                              'data' => event_data.data,
         | 
| 27 | 
            -
                              'metadata' => event_data.metadata
         | 
| 28 | 
            -
                            }
         | 
| 29 | 
            -
                          end
         | 
| 30 | 
            -
             | 
| 31 | 
            -
                          headers = { 'Content-Type' => MediaTypes.vnd_event_store_events_json }
         | 
| 32 | 
            -
             | 
| 33 | 
            -
                          path = "/streams/#{stream_name}"
         | 
| 34 | 
            -
             | 
| 35 | 
            -
                          request_body = JSON.pretty_generate event_datum
         | 
| 36 | 
            -
             | 
| 37 | 
            -
                          response = http.request_post path, request_body, headers
         | 
| 18 | 
            +
                          response = http.request post
         | 
| 38 19 |  | 
| 39 20 | 
             
                          unless response.code.to_i == 201
         | 
| 40 21 | 
             
                            fail "Write failed (StatusCode: #{response.code}, ReasonPhrase: #{response.message})"
         | 
| @@ -48,3 +29,4 @@ module EventSource | |
| 48 29 | 
             
                end
         | 
| 49 30 | 
             
              end
         | 
| 50 31 | 
             
            end
         | 
| 32 | 
            +
             | 
| @@ -0,0 +1,27 @@ | |
| 1 | 
            +
            module EventSource
         | 
| 2 | 
            +
              module EventStore
         | 
| 3 | 
            +
                module HTTP
         | 
| 4 | 
            +
                  class Request
         | 
| 5 | 
            +
                    include Log::Dependency
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                    configure :request
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                    dependency :session, Session
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                    def self.build(session: nil)
         | 
| 12 | 
            +
                      instance = new
         | 
| 13 | 
            +
                      Session.configure instance, session: session
         | 
| 14 | 
            +
                      instance
         | 
| 15 | 
            +
                    end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                    abstract :call
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                    abstract :media_type
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                    def headers
         | 
| 22 | 
            +
                      @headers ||= {}
         | 
| 23 | 
            +
                    end
         | 
| 24 | 
            +
                  end
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
            end
         | 
| @@ -0,0 +1,64 @@ | |
| 1 | 
            +
            module EventSource
         | 
| 2 | 
            +
              module EventStore
         | 
| 3 | 
            +
                module HTTP
         | 
| 4 | 
            +
                  class Request
         | 
| 5 | 
            +
                    class Get < Request
         | 
| 6 | 
            +
                      include Log::Dependency
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                      def call(path, &probe)
         | 
| 9 | 
            +
                        log_attributes = "Path: #{path}, MediaType: #{media_type}, Headers: #{headers.inspect}"
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                        logger.trace { "Performing GET request (#{log_attributes}" }
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                        request = Net::HTTP::Get.new path, headers
         | 
| 14 | 
            +
                        request['Accept'] = media_type
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                        response = session.(request, &probe)
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                        log_attributes << ", StatusCode: #{response.code}, ReasonPhrose: #{response.message}"
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                        status_code = response.code.to_i
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                        if (200..399).include? status_code
         | 
| 23 | 
            +
                          response_body = response.body
         | 
| 24 | 
            +
                        elsif status_code == 404
         | 
| 25 | 
            +
                          logger.warn "Get query failed, resource not found (#{log_attributes})"
         | 
| 26 | 
            +
                        else
         | 
| 27 | 
            +
                          error_message = "Get command failed (#{log_attributes})"
         | 
| 28 | 
            +
                          logger.error error_message
         | 
| 29 | 
            +
                          raise Error, error_message
         | 
| 30 | 
            +
                        end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                        logger.debug { "GET request done (#{log_attributes}, StatusCode: #{status_code})" }
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                        return response_body, status_code
         | 
| 35 | 
            +
                      end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                      def enable_long_poll
         | 
| 38 | 
            +
                        headers['ES-LongPoll'] = Defaults.long_poll_duration.to_s
         | 
| 39 | 
            +
                      end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                      def long_poll_enabled?
         | 
| 42 | 
            +
                        headers.key? 'ES-LongPoll'
         | 
| 43 | 
            +
                      end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                      def media_type
         | 
| 46 | 
            +
                        MediaTypes.vnd_event_store_atom_json
         | 
| 47 | 
            +
                      end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                      Error = Class.new StandardError
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                      module Defaults
         | 
| 52 | 
            +
                        def self.long_poll_duration
         | 
| 53 | 
            +
                          duration = ENV['LONG_POLL_DURATION']
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                          return duration.to_i if duration
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                          15
         | 
| 58 | 
            +
                        end
         | 
| 59 | 
            +
                      end
         | 
| 60 | 
            +
                    end
         | 
| 61 | 
            +
                  end
         | 
| 62 | 
            +
                end
         | 
| 63 | 
            +
              end
         | 
| 64 | 
            +
            end
         | 
| @@ -0,0 +1,79 @@ | |
| 1 | 
            +
            module EventSource
         | 
| 2 | 
            +
              module EventStore
         | 
| 3 | 
            +
                module HTTP
         | 
| 4 | 
            +
                  class Request
         | 
| 5 | 
            +
                    class Post < Request
         | 
| 6 | 
            +
                      include Log::Dependency
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                      def call(path, request_body, expected_version: nil, &probe)
         | 
| 9 | 
            +
                        expected_version = -1 if expected_version == Post.no_stream_version
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                        log_attributes = "Path: #{path}, ContentLength: #{request_body.bytesize}, MediaType: #{media_type}, Headers: #{headers.inspect}"
         | 
| 12 | 
            +
                        logger.trace { "Performing GET request (#{log_attributes}" }
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                        request = Net::HTTP::Post.new path, headers
         | 
| 15 | 
            +
                        request['Content-Type'] = media_type
         | 
| 16 | 
            +
                        request['ES-ExpectedVersion'] = expected_version.to_s if expected_version
         | 
| 17 | 
            +
                        request.body = request_body
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                        response = session.(request, &probe)
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                        status_code = response.code.to_i
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                        log_attributes << ", StatusCode: #{status_code}, ReasonPhrase: #{response.message}"
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                        unless (200..299).include? status_code
         | 
| 26 | 
            +
                          if expected_version_error? response
         | 
| 27 | 
            +
                            error_message = "Wrong expected version number (#{log_attributes})"
         | 
| 28 | 
            +
                            error_type = ExpectedVersionError
         | 
| 29 | 
            +
                          end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                          if write_timeout_error? response
         | 
| 32 | 
            +
                            error_message = "Write timeout (#{log_attributes})"
         | 
| 33 | 
            +
                            error_type = WriteTimeoutError
         | 
| 34 | 
            +
                          end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                          error_message ||= "Post command failed (#{log_attributes})"
         | 
| 37 | 
            +
                          error_type ||= Error
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                          logger.error error_message
         | 
| 40 | 
            +
                          raise error_type, error_message
         | 
| 41 | 
            +
                        end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                        logger.debug { "GET request done (#{log_attributes}, StatusCode: #{status_code})" }
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                        return status_code
         | 
| 46 | 
            +
                      end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                      def require_leader
         | 
| 49 | 
            +
                        headers['ES-RequireMaster'] = 'True'
         | 
| 50 | 
            +
                      end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                      def leader_required?
         | 
| 53 | 
            +
                        headers.key? 'ES-RequireMaster'
         | 
| 54 | 
            +
                      end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                      def media_type
         | 
| 57 | 
            +
                        MediaTypes.vnd_event_store_events_json
         | 
| 58 | 
            +
                      end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                      def expected_version_error?(response)
         | 
| 61 | 
            +
                        response.code == '400' && response.message == 'Wrong expected EventNumber'
         | 
| 62 | 
            +
                      end
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                      def write_timeout_error?(response)
         | 
| 65 | 
            +
                        response.code == '500' && response.message == 'Write timeout'
         | 
| 66 | 
            +
                      end
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                      Error = Class.new StandardError
         | 
| 69 | 
            +
                      ExpectedVersionError = Class.new Error
         | 
| 70 | 
            +
                      WriteTimeoutError = Class.new Error
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                      def self.no_stream_version
         | 
| 73 | 
            +
                        :no_stream
         | 
| 74 | 
            +
                      end
         | 
| 75 | 
            +
                    end
         | 
| 76 | 
            +
                  end
         | 
| 77 | 
            +
                end
         | 
| 78 | 
            +
              end
         | 
| 79 | 
            +
            end
         | 
| @@ -4,157 +4,107 @@ module EventSource | |
| 4 4 | 
             
                  class Session
         | 
| 5 5 | 
             
                    include Log::Dependency
         | 
| 6 6 |  | 
| 7 | 
            -
                     | 
| 8 | 
            -
                     | 
| 9 | 
            -
             | 
| 10 | 
            -
                    def self.build(settings=nil, namespace: nil)
         | 
| 11 | 
            -
                      instance = new
         | 
| 7 | 
            +
                    extend Build
         | 
| 8 | 
            +
                    extend Configure
         | 
| 9 | 
            +
                    extend Telemetry::RegisterSink
         | 
| 12 10 |  | 
| 13 | 
            -
             | 
| 14 | 
            -
             | 
| 11 | 
            +
                    attr_writer :connection
         | 
| 12 | 
            +
                    attr_writer :disable_leader_detection
         | 
| 15 13 |  | 
| 16 | 
            -
             | 
| 14 | 
            +
                    def disable_leader_detection
         | 
| 15 | 
            +
                      if @disable_leader_detection.nil?
         | 
| 16 | 
            +
                        @disable_leader_detection = Defaults.disable_leader_detection
         | 
| 17 | 
            +
                      end
         | 
| 17 18 |  | 
| 18 | 
            -
                       | 
| 19 | 
            +
                      @disable_leader_detection
         | 
| 19 20 | 
             
                    end
         | 
| 20 21 |  | 
| 21 | 
            -
                     | 
| 22 | 
            -
             | 
| 22 | 
            +
                    dependency :connect, ::EventStore::HTTP::Connect
         | 
| 23 | 
            +
                    dependency :get_leader_status, ::EventStore::Cluster::LeaderStatus::Get
         | 
| 24 | 
            +
                    dependency :telemetry, ::Telemetry
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                    attr_accessor :host
         | 
| 27 | 
            +
                    attr_accessor :port
         | 
| 23 28 |  | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
                      else
         | 
| 27 | 
            -
                        instance = session
         | 
| 28 | 
            -
                      end
         | 
| 29 | 
            +
                    def call(request, redirect: nil, &probe)
         | 
| 30 | 
            +
                      redirect ||= false
         | 
| 29 31 |  | 
| 30 | 
            -
                       | 
| 32 | 
            +
                      logger.trace(tags: :http) { "Issuing #{request.method} request (#{LogText.request_attributes request})" }
         | 
| 33 | 
            +
                      logger.trace(tag: :data) { LogText.request_body request } if request.request_body_permitted?
         | 
| 31 34 |  | 
| 32 | 
            -
                       | 
| 33 | 
            -
                    end
         | 
| 35 | 
            +
                      response = connection.request request
         | 
| 34 36 |  | 
| 35 | 
            -
             | 
| 36 | 
            -
             | 
| 37 | 
            +
                      if Net::HTTPRedirection === response && !redirect
         | 
| 38 | 
            +
                        logger.debug(tags: :http) { "#{request.method} request received redirect response (#{LogText.request_attributes request}, #{LogText.response_attributes response}, Location: #{response['Location'] || '(none)'})" }
         | 
| 37 39 |  | 
| 38 | 
            -
             | 
| 40 | 
            +
                        location = URI.parse response['Location']
         | 
| 41 | 
            +
                        leader_ip_address = location.host
         | 
| 39 42 |  | 
| 40 | 
            -
             | 
| 41 | 
            -
                    end
         | 
| 43 | 
            +
                        telemetry.record :redirected, Telemetry::Redirected.new(request.path, connection.address, location)
         | 
| 42 44 |  | 
| 43 | 
            -
             | 
| 44 | 
            -
                      logger.trace(tag: [:http, :db_connection]) {
         | 
| 45 | 
            -
                        "Connecting to EventStore (Host: #{host.inspect}, Port: #{port.inspect})"
         | 
| 46 | 
            -
                      }
         | 
| 45 | 
            +
                        establish_connection leader_ip_address
         | 
| 47 46 |  | 
| 48 | 
            -
             | 
| 47 | 
            +
                        request['Host'] = nil
         | 
| 48 | 
            +
                        response = self.(request, redirect: true)
         | 
| 49 49 |  | 
| 50 | 
            -
             | 
| 50 | 
            +
                        return response
         | 
| 51 | 
            +
                      end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                      logger.trace(tags: :http) { "#{request.method} request issued (#{LogText.request_attributes request}, #{LogText.response_attributes response})" }
         | 
| 54 | 
            +
                      logger.trace(tag: :data) { LogText.response_body response }
         | 
| 51 55 |  | 
| 52 | 
            -
                      telemetry.record : | 
| 56 | 
            +
                      telemetry.record :http_request, Telemetry::HTTPRequest.build(request, response)
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                      probe.(response) if probe
         | 
| 53 59 |  | 
| 54 | 
            -
                       | 
| 55 | 
            -
             | 
| 56 | 
            -
                      }
         | 
| 60 | 
            +
                      response
         | 
| 61 | 
            +
                    end
         | 
| 57 62 |  | 
| 58 | 
            -
             | 
| 63 | 
            +
                    def connection
         | 
| 64 | 
            +
                      @connection ||= establish_connection
         | 
| 59 65 | 
             
                    end
         | 
| 60 66 |  | 
| 61 67 | 
             
                    def connected?
         | 
| 62 | 
            -
                       | 
| 68 | 
            +
                      !@connection.nil?
         | 
| 63 69 | 
             
                    end
         | 
| 64 70 |  | 
| 65 71 | 
             
                    def close
         | 
| 66 | 
            -
                       | 
| 67 | 
            -
             | 
| 68 | 
            -
                      net_http.finish
         | 
| 72 | 
            +
                      connection.finish
         | 
| 69 73 |  | 
| 70 | 
            -
                       | 
| 71 | 
            -
             | 
| 72 | 
            -
                      net_http
         | 
| 74 | 
            +
                      self.connection = nil
         | 
| 73 75 | 
             
                    end
         | 
| 74 76 |  | 
| 75 | 
            -
                    def  | 
| 76 | 
            -
                       | 
| 77 | 
            -
             | 
| 78 | 
            -
                      logger.trace(tag: :http) {
         | 
| 79 | 
            -
                        "Issuing GET request (Path: #{path}, MediaType: #{media_type})"
         | 
| 80 | 
            -
                      }
         | 
| 77 | 
            +
                    def establish_connection(leader_ip_address=nil)
         | 
| 78 | 
            +
                      logger.trace { "Establishing connection to EventStore (#{LogText.establishing_connection self, leader_ip_address})" }
         | 
| 81 79 |  | 
| 82 | 
            -
                       | 
| 80 | 
            +
                      close if connected?
         | 
| 83 81 |  | 
| 84 | 
            -
                       | 
| 82 | 
            +
                      unless leader_ip_address || disable_leader_detection
         | 
| 83 | 
            +
                        leader_status_queried_telemetry = Telemetry::LeaderStatusQueried.new
         | 
| 85 84 |  | 
| 86 | 
            -
             | 
| 87 | 
            -
             | 
| 85 | 
            +
                        begin
         | 
| 86 | 
            +
                          leader_status = get_leader_status.()
         | 
| 87 | 
            +
                          leader_ip_address = leader_status.http_ip_address
         | 
| 88 88 |  | 
| 89 | 
            -
             | 
| 90 | 
            -
                        "GET request issued (Path: #{path}, MediaType: #{media_type}, StatusCode: #{status_code}, ReasonPhrase: #{response.message}, ContentLength: #{response_body&.bytesize.inspect})"
         | 
| 91 | 
            -
                      }
         | 
| 89 | 
            +
                          leader_status_queried_telemetry.leader_status = leader_status
         | 
| 92 90 |  | 
| 93 | 
            -
             | 
| 94 | 
            -
             | 
| 95 | 
            -
             | 
| 96 | 
            -
                         | 
| 97 | 
            -
                      end
         | 
| 98 | 
            -
             | 
| 99 | 
            -
                      probe.(response) if probe
         | 
| 100 | 
            -
             | 
| 101 | 
            -
                      data = Telemetry::Get.new(
         | 
| 102 | 
            -
                        path,
         | 
| 103 | 
            -
                        status_code,
         | 
| 104 | 
            -
                        response.message,
         | 
| 105 | 
            -
                        response.body,
         | 
| 106 | 
            -
                        media_type
         | 
| 107 | 
            -
                      )
         | 
| 108 | 
            -
             | 
| 109 | 
            -
                      telemetry.record :get, data
         | 
| 110 | 
            -
             | 
| 111 | 
            -
                      return status_code, response_body
         | 
| 112 | 
            -
                    end
         | 
| 113 | 
            -
             | 
| 114 | 
            -
                    def post(path, request_body, media_type, headers=nil, &probe)
         | 
| 115 | 
            -
                      headers ||= {}
         | 
| 116 | 
            -
                      headers['Content-Type'] = media_type
         | 
| 91 | 
            +
                        rescue ::EventStore::Cluster::LeaderStatus::GossipEndpoint::Get::NonClusterError => error
         | 
| 92 | 
            +
                          leader_status_queried_telemetry.error = error
         | 
| 93 | 
            +
                          logger.warn { "Could not determine cluster leader (#{LogText.establishing_connection self, leader_ip_address}, Error: #{error.class})" }
         | 
| 94 | 
            +
                        end
         | 
| 117 95 |  | 
| 118 | 
            -
             | 
| 119 | 
            -
                        "Issuing POST request (Path: #{path}, MediaType: #{media_type}, ContentLength: #{request_body.bytesize})"
         | 
| 120 | 
            -
                      }
         | 
| 121 | 
            -
                      logger.trace(tags: [:data]) { "Request:\n\n#{request_body}" }
         | 
| 122 | 
            -
             | 
| 123 | 
            -
                      response = net_http.request_post path, request_body, headers
         | 
| 124 | 
            -
             | 
| 125 | 
            -
                      status_code = response.code.to_i
         | 
| 126 | 
            -
             | 
| 127 | 
            -
                      logger.debug(tag: :http) {
         | 
| 128 | 
            -
                        "POST request issued (Path: #{path}, MediaType: #{media_type}, ContentLength: #{request_body.bytesize}, StatusCode: #{status_code}, ReasonPhrase: #{response.message})"
         | 
| 129 | 
            -
                      }
         | 
| 130 | 
            -
             | 
| 131 | 
            -
                      if response.body.empty?
         | 
| 132 | 
            -
                        logger.debug(tags: [:data]) { "Response: (none)" }
         | 
| 133 | 
            -
                      else
         | 
| 134 | 
            -
                        logger.debug(tags: [:data]) { "Response:\n\n#{response.body}" }
         | 
| 96 | 
            +
                        telemetry.record :leader_status_queried, leader_status_queried_telemetry
         | 
| 135 97 | 
             
                      end
         | 
| 136 98 |  | 
| 137 | 
            -
                       | 
| 138 | 
            -
             | 
| 139 | 
            -
                      data = Telemetry::Post.new(
         | 
| 140 | 
            -
                        path,
         | 
| 141 | 
            -
                        status_code,
         | 
| 142 | 
            -
                        response.message,
         | 
| 143 | 
            -
                        request_body,
         | 
| 144 | 
            -
                        media_type
         | 
| 145 | 
            -
                      )
         | 
| 99 | 
            +
                      connection = connect.(leader_ip_address)
         | 
| 146 100 |  | 
| 147 | 
            -
                      telemetry.record : | 
| 101 | 
            +
                      telemetry.record :connection_established, Telemetry::ConnectionEstablished.new(leader_ip_address || host, port, connection)
         | 
| 148 102 |  | 
| 149 | 
            -
                       | 
| 150 | 
            -
                    end
         | 
| 103 | 
            +
                      logger.debug { "Connection to EventStore established (#{LogText.connection_established self, leader_ip_address})" }
         | 
| 151 104 |  | 
| 152 | 
            -
             | 
| 153 | 
            -
                      net_http.address
         | 
| 154 | 
            -
                    end
         | 
| 105 | 
            +
                      self.connection = connection
         | 
| 155 106 |  | 
| 156 | 
            -
             | 
| 157 | 
            -
                      net_http.port
         | 
| 107 | 
            +
                      connection
         | 
| 158 108 | 
             
                    end
         | 
| 159 109 | 
             
                  end
         | 
| 160 110 | 
             
                end
         | 
| @@ -0,0 +1,28 @@ | |
| 1 | 
            +
            module EventSource
         | 
| 2 | 
            +
              module EventStore
         | 
| 3 | 
            +
                module HTTP
         | 
| 4 | 
            +
                  class Session
         | 
| 5 | 
            +
                    module Build
         | 
| 6 | 
            +
                      def build(settings=nil, namespace: nil)
         | 
| 7 | 
            +
                        instance = new
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                        connect = ::EventStore::HTTP::Connect.configure(
         | 
| 10 | 
            +
                          instance,
         | 
| 11 | 
            +
                          settings,
         | 
| 12 | 
            +
                          namespace: namespace
         | 
| 13 | 
            +
                        )
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                        instance.host = connect.host
         | 
| 16 | 
            +
                        instance.port = connect.port
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                        ::EventStore::Cluster::LeaderStatus::Get.configure instance, connect
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                        ::Telemetry.configure instance
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                        instance
         | 
| 23 | 
            +
                      end
         | 
| 24 | 
            +
                    end
         | 
| 25 | 
            +
                  end
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
              end
         | 
| 28 | 
            +
            end
         | 
| @@ -0,0 +1,22 @@ | |
| 1 | 
            +
            module EventSource
         | 
| 2 | 
            +
              module EventStore
         | 
| 3 | 
            +
                module HTTP
         | 
| 4 | 
            +
                  class Session
         | 
| 5 | 
            +
                    module Configure
         | 
| 6 | 
            +
                      def configure(receiver, settings=nil, namespace: nil, session: nil, attr_name: nil)
         | 
| 7 | 
            +
                        attr_name ||= :session
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                        if session.nil?
         | 
| 10 | 
            +
                          instance = build settings, namespace: namespace
         | 
| 11 | 
            +
                        else
         | 
| 12 | 
            +
                          instance = session
         | 
| 13 | 
            +
                        end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                        receiver.public_send "#{attr_name}=", instance
         | 
| 16 | 
            +
                        instance
         | 
| 17 | 
            +
                      end
         | 
| 18 | 
            +
                    end
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
              end
         | 
| 22 | 
            +
            end
         | 
| @@ -0,0 +1,19 @@ | |
| 1 | 
            +
            module EventSource
         | 
| 2 | 
            +
              module EventStore
         | 
| 3 | 
            +
                module HTTP
         | 
| 4 | 
            +
                  class Session
         | 
| 5 | 
            +
                    module Defaults
         | 
| 6 | 
            +
                      def self.disable_leader_detection
         | 
| 7 | 
            +
                        disabled = ENV['DISABLE_EVENT_STORE_LEADER_DETECTION']
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                        if /\A(?:on|yes|y|true|1)\z/i.match disabled
         | 
| 10 | 
            +
                          true
         | 
| 11 | 
            +
                        else
         | 
| 12 | 
            +
                          false
         | 
| 13 | 
            +
                        end
         | 
| 14 | 
            +
                      end
         | 
| 15 | 
            +
                    end
         | 
| 16 | 
            +
                  end
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
            end
         | 
| @@ -0,0 +1,41 @@ | |
| 1 | 
            +
            module EventSource
         | 
| 2 | 
            +
              module EventStore
         | 
| 3 | 
            +
                module HTTP
         | 
| 4 | 
            +
                  class Session
         | 
| 5 | 
            +
                    module LogText
         | 
| 6 | 
            +
                      def self.establishing_connection(session, leader_ip_address)
         | 
| 7 | 
            +
                        "HostSetting: #{session.host}, PortSetting: #{session.port}, LeaderIPAddress: #{leader_ip_address || '(unknown)'}"
         | 
| 8 | 
            +
                      end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                      def self.connection_established(session, leader_ip_address)
         | 
| 11 | 
            +
                        "HostSetting: #{session.host}, PortSetting: #{session.port}, LeaderIPAddress: #{leader_ip_address || '(unused)'}"
         | 
| 12 | 
            +
                      end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                      def self.request_attributes(request)
         | 
| 15 | 
            +
                        "Path: #{request.path}, Host: #{request['Host'] || '(not yet set)'}, MediaType: #{request['Content-Type'] || '(none)'}, ContentLength: #{request.body&.bytesize.to_i}, Accept: #{request['Accept'] || '(none)'}"
         | 
| 16 | 
            +
                      end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                      def self.request_body(request)
         | 
| 19 | 
            +
                        if request.body.nil? || request.body.empty?
         | 
| 20 | 
            +
                          "Request: (none)'"
         | 
| 21 | 
            +
                        else
         | 
| 22 | 
            +
                          "Request:\n\n#{request.body}"
         | 
| 23 | 
            +
                        end
         | 
| 24 | 
            +
                      end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                      def self.response_attributes(response)
         | 
| 27 | 
            +
                        "StatusCode: #{response.code}, ReasonPhrase: #{response.message}"
         | 
| 28 | 
            +
                      end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                      def self.response_body(response)
         | 
| 31 | 
            +
                        if response.body.empty?
         | 
| 32 | 
            +
                          "Response: (none)"
         | 
| 33 | 
            +
                        else
         | 
| 34 | 
            +
                          "Response:\n\n#{response.body}"
         | 
| 35 | 
            +
                        end
         | 
| 36 | 
            +
                      end
         | 
| 37 | 
            +
                    end
         | 
| 38 | 
            +
                  end
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
              end
         | 
| 41 | 
            +
            end
         | 
| @@ -4,46 +4,36 @@ module EventSource | |
| 4 4 | 
             
                  class Session
         | 
| 5 5 | 
             
                    module Substitute
         | 
| 6 6 | 
             
                      def self.build
         | 
| 7 | 
            -
                        Session. | 
| 7 | 
            +
                        Session.new
         | 
| 8 8 | 
             
                      end
         | 
| 9 9 |  | 
| 10 | 
            -
                       | 
| 11 | 
            -
                        attr_accessor :telemetry_sink
         | 
| 10 | 
            +
                      Response = Struct.new :code, :message, :body
         | 
| 12 11 |  | 
| 13 | 
            -
             | 
| 14 | 
            -
             | 
| 12 | 
            +
                      class Session
         | 
| 13 | 
            +
                        attr_writer :status_code
         | 
| 14 | 
            +
                        attr_writer :reason_phrase
         | 
| 15 | 
            +
                        attr_accessor :response_body
         | 
| 15 16 |  | 
| 16 | 
            -
             | 
| 17 | 
            -
             | 
| 18 | 
            -
                           | 
| 19 | 
            -
             | 
| 20 | 
            -
                           | 
| 17 | 
            +
                        def call(request)
         | 
| 18 | 
            +
                          response = Response.new
         | 
| 19 | 
            +
                          response.code = status_code.to_s
         | 
| 20 | 
            +
                          response.message = reason_phrase
         | 
| 21 | 
            +
                          response.body = response_body.to_s
         | 
| 22 | 
            +
                          response
         | 
| 21 23 | 
             
                        end
         | 
| 22 24 |  | 
| 23 25 | 
             
                        def set_response(status_code, response_body=nil, reason_phrase: nil)
         | 
| 24 | 
            -
                           | 
| 25 | 
            -
             | 
| 26 | 
            -
             | 
| 27 | 
            -
                            reason_phrase: reason_phrase
         | 
| 28 | 
            -
                          )
         | 
| 26 | 
            +
                          self.status_code = status_code
         | 
| 27 | 
            +
                          self.reason_phrase = reason_phrase
         | 
| 28 | 
            +
                          self.response_body = response_body if response_body
         | 
| 29 29 | 
             
                        end
         | 
| 30 30 |  | 
| 31 | 
            -
                         | 
| 32 | 
            -
                           | 
| 33 | 
            -
             | 
| 34 | 
            -
             | 
| 35 | 
            -
                            telemetry_sink.recorded_get? do |record|
         | 
| 36 | 
            -
                              block.(record.data)
         | 
| 37 | 
            -
                            end
         | 
| 38 | 
            -
                          end
         | 
| 39 | 
            -
             | 
| 40 | 
            -
                          def post_request?(&block)
         | 
| 41 | 
            -
                            block ||= proc { true }
         | 
| 31 | 
            +
                        def status_code
         | 
| 32 | 
            +
                          @status_code ||= 404
         | 
| 33 | 
            +
                        end
         | 
| 42 34 |  | 
| 43 | 
            -
             | 
| 44 | 
            -
             | 
| 45 | 
            -
                            end
         | 
| 46 | 
            -
                          end
         | 
| 35 | 
            +
                        def reason_phrase
         | 
| 36 | 
            +
                          @reason_phrase ||= 'Not found'
         | 
| 47 37 | 
             
                        end
         | 
| 48 38 | 
             
                      end
         | 
| 49 39 | 
             
                    end
         | 
| @@ -6,28 +6,77 @@ module EventSource | |
| 6 6 | 
             
                      class Sink
         | 
| 7 7 | 
             
                        include ::Telemetry::Sink
         | 
| 8 8 |  | 
| 9 | 
            -
                        record : | 
| 10 | 
            -
             | 
| 11 | 
            -
                        record : | 
| 9 | 
            +
                        record :connection_established
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                        record :leader_status_queried
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                        record :http_request
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                        record :redirected
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                        def leader_status_query_successful?
         | 
| 18 | 
            +
                          recorded_leader_status_queried? do |record|
         | 
| 19 | 
            +
                            record.data.leader_status && record.data.error.nil?
         | 
| 20 | 
            +
                          end
         | 
| 21 | 
            +
                        end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                        def leader_status_query_failed?
         | 
| 24 | 
            +
                          recorded_leader_status_queried? do |record|
         | 
| 25 | 
            +
                            record.data.leader_status.nil? && record.data.error
         | 
| 26 | 
            +
                          end
         | 
| 27 | 
            +
                        end
         | 
| 12 28 | 
             
                      end
         | 
| 13 29 |  | 
| 14 | 
            -
                       | 
| 30 | 
            +
                      module RegisterSink
         | 
| 31 | 
            +
                        def register_telemetry_sink(instance)
         | 
| 32 | 
            +
                          sink = Telemetry::Sink.new
         | 
| 15 33 |  | 
| 16 | 
            -
             | 
| 17 | 
            -
                        :path,
         | 
| 18 | 
            -
                        :status_code,
         | 
| 19 | 
            -
                        :reason_phrase,
         | 
| 20 | 
            -
                        :response_body,
         | 
| 21 | 
            -
                        :acceptable_media_type
         | 
| 22 | 
            -
                      )
         | 
| 34 | 
            +
                          instance.telemetry.register sink
         | 
| 23 35 |  | 
| 24 | 
            -
             | 
| 36 | 
            +
                          sink
         | 
| 37 | 
            +
                        end
         | 
| 38 | 
            +
                      end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                      ConnectionEstablished = Struct.new :host, :port, :connection
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                      LeaderStatusQueried = Struct.new :leader_status, :error
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                      HTTPRequest = Struct.new(
         | 
| 45 | 
            +
                        :request,
         | 
| 46 | 
            +
                        :response,
         | 
| 47 | 
            +
                        :action,
         | 
| 25 48 | 
             
                        :path,
         | 
| 26 49 | 
             
                        :status_code,
         | 
| 27 50 | 
             
                        :reason_phrase,
         | 
| 51 | 
            +
                        :response_body,
         | 
| 52 | 
            +
                        :acceptable_media_type,
         | 
| 28 53 | 
             
                        :request_body,
         | 
| 29 54 | 
             
                        :content_type
         | 
| 30 55 | 
             
                      )
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                      class HTTPRequest
         | 
| 58 | 
            +
                        def self.build(request, response)
         | 
| 59 | 
            +
                          instance = new(
         | 
| 60 | 
            +
                            request,
         | 
| 61 | 
            +
                            response,
         | 
| 62 | 
            +
                            request.method,
         | 
| 63 | 
            +
                            request.path,
         | 
| 64 | 
            +
                            response.code.to_i,
         | 
| 65 | 
            +
                            response.message,
         | 
| 66 | 
            +
                            response.body,
         | 
| 67 | 
            +
                            request['Accept']
         | 
| 68 | 
            +
                          )
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                          if request.request_body_permitted?
         | 
| 71 | 
            +
                            instance.request_body = request.body
         | 
| 72 | 
            +
                            instance.content_type = request['Content-Type']
         | 
| 73 | 
            +
                          end
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                          instance
         | 
| 76 | 
            +
                        end
         | 
| 77 | 
            +
                      end
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                      Redirected = Struct.new :requested_path, :origin_host, :redirect_uri
         | 
| 31 80 | 
             
                    end
         | 
| 32 81 | 
             
                  end
         | 
| 33 82 | 
             
                end
         | 
| @@ -1,27 +1,7 @@ | |
| 1 1 | 
             
            module EventSource
         | 
| 2 2 | 
             
              module EventStore
         | 
| 3 3 | 
             
                module HTTP
         | 
| 4 | 
            -
                   | 
| 5 | 
            -
                    def self.data_source
         | 
| 6 | 
            -
                      'settings/event_source_event_store_http.json'
         | 
| 7 | 
            -
                    end
         | 
| 8 | 
            -
             | 
| 9 | 
            -
                    def self.instance
         | 
| 10 | 
            -
                      @instance ||= build
         | 
| 11 | 
            -
                    end
         | 
| 12 | 
            -
             | 
| 13 | 
            -
                    def self.names
         | 
| 14 | 
            -
                      %i(host port read_timeout)
         | 
| 15 | 
            -
                    end
         | 
| 16 | 
            -
             | 
| 17 | 
            -
                    def self.set(receiver)
         | 
| 18 | 
            -
                      instance.set receiver
         | 
| 19 | 
            -
                    end
         | 
| 20 | 
            -
             | 
| 21 | 
            -
                    def self.get(name)
         | 
| 22 | 
            -
                      instance.get name
         | 
| 23 | 
            -
                    end
         | 
| 24 | 
            -
                  end
         | 
| 4 | 
            +
                  Settings = ::EventStore::HTTP::Connect::Settings
         | 
| 25 5 | 
             
                end
         | 
| 26 6 | 
             
              end
         | 
| 27 7 | 
             
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,29 +1,15 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: evt-event_source-event_store-http
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 0.2.0.0.pre1
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - The Eventide Project
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date:  | 
| 11 | 
            +
            date: 2017-01-05 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 | 
            -
            - !ruby/object:Gem::Dependency
         | 
| 14 | 
            -
              name: evt-configure
         | 
| 15 | 
            -
              requirement: !ruby/object:Gem::Requirement
         | 
| 16 | 
            -
                requirements:
         | 
| 17 | 
            -
                - - ">="
         | 
| 18 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 19 | 
            -
                    version: '0'
         | 
| 20 | 
            -
              type: :runtime
         | 
| 21 | 
            -
              prerelease: false
         | 
| 22 | 
            -
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 23 | 
            -
                requirements:
         | 
| 24 | 
            -
                - - ">="
         | 
| 25 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 26 | 
            -
                    version: '0'
         | 
| 27 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 28 14 | 
             
              name: evt-event_source
         | 
| 29 15 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -39,7 +25,7 @@ dependencies: | |
| 39 25 | 
             
                  - !ruby/object:Gem::Version
         | 
| 40 26 | 
             
                    version: '0'
         | 
| 41 27 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 42 | 
            -
              name: evt- | 
| 28 | 
            +
              name: evt-event_store-cluster-leader_status
         | 
| 43 29 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 44 30 | 
             
                requirements:
         | 
| 45 31 | 
             
                - - ">="
         | 
| @@ -74,11 +60,21 @@ extra_rdoc_files: [] | |
| 74 60 | 
             
            files:
         | 
| 75 61 | 
             
            - lib/event_source/event_store/http.rb
         | 
| 76 62 | 
             
            - lib/event_source/event_store/http/controls.rb
         | 
| 77 | 
            -
            - lib/event_source/event_store/http/controls/ | 
| 63 | 
            +
            - lib/event_source/event_store/http/controls/cluster_members.rb
         | 
| 78 64 | 
             
            - lib/event_source/event_store/http/controls/event_data.rb
         | 
| 79 65 | 
             
            - lib/event_source/event_store/http/controls/event_data/event_id.rb
         | 
| 80 66 | 
             
            - lib/event_source/event_store/http/controls/event_data/write.rb
         | 
| 67 | 
            +
            - lib/event_source/event_store/http/controls/expected_version.rb
         | 
| 68 | 
            +
            - lib/event_source/event_store/http/controls/hostname.rb
         | 
| 69 | 
            +
            - lib/event_source/event_store/http/controls/hostname/cluster.rb
         | 
| 70 | 
            +
            - lib/event_source/event_store/http/controls/ip_address/cluster.rb
         | 
| 81 71 | 
             
            - lib/event_source/event_store/http/controls/media_type.rb
         | 
| 72 | 
            +
            - lib/event_source/event_store/http/controls/port.rb
         | 
| 73 | 
            +
            - lib/event_source/event_store/http/controls/resolve_host.rb
         | 
| 74 | 
            +
            - lib/event_source/event_store/http/controls/session/request/require_leader.rb
         | 
| 75 | 
            +
            - lib/event_source/event_store/http/controls/session/request/write_event.rb
         | 
| 76 | 
            +
            - lib/event_source/event_store/http/controls/settings.rb
         | 
| 77 | 
            +
            - lib/event_source/event_store/http/controls/settings/cluster.rb
         | 
| 82 78 | 
             
            - lib/event_source/event_store/http/controls/stream.rb
         | 
| 83 79 | 
             
            - lib/event_source/event_store/http/controls/stream_name.rb
         | 
| 84 80 | 
             
            - lib/event_source/event_store/http/controls/uri/path.rb
         | 
| @@ -86,8 +82,14 @@ files: | |
| 86 82 | 
             
            - lib/event_source/event_store/http/controls/write.rb
         | 
| 87 83 | 
             
            - lib/event_source/event_store/http/log.rb
         | 
| 88 84 | 
             
            - lib/event_source/event_store/http/media_types.rb
         | 
| 85 | 
            +
            - lib/event_source/event_store/http/request.rb
         | 
| 86 | 
            +
            - lib/event_source/event_store/http/request/get.rb
         | 
| 87 | 
            +
            - lib/event_source/event_store/http/request/post.rb
         | 
| 89 88 | 
             
            - lib/event_source/event_store/http/session.rb
         | 
| 90 | 
            -
            - lib/event_source/event_store/http/session/ | 
| 89 | 
            +
            - lib/event_source/event_store/http/session/build.rb
         | 
| 90 | 
            +
            - lib/event_source/event_store/http/session/configure.rb
         | 
| 91 | 
            +
            - lib/event_source/event_store/http/session/defaults.rb
         | 
| 92 | 
            +
            - lib/event_source/event_store/http/session/log_text.rb
         | 
| 91 93 | 
             
            - lib/event_source/event_store/http/session/substitute.rb
         | 
| 92 94 | 
             
            - lib/event_source/event_store/http/session/telemetry.rb
         | 
| 93 95 | 
             
            - lib/event_source/event_store/http/settings.rb
         | 
| @@ -106,9 +108,9 @@ required_ruby_version: !ruby/object:Gem::Requirement | |
| 106 108 | 
             
                  version: 2.3.3
         | 
| 107 109 | 
             
            required_rubygems_version: !ruby/object:Gem::Requirement
         | 
| 108 110 | 
             
              requirements:
         | 
| 109 | 
            -
              - - " | 
| 111 | 
            +
              - - ">"
         | 
| 110 112 | 
             
                - !ruby/object:Gem::Version
         | 
| 111 | 
            -
                  version:  | 
| 113 | 
            +
                  version: 1.3.1
         | 
| 112 114 | 
             
            requirements: []
         | 
| 113 115 | 
             
            rubyforge_project: 
         | 
| 114 116 | 
             
            rubygems_version: 2.6.8
         | 
| @@ -1,100 +0,0 @@ | |
| 1 | 
            -
            module EventSource
         | 
| 2 | 
            -
              module EventStore
         | 
| 3 | 
            -
                module HTTP
         | 
| 4 | 
            -
                  class Session
         | 
| 5 | 
            -
                    module NetHTTP
         | 
| 6 | 
            -
                      def self.configure(receiver, settings: nil, namespace: nil, attr_name: nil)
         | 
| 7 | 
            -
                        attr_name ||= :net_http
         | 
| 8 | 
            -
                        settings ||= Settings.instance
         | 
| 9 | 
            -
                        namespace = Array(namespace)
         | 
| 10 | 
            -
             | 
| 11 | 
            -
                        host = settings.get *namespace, :host
         | 
| 12 | 
            -
                        port = settings.get *namespace, :port
         | 
| 13 | 
            -
                        read_timeout = settings.get *namespace, :read_timeout
         | 
| 14 | 
            -
             | 
| 15 | 
            -
                        net_http = Net::HTTP.new host, port
         | 
| 16 | 
            -
             | 
| 17 | 
            -
                        net_http.read_timeout = read_timeout if read_timeout
         | 
| 18 | 
            -
             | 
| 19 | 
            -
                        receiver.public_send "#{attr_name}=", net_http
         | 
| 20 | 
            -
             | 
| 21 | 
            -
                        net_http
         | 
| 22 | 
            -
                      end
         | 
| 23 | 
            -
             | 
| 24 | 
            -
                      class Substitute
         | 
| 25 | 
            -
                        attr_accessor :address
         | 
| 26 | 
            -
                        attr_accessor :reason_phrase
         | 
| 27 | 
            -
                        attr_writer :response_body
         | 
| 28 | 
            -
                        attr_accessor :port
         | 
| 29 | 
            -
                        attr_accessor :status_code
         | 
| 30 | 
            -
                        attr_accessor :started
         | 
| 31 | 
            -
             | 
| 32 | 
            -
                        def self.build
         | 
| 33 | 
            -
                          new
         | 
| 34 | 
            -
                        end
         | 
| 35 | 
            -
             | 
| 36 | 
            -
                        def request_get(path, initheader=nil)
         | 
| 37 | 
            -
                          status_code = get_request_status_code
         | 
| 38 | 
            -
             | 
| 39 | 
            -
                          OpenStruct.new(
         | 
| 40 | 
            -
                            :code => status_code,
         | 
| 41 | 
            -
                            :body => response_body,
         | 
| 42 | 
            -
                            :message => reason_phrase
         | 
| 43 | 
            -
                          )
         | 
| 44 | 
            -
                        end
         | 
| 45 | 
            -
             | 
| 46 | 
            -
                        def request_post(path, request_body, initheader=nil)
         | 
| 47 | 
            -
                          status_code = post_request_status_code
         | 
| 48 | 
            -
             | 
| 49 | 
            -
                          OpenStruct.new(
         | 
| 50 | 
            -
                            :code => status_code,
         | 
| 51 | 
            -
                            :body => response_body,
         | 
| 52 | 
            -
                            :message => reason_phrase
         | 
| 53 | 
            -
                          )
         | 
| 54 | 
            -
                        end
         | 
| 55 | 
            -
             | 
| 56 | 
            -
                        def start
         | 
| 57 | 
            -
                          self.started = true
         | 
| 58 | 
            -
                        end
         | 
| 59 | 
            -
             | 
| 60 | 
            -
                        def started?
         | 
| 61 | 
            -
                          started ? true : false
         | 
| 62 | 
            -
                        end
         | 
| 63 | 
            -
             | 
| 64 | 
            -
                        def response_body
         | 
| 65 | 
            -
                          @response_body ||= Defaults.response_body
         | 
| 66 | 
            -
                        end
         | 
| 67 | 
            -
             | 
| 68 | 
            -
                        def get_request_status_code
         | 
| 69 | 
            -
                          status_code || Defaults.get_request_status_code
         | 
| 70 | 
            -
                        end
         | 
| 71 | 
            -
             | 
| 72 | 
            -
                        def post_request_status_code
         | 
| 73 | 
            -
                          status_code || Defaults.post_request_status_code
         | 
| 74 | 
            -
                        end
         | 
| 75 | 
            -
             | 
| 76 | 
            -
                        def set_response(status_code, response_body=nil, reason_phrase: nil)
         | 
| 77 | 
            -
                          self.status_code = status_code
         | 
| 78 | 
            -
                          self.response_body = response_body if response_body
         | 
| 79 | 
            -
                          self.reason_phrase = reason_phrase if reason_phrase
         | 
| 80 | 
            -
                        end
         | 
| 81 | 
            -
             | 
| 82 | 
            -
                        module Defaults
         | 
| 83 | 
            -
                          def self.get_request_status_code
         | 
| 84 | 
            -
                            404
         | 
| 85 | 
            -
                          end
         | 
| 86 | 
            -
             | 
| 87 | 
            -
                          def self.post_request_status_code
         | 
| 88 | 
            -
                            201
         | 
| 89 | 
            -
                          end
         | 
| 90 | 
            -
             | 
| 91 | 
            -
                          def self.response_body
         | 
| 92 | 
            -
                            ''
         | 
| 93 | 
            -
                          end
         | 
| 94 | 
            -
                        end
         | 
| 95 | 
            -
                      end
         | 
| 96 | 
            -
                    end
         | 
| 97 | 
            -
                  end
         | 
| 98 | 
            -
                end
         | 
| 99 | 
            -
              end
         | 
| 100 | 
            -
            end
         |