evt-event_source-event_store-http 0.2.0.0 → 0.3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/lib/event_source/event_store/http.rb +11 -12
  3. data/lib/event_source/event_store/http/controls.rb +6 -25
  4. data/lib/event_source/event_store/http/controls/{resolve_host.rb → category.rb} +1 -1
  5. data/lib/event_source/event_store/http/controls/stream_name.rb +11 -1
  6. data/lib/event_source/event_store/http/controls/write.rb +9 -14
  7. data/lib/event_source/event_store/http/get.rb +58 -0
  8. data/lib/event_source/event_store/http/get/assertions.rb +21 -0
  9. data/lib/event_source/event_store/http/get/result.rb +51 -0
  10. data/lib/event_source/event_store/http/put.rb +52 -0
  11. data/lib/event_source/event_store/http/read.rb +36 -0
  12. data/lib/event_source/event_store/http/session.rb +1 -106
  13. data/lib/event_source/event_store/http/settings.rb +1 -1
  14. data/lib/event_source/event_store/http/stream_name.rb +25 -0
  15. data/lib/event_source/event_store/http/write.rb +27 -0
  16. metadata +11 -24
  17. data/lib/event_source/event_store/http/controls/cluster_members.rb +0 -9
  18. data/lib/event_source/event_store/http/controls/expected_version.rb +0 -31
  19. data/lib/event_source/event_store/http/controls/hostname.rb +0 -13
  20. data/lib/event_source/event_store/http/controls/hostname/cluster.rb +0 -15
  21. data/lib/event_source/event_store/http/controls/ip_address/cluster.rb +0 -25
  22. data/lib/event_source/event_store/http/controls/media_type.rb +0 -25
  23. data/lib/event_source/event_store/http/controls/session/request/require_leader.rb +0 -41
  24. data/lib/event_source/event_store/http/controls/session/request/write_event.rb +0 -17
  25. data/lib/event_source/event_store/http/controls/settings/cluster.rb +0 -19
  26. data/lib/event_source/event_store/http/controls/uri/path.rb +0 -21
  27. data/lib/event_source/event_store/http/media_types.rb +0 -13
  28. data/lib/event_source/event_store/http/request.rb +0 -27
  29. data/lib/event_source/event_store/http/request/get.rb +0 -64
  30. data/lib/event_source/event_store/http/request/post.rb +0 -75
  31. data/lib/event_source/event_store/http/session/build.rb +0 -28
  32. data/lib/event_source/event_store/http/session/configure.rb +0 -22
  33. data/lib/event_source/event_store/http/session/defaults.rb +0 -19
  34. data/lib/event_source/event_store/http/session/log_text.rb +0 -41
  35. data/lib/event_source/event_store/http/session/substitute.rb +0 -43
  36. data/lib/event_source/event_store/http/session/telemetry.rb +0 -84
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2025e86eb955cf9dd473e6c37926b060a69381ad
4
- data.tar.gz: 65b06cf4026cd00047828ae408adf537736e3f83
3
+ metadata.gz: 103accfc22fbead9cbb14c7ebc34caa3a835d121
4
+ data.tar.gz: 7275b6f7d9334f8f8a1760a45ebb5819a9038adb
5
5
  SHA512:
6
- metadata.gz: b6462d550f3eea7c2765f72e0d0fbd09c146edb8c1d6373b52f98109e668e1ec0f129cf98378f54184fa180161315c04d2d9da85af28bc70df4388bdcd7d8343
7
- data.tar.gz: 3d57ea9a962f4abea3f7f8b69790f92694552ad3edb00a31c6f4100d3cda51362cc638af5e2edb55168bf230fb8370416d4cf42078c7f3bf93fa5d8e6eab6b15
6
+ metadata.gz: 06ef8b13ec026bdc2f6f5d04b70694c3d12a13fe1477dc9269690b72418882890b140e09145212553b0c65468ceaf97ad1444844f4ab3661597cd24c177c77ea
7
+ data.tar.gz: fae00c828d0bca010819a4e844e754946dada6852c4f71f472b6350afe4ec9e4ba4659b8d49b3e2dc53397aa2b86782bb936c7ab62d693a302e4eb4f68807796
@@ -1,18 +1,17 @@
1
1
  require 'event_source'
