evt-event_source-event_store-http 0.2.0.0 → 0.3.0.0

Sign up to get free protection for your applications and to get access to all the features.
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