2
- require 'event_store/cluster/leader_status'
2
+ require 'event_store/http'
3
3
 
4
4
  require 'event_source/event_store/http/log'
5
- require 'event_source/event_store/http/media_types'
5
+ require 'event_source/event_store/http/session'
6
6
  require 'event_source/event_store/http/settings'
7
+ require 'event_source/event_store/http/stream_name'
7
8
 
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'
12
- require 'event_source/event_store/http/session/substitute'
13
- require 'event_source/event_store/http/session/telemetry'
14
- require 'event_source/event_store/http/session'
9
+ require 'event_source/event_store/http/get'
10
+ require 'event_source/event_store/http/get/assertions'
11
+ require 'event_source/event_store/http/get/result'
12
+
13
+ require 'event_source/event_store/http/put'
14
+
15
+ require 'event_source/event_store/http/write'
15
16
 
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'
17
+ require 'event_source/event_store/http/read'
@@ -1,33 +1,14 @@
1
1
  require 'identifier/uuid/controls'
2
2
  require 'event_source/controls'
3
- require 'event_store/cluster/leader_status/controls'
3
+ require 'event_store/http/controls'
4
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'
5
+ require 'event_source/event_store/http/controls/write'
19
6
 
20
- require 'event_source/event_store/http/controls/session/request/require_leader'
21
- require 'event_source/event_store/http/controls/session/request/write_event'
7
+ require 'event_source/event_store/http/controls/category'
8
+ require 'event_source/event_store/http/controls/stream'
9
+ require 'event_source/event_store/http/controls/stream_name'
10
+ require 'event_source/event_store/http/controls/uuid'
22
11
 
23
12
  require 'event_source/event_store/http/controls/event_data'
24
13
  require 'event_source/event_store/http/controls/event_data/event_id'
25
14
  require 'event_source/event_store/http/controls/event_data/write'
26
-
27
- require 'event_source/event_store/http/controls/stream'
28
- require 'event_source/event_store/http/controls/stream_name'
29
- require 'event_source/event_store/http/controls/uri/path'
30
-
31
- require 'event_source/event_store/http/controls/expected_version'
32
-
33
- require 'event_source/event_store/http/controls/write'
@@ -2,7 +2,7 @@ module EventSource
2
2
  module EventStore
3
3
  module HTTP
4
4
  module Controls
5
- ResolveHost = ::EventStore::HTTP::Connect::Controls::ResolveHost
5
+ Category = EventSource::Controls::Category
6
6
  end
7
7
  end
8
8
  end
@@ -2,7 +2,17 @@ module EventSource
2
2
  module EventStore
3
3
  module HTTP
4
4
  module Controls
5
- StreamName = EventSource::Controls::StreamName
5
+ module StreamName
6
+ def self.example(*arguments)
7
+ EventSource::Controls::StreamName.example *arguments
8
+ end
9
+
10
+ module Category
11
+ def self.example
12
+ Stream::Category.example.name
13
+ end
14
+ end
15
+ end
6
16
  end
7
17
  end
8
18
  end
@@ -3,25 +3,21 @@ module EventSource
3
3
  module HTTP
4
4
  module Controls
5
5
  module Write
6
- def self.call(event_count=nil, data: nil, metadata: nil, stream_name: nil, type: nil)
7
- event_count ||= 1
6
+ def self.call(events=nil, instances: nil, stream_name: nil)
8
7
  stream_name ||= StreamName.example
9
8
 
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
- )
9
+ if events.nil?
10
+ instances ||= 1
17
11
 
18
- response = http.request post
19
-
20
- unless response.code.to_i == 201
21
- fail "Write failed (StatusCode: #{response.code}, ReasonPhrase: #{response.message})"
12
+ events = instances.times.map do |position|
13
+ EventData::Write.example
22
14
  end
15
+ else
16
+ events = Array(events)
23
17
  end
24
18
 
19
+ ::EventStore::HTTP::Write.(events, stream_name)
20
+
25
21
  stream_name
26
22
  end
27
23
  end
@@ -29,4 +25,3 @@ module EventSource
29
25
  end
30
26
  end
31
27
  end
32
-
@@ -0,0 +1,58 @@
1
+ module EventSource
2
+ module EventStore
3
+ module HTTP
4
+ class Get
5
+ include Log::Dependency
6
+
7
+ configure :get
8
+
9
+ initializer :batch_size, :precedence, a(:long_poll_duration)
10
+
11
+ dependency :session, Session
12
+ dependency :read_stream, ::EventStore::HTTP::ReadStream
13
+
14
+ def self.build(batch_size: nil, precedence: nil, long_poll_duration: nil, session: nil)
15
+ instance = new batch_size, precedence, long_poll_duration
16
+ Session.configure instance, session: session
17
+ ::EventStore::HTTP::ReadStream.configure instance
18
+ instance.configure
19
+ instance
20
+ end
21
+
22
+ def self.call(stream_name, position: nil, **build_arguments)
23
+ instance = build **build_arguments
24
+ instance.(stream_name, position: position)
25
+ end
26
+
27
+ def configure
28
+ read_stream.embed_body
29
+ read_stream.output_schema = Result
30
+
31
+ unless long_poll_duration.nil?
32
+ read_stream.enable_long_poll long_poll_duration
33
+ end
34
+ end
35
+
36
+ def call(stream_name, position: nil)
37
+ logger.trace { "Reading stream (StreamName: #{stream_name}, Position: #{position || '(start)'})" }
38
+
39
+ begin
40
+ events = read_stream.(
41
+ stream_name,
42
+ position: position,
43
+ batch_size: batch_size
44
+ )
45
+ rescue ::EventStore::HTTP::ReadStream::StreamNotFoundError
46
+ events = []
47
+ end
48
+
49
+ events.reverse! if precedence == :desc
50
+
51
+ logger.debug { "Done reading stream (StreamName: #{stream_name}, Position: #{position || '(start)'}, Events: #{events.count})" }
52
+
53
+ events
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,21 @@
1
+ module EventSource
2
+ module EventStore
3
+ module HTTP
4
+ class Get
5
+ module Assertions
6
+ def long_poll_enabled?(value=nil)
7
+ duration = read_stream.long_poll_duration
8
+
9
+ if duration.nil?
10
+ false
11
+ elsif value.nil?
12
+ true
13
+ else
14
+ duration == value
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,51 @@
1
+ module EventSource
2
+ module EventStore
3
+ module HTTP
4
+ class Get
5
+ module Result
6
+ module Transformer
7
+ def self.json
8
+ JSON
9
+ end
10
+
11
+ def self.instance(raw_data)
12
+ entries = raw_data.fetch :entries
13
+
14
+ events = []
15
+
16
+ entries.reverse_each do |atom_event|
17
+ event = EventData::Read.new
18
+ event.id = atom_event.fetch :event_id
19
+ event.type = atom_event.fetch :event_type
20
+
21
+ data_text = atom_event.fetch :data
22
+ event.data = ::EventStore::HTTP::JSON::Deserialize.(data_text)
23
+
24
+ if atom_event.key? :meta_data
25
+ metadata_text = atom_event.fetch :meta_data
26
+ event.metadata = ::EventStore::HTTP::JSON::Deserialize.(metadata_text)
27
+ end
28
+
29
+ event.stream_name = atom_event.fetch :stream_id
30
+
31
+ event.position = atom_event.fetch :event_number
32
+ event.global_position = atom_event.fetch :position_event_number
33
+ event.time = Clock.parse atom_event.fetch(:updated)
34
+
35
+ events << event
36
+ end
37
+
38
+ events
39
+ end
40
+
41
+ module JSON
42
+ def self.read(text)
43
+ ::EventStore::HTTP::JSON::Deserialize.(text)
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,52 @@
1
+ module EventSource
2
+ module EventStore
3
+ module HTTP
4
+ class Put
5
+ include Log::Dependency
6
+
7
+ configure :put
8
+
9
+ dependency :write, ::EventStore::HTTP::Write
10
+
11
+ def self.build(session: nil)
12
+ instance = new
13
+ ::EventStore::HTTP::Write.configure instance, session: session
14
+ instance
15
+ end
16
+
17
+ def self.call(write_event, stream_name, expected_version: nil, session: nil)
18
+ instance = build session: session
19
+ instance.(write_event, stream_name, expected_version: expected_version)
20
+ end
21
+
22
+ def call(write_events, stream_name, expected_version: nil)
23
+ write_events = Array(write_events)
24
+
25
+ expected_version = ExpectedVersion.canonize expected_version
26
+
27
+ logger.trace { "Putting event data (StreamName: #{stream_name}, BatchSize: #{write_events.count}, Types: #{write_events.map(&:type).inspect}, ExpectedVersion: #{expected_version.inspect})" }
28
+
29
+ write_events.each do |write_event|
30
+ write_event.metadata = nil if write_event.metadata&.empty?
31
+ end
32
+
33
+ begin
34
+ location = write.(
35
+ write_events,
36
+ stream_name,
37
+ expected_version: expected_version
38
+ )
39
+ rescue ::EventStore::HTTP::Write::ExpectedVersionError => error
40
+ raise ExpectedVersion::Error, error.message
41
+ end
42
+
43
+ *, position = location.path.split '/'
44
+
45
+ logger.debug { "Put event data done (StreamName: #{stream_name}, BatchSize: #{write_events.count}, Types: #{write_events.map(&:type).inspect}, Position: #{position}, ExpectedVersion: #{expected_version.inspect})" }
46
+
47
+ position.to_i
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,36 @@
1
+ module EventSource
2
+ module EventStore
3
+ module HTTP
4
+ class Read
5
+ include EventSource::Read
6
+
7
+ def self.build(*)
8
+ instance = super
9
+ instance.configure_long_poll
10
+ instance
11
+ end
12
+
13
+ def configure(batch_size: nil, precedence: nil, session: nil)
14
+ Get.configure(
15
+ self,
16
+ batch_size: batch_size,
17
+ precedence: precedence,
18
+ session: session
19
+ )
20
+ end
21
+
22
+ def configure_long_poll
23
+ cycle = iterator.cycle
24
+
25
+ return if cycle.instance_of? Cycle::None
26
+
27
+ maximum_milliseconds = cycle.maximum_milliseconds
28
+
29
+ long_poll_duration = Rational(maximum_milliseconds, 1000).ceil
30
+
31
+ get.read_stream.enable_long_poll long_poll_duration
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -1,112 +1,7 @@
1
1
  module EventSource
2
2
  module EventStore
3
3
  module HTTP
4
- class Session
5
- include Log::Dependency
6
-
7
- extend Build
8
- extend Configure
9
- extend Telemetry::RegisterSink
10
-
11
- attr_writer :connection
12
- attr_writer :disable_leader_detection
13
-
14
- def disable_leader_detection
15
- if @disable_leader_detection.nil?
16
- @disable_leader_detection = Defaults.disable_leader_detection
17
- end
18
-
19
- @disable_leader_detection
20
- end
21
-
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
28
-
29
- def call(request, redirect: nil, &probe)
30
- redirect ||= false
31
-
32
- logger.trace(tag: :event_store_http) { "Issuing #{request.method} request (#{LogText.request_attributes request})" }
33
- logger.trace(tag: :data) { LogText.request_body request } if request.request_body_permitted?
34
-
35
- response = connection.request request
36
-
37
- if Net::HTTPRedirection === response && !redirect
38
- logger.debug(tag: :event_store_http) { "#{request.method} request received redirect response (#{LogText.request_attributes request}, #{LogText.response_attributes response}, Location: #{response['Location'] || '(none)'})" }
39
-
40
- location = URI.parse response['Location']
41
- leader_ip_address = location.host
42
-
43
- telemetry.record :redirected, Telemetry::Redirected.new(request.path, connection.address, location)
44
-
45
- establish_connection leader_ip_address
46
-
47
- request['Host'] = nil
48
- response = self.(request, redirect: true)
49
-
50
- return response
51
- end
52
-
53
- logger.trace(tag: :event_store_http) { "#{request.method} request issued (#{LogText.request_attributes request}, #{LogText.response_attributes response})" }
54
- logger.trace(tag: :data) { LogText.response_body response }
55
-
56
- telemetry.record :http_request, Telemetry::HTTPRequest.build(request, response)
57
-
58
- probe.(response) if probe
59
-
60
- response
61
- end
62
-
63
- def connection
64
- @connection ||= establish_connection
65
- end
66
-
67
- def connected?
68
- !@connection.nil?
69
- end
70
-
71
- def close
72
- connection.finish
73
-
74
- self.connection = nil
75
- end
76
-
77
- def establish_connection(leader_ip_address=nil)
78
- logger.trace(tag: :event_store_connection) { "Establishing connection to EventStore (#{LogText.establishing_connection self, leader_ip_address})" }
79
-
80
- close if connected?
81
-
82
- unless leader_ip_address || disable_leader_detection
83
- leader_status_queried_telemetry = Telemetry::LeaderStatusQueried.new
84
-
85
- begin
86
- leader_status = get_leader_status.()
87
- leader_ip_address = leader_status.http_ip_address
88
-
89
- leader_status_queried_telemetry.leader_status = leader_status
90
-
91
- rescue ::EventStore::Cluster::LeaderStatus::GossipEndpoint::Get::NonClusterError => error
92
- leader_status_queried_telemetry.error = error
93
- logger.warn(tag: :event_store_connection) { "Could not determine cluster leader (#{LogText.establishing_connection self, leader_ip_address}, Error: #{error.class})" }
94
- end
95
-
96
- telemetry.record :leader_status_queried, leader_status_queried_telemetry
97
- end
98
-
99
- connection = connect.(leader_ip_address)
100
-
101
- telemetry.record :connection_established, Telemetry::ConnectionEstablished.new(leader_ip_address || host, port, connection)
102
-
103
- logger.info(tag: :event_store_connection) { "Connection to EventStore established (#{LogText.connection_established self, leader_ip_address})" }
104
-
105
- self.connection = connection
106
-
107
- connection
108
- end
109
- end
4
+ Session = ::EventStore::HTTP::Session
110
5
  end
111
6
  end
112
7
  end
@@ -1,7 +1,7 @@
1
1
  module EventSource
2
2
  module EventStore
3
3
  module HTTP
4
- Settings = ::EventStore::HTTP::Connect::Settings
4
+ Settings = ::EventStore::HTTP::Settings
5
5
  end
6
6
  end
7
7
  end
@@ -0,0 +1,25 @@
1
+ module EventSource
2
+ module EventStore
3
+ module HTTP
4
+ module StreamName
5
+ def self.canonize(stream_or_stream_name)
6
+ stream =
7
+ case stream_or_stream_name
8
+ when EventSource::Stream then stream_or_stream_name
9
+ else EventSource::Stream.new String(stream_or_stream_name)
10
+ end
11
+
12
+ if stream.category?
13
+ category_stream_name stream.name
14
+ else
15
+ stream.name
16
+ end
17
+ end
18
+
19
+ def self.category_stream_name(category)
20
+ "$ce-#{category}"
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,27 @@
1
+ module EventSource
2
+ module EventStore
3
+ module HTTP
4
+ class Write
5
+ include EventSource::Write
6
+
7
+ dependency :put, Put
8
+
9
+ def configure(session: nil)
10
+ Put.configure self, session: session
11
+ end
12
+
13
+ def write(batch, stream_name, expected_version: nil)
14
+ logger.trace { "Writing batch (Stream Name: #{stream_name}, Number of Events: #{batch.count}, Expected Version: #{expected_version.inspect})" }
15
+
16
+ position = put.(batch, stream_name, expected_version: expected_version)
17
+
18
+ last_position = position + (batch.count - 1)
19
+
20
+ logger.debug { "Wrote batch (Stream Name: #{stream_name}, Number of Events: #{batch.count}, Expected Version: #{expected_version.inspect}, Last Position: #{last_position})" }
21
+
22
+ last_position
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
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.2.0.0
4
+ version: 0.3.0.0
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: 2017-01-06 00:00:00.000000000 Z
11
+ date: 2017-01-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: evt-event_source
@@ -25,7 +25,7 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: evt-event_store-cluster-leader_status
28
+ name: evt-event_store-http
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
@@ -60,39 +60,26 @@ extra_rdoc_files: []
60
60
  files:
61
61
  - lib/event_source/event_store/http.rb
62
62
  - lib/event_source/event_store/http/controls.rb
63
- - lib/event_source/event_store/http/controls/cluster_members.rb
63
+ - lib/event_source/event_store/http/controls/category.rb
64
64
  - lib/event_source/event_store/http/controls/event_data.rb
65
65
  - lib/event_source/event_store/http/controls/event_data/event_id.rb
66
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
71
- - lib/event_source/event_store/http/controls/media_type.rb
72
67
  - 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
68
  - lib/event_source/event_store/http/controls/settings.rb
77
- - lib/event_source/event_store/http/controls/settings/cluster.rb
78
69
  - lib/event_source/event_store/http/controls/stream.rb
79
70
  - lib/event_source/event_store/http/controls/stream_name.rb
80
- - lib/event_source/event_store/http/controls/uri/path.rb
81
71
  - lib/event_source/event_store/http/controls/uuid.rb
82
72
  - lib/event_source/event_store/http/controls/write.rb
73
+ - lib/event_source/event_store/http/get.rb
74
+ - lib/event_source/event_store/http/get/assertions.rb
75
+ - lib/event_source/event_store/http/get/result.rb
83
76
  - lib/event_source/event_store/http/log.rb
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
77
+ - lib/event_source/event_store/http/put.rb
78
+ - lib/event_source/event_store/http/read.rb
88
79
  - lib/event_source/event_store/http/session.rb
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
93
- - lib/event_source/event_store/http/session/substitute.rb
94
- - lib/event_source/event_store/http/session/telemetry.rb
95
80
  - lib/event_source/event_store/http/settings.rb
81
+ - lib/event_source/event_store/http/stream_name.rb
82
+ - lib/event_source/event_store/http/write.rb
96
83
  homepage: https://github.com/eventide-project/event-source-event-store-http
97
84
  licenses:
98
85
  - MIT
@@ -1,9 +0,0 @@
1
- module EventSource
2
- module EventStore
3
- module HTTP
4
- module Controls
5
- ClusterMembers = ::EventStore::Cluster::LeaderStatus::Controls::CurrentMembers
6
- end
7
- end
8
- end
9
- end
@@ -1,31 +0,0 @@
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
- EventSource::NoStream.name
19
- end
20
-
21
- module Header
22
- def self.example
23
- EventSource::NoStream.version.to_s
24
- end
25
- end
26
- end
27
- end
28
- end
29
- end
30
- end
31
- end
@@ -1,13 +0,0 @@
1
- module EventSource
2
- module EventStore
3
- module HTTP
4
- module Controls
5
- module Hostname
6
- def self.example
7
- 'localhost'
8
- end
9
- end
10
- end
11
- end
12
- end
13
- end
@@ -1,15 +0,0 @@
1
- module EventSource
2
- module EventStore
3
- module HTTP
4
- module Controls
5
- module Hostname
6
- module Cluster
7
- def self.example
8
- 'localhost'
9
- end
10
- end
11
- end
12
- end
13
- end
14
- end
15
- end
@@ -1,25 +0,0 @@
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
@@ -1,25 +0,0 @@
1
- module EventSource
2
- module EventStore
3
- module HTTP
4
- module Controls
5
- module MediaType
6
- def self.example
7
- unknown
8
- end
9
-
10
- def self.events
11
- EventStore::MediaTypes.vnd_event_store_events_json
12
- end
13
-
14
- def self.stream
15
- EventStore::MediaTypes.vnd_event_store_atom_json
16
- end
17
-
18
- def self.unknown
19
- 'application/octet-stream'
20
- end
21
- end
22
- end
23
- end
24
- end
25
- end
@@ -1,41 +0,0 @@
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
@@ -1,17 +0,0 @@
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
@@ -1,19 +0,0 @@
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
@@ -1,21 +0,0 @@
1
- module EventSource
2
- module EventStore
3
- module HTTP
4
- module Controls
5
- module URI
6
- module Path
7
- module Stream
8
- def self.example(**stream_arguments)
9
- stream = Controls::Stream.example **stream_arguments
10
-
11
- stream_id = EventSource::StreamName.get_id stream.name
12
-
13
- "/streams/#{stream.category}-#{stream_id}"
14
- end
15
- end
16
- end
17
- end
18
- end
19
- end
20
- end
21
- end
@@ -1,13 +0,0 @@
1
- module EventSource
2
- module EventStore
3
- module MediaTypes
4
- def self.vnd_event_store_atom_json
5
- 'application/vnd.eventstore.atom+json'
6
- end
7
-
8
- def self.vnd_event_store_events_json
9
- 'application/vnd.eventstore.events+json'
10
- end
11
- end
12
- end
13
- end
@@ -1,27 +0,0 @@
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
@@ -1,64 +0,0 @@
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
@@ -1,75 +0,0 @@
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 = EventSource::ExpectedVersion.canonize expected_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
- end
72
- end
73
- end
74
- end
75
- end
@@ -1,28 +0,0 @@
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
@@ -1,22 +0,0 @@
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
@@ -1,19 +0,0 @@
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
@@ -1,41 +0,0 @@
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
@@ -1,43 +0,0 @@
1
- module EventSource
2
- module EventStore
3
- module HTTP
4
- class Session
5
- module Substitute
6
- def self.build
7
- Session.new
8
- end
9
-
10
- Response = Struct.new :code, :message, :body
11
-
12
- class Session
13
- attr_writer :status_code
14
- attr_writer :reason_phrase
15
- attr_accessor :response_body
16
-
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
23
- end
24
-
25
- def set_response(status_code, response_body=nil, reason_phrase: nil)
26
- self.status_code = status_code
27
- self.reason_phrase = reason_phrase
28
- self.response_body = response_body if response_body
29
- end
30
-
31
- def status_code
32
- @status_code ||= 404
33
- end
34
-
35
- def reason_phrase
36
- @reason_phrase ||= 'Not found'
37
- end
38
- end
39
- end
40
- end
41
- end
42
- end
43
- end
@@ -1,84 +0,0 @@
1
- module EventSource
2
- module EventStore
3
- module HTTP
4
- class Session
5
- module Telemetry
6
- class Sink
7
- include ::Telemetry::Sink
8
-
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
28
- end
29
-
30
- module RegisterSink
31
- def register_telemetry_sink(instance)
32
- sink = Telemetry::Sink.new
33
-
34
- instance.telemetry.register sink
35
-
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,
48
- :path,
49
- :status_code,
50
- :reason_phrase,
51
- :response_body,
52
- :acceptable_media_type,
53
- :request_body,
54
- :content_type
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
80
- end
81
- end
82
- end
83
- end
84
- end