evt-event_store-http 0.0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/event_store/http/cluster/member_state.rb +28 -0
- data/lib/event_store/http/connect/defaults.rb +11 -0
- data/lib/event_store/http/connect/leader.rb +37 -0
- data/lib/event_store/http/connect.rb +69 -0
- data/lib/event_store/http/controls/cluster/current_members.rb +52 -0
- data/lib/event_store/http/controls/cluster/size.rb +13 -0
- data/lib/event_store/http/controls/event.rb +43 -0
- data/lib/event_store/http/controls/gossip/response/json.rb +91 -0
- data/lib/event_store/http/controls/gossip/response/member.rb +114 -0
- data/lib/event_store/http/controls/gossip/response.rb +17 -0
- data/lib/event_store/http/controls/hostname/cluster.rb +67 -0
- data/lib/event_store/http/controls/hostname/resolution.rb +61 -0
- data/lib/event_store/http/controls/hostname.rb +35 -0
- data/lib/event_store/http/controls/info/response/json.rb +25 -0
- data/lib/event_store/http/controls/info/response.rb +21 -0
- data/lib/event_store/http/controls/ip_address/cluster.rb +77 -0
- data/lib/event_store/http/controls/ip_address.rb +23 -0
- data/lib/event_store/http/controls/json.rb +27 -0
- data/lib/event_store/http/controls/media_types/atom/event/content.rb +47 -0
- data/lib/event_store/http/controls/media_types/atom/event/json.rb +52 -0
- data/lib/event_store/http/controls/media_types/atom/event/links.rb +28 -0
- data/lib/event_store/http/controls/media_types/atom/event.rb +46 -0
- data/lib/event_store/http/controls/media_types/atom/page/entries.rb +131 -0
- data/lib/event_store/http/controls/media_types/atom/page/json/backward.rb +115 -0
- data/lib/event_store/http/controls/media_types/atom/page/json/embed/body.rb +150 -0
- data/lib/event_store/http/controls/media_types/atom/page/json/embed/rich.rb +144 -0
- data/lib/event_store/http/controls/media_types/atom/page/json.rb +113 -0
- data/lib/event_store/http/controls/media_types/atom/page/links.rb +70 -0
- data/lib/event_store/http/controls/media_types/atom/page.rb +43 -0
- data/lib/event_store/http/controls/media_types/events/json.rb +25 -0
- data/lib/event_store/http/controls/media_types/events.rb +39 -0
- data/lib/event_store/http/controls/net_http/host_header.rb +41 -0
- data/lib/event_store/http/controls/net_http/request/post.rb +36 -0
- data/lib/event_store/http/controls/net_http/request.rb +13 -0
- data/lib/event_store/http/controls/net_http.rb +14 -0
- data/lib/event_store/http/controls/port.rb +29 -0
- data/lib/event_store/http/controls/read_event/output_schema.rb +43 -0
- data/lib/event_store/http/controls/read_stream/output_schema/optimized.rb +66 -0
- data/lib/event_store/http/controls/read_stream/output_schema.rb +50 -0
- data/lib/event_store/http/controls/session_type.rb +15 -0
- data/lib/event_store/http/controls/stream.rb +17 -0
- data/lib/event_store/http/controls/time.rb +7 -0
- data/lib/event_store/http/controls/uri/event.rb +24 -0
- data/lib/event_store/http/controls/uuid.rb +7 -0
- data/lib/event_store/http/controls/write.rb +22 -0
- data/lib/event_store/http/controls.rb +59 -0
- data/lib/event_store/http/gossip/response/member.rb +40 -0
- data/lib/event_store/http/gossip/response/transformer.rb +49 -0
- data/lib/event_store/http/gossip/response.rb +25 -0
- data/lib/event_store/http/gossip.rb +28 -0
- data/lib/event_store/http/info/response/transformer.rb +28 -0
- data/lib/event_store/http/info/response.rb +25 -0
- data/lib/event_store/http/info.rb +28 -0
- data/lib/event_store/http/json/deserialize.rb +25 -0
- data/lib/event_store/http/json/serialize.rb +20 -0
- data/lib/event_store/http/log.rb +20 -0
- data/lib/event_store/http/media_types/atom/event/transformer.rb +44 -0
- data/lib/event_store/http/media_types/atom/event.rb +28 -0
- data/lib/event_store/http/media_types/atom/links.rb +18 -0
- data/lib/event_store/http/media_types/atom/page/embed/body/transformer.rb +43 -0
- data/lib/event_store/http/media_types/atom/page/embed/none/transformer.rb +45 -0
- data/lib/event_store/http/media_types/atom/page/embed/rich/event.rb +33 -0
- data/lib/event_store/http/media_types/atom/page/embed/rich/transformer.rb +63 -0
- data/lib/event_store/http/media_types/atom/page/transformer.rb +11 -0
- data/lib/event_store/http/media_types/atom/page.rb +17 -0
- data/lib/event_store/http/media_types/atom.rb +11 -0
- data/lib/event_store/http/media_types/events/data.rb +46 -0
- data/lib/event_store/http/media_types/events.rb +11 -0
- data/lib/event_store/http/net_http/extensions.rb +34 -0
- data/lib/event_store/http/net_http/substitute/telemetry.rb +19 -0
- data/lib/event_store/http/net_http/substitute.rb +112 -0
- data/lib/event_store/http/net_http.rb +11 -0
- data/lib/event_store/http/read_event/log_text.rb +17 -0
- data/lib/event_store/http/read_event/substitute.rb +35 -0
- data/lib/event_store/http/read_event.rb +72 -0
- data/lib/event_store/http/read_stream/defaults.rb +31 -0
- data/lib/event_store/http/read_stream/log_text.rb +17 -0
- data/lib/event_store/http/read_stream/substitute.rb +90 -0
- data/lib/event_store/http/read_stream.rb +100 -0
- data/lib/event_store/http/request.rb +48 -0
- data/lib/event_store/http/retry/substitute.rb +44 -0
- data/lib/event_store/http/retry/telemetry.rb +15 -0
- data/lib/event_store/http/retry.rb +98 -0
- data/lib/event_store/http/session/any_member.rb +9 -0
- data/lib/event_store/http/session/defaults.rb +11 -0
- data/lib/event_store/http/session/factory.rb +74 -0
- data/lib/event_store/http/session/leader.rb +33 -0
- data/lib/event_store/http/session/log_text.rb +41 -0
- data/lib/event_store/http/session/read.rb +22 -0
- data/lib/event_store/http/session.rb +100 -0
- data/lib/event_store/http/settings/read.rb +29 -0
- data/lib/event_store/http/settings.rb +27 -0
- data/lib/event_store/http/write/log_text.rb +17 -0
- data/lib/event_store/http/write/substitute.rb +52 -0
- data/lib/event_store/http/write.rb +82 -0
- data/lib/event_store/http.rb +77 -0
- metadata +237 -0
@@ -0,0 +1,31 @@
|
|
1
|
+
module EventStore
|
2
|
+
module HTTP
|
3
|
+
class ReadStream
|
4
|
+
module Defaults
|
5
|
+
def self.batch_size
|
6
|
+
batch_size = ENV['EVENT_STORE_HTTP_READ_BATCH_SIZE']
|
7
|
+
|
8
|
+
return batch_size.to_i if batch_size
|
9
|
+
|
10
|
+
20
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.direction
|
14
|
+
:forward
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.long_poll_duration
|
18
|
+
long_poll_duration = ENV['EVENT_STORE_HTTP_LONG_POLL_DURATION']
|
19
|
+
|
20
|
+
return long_poll_duration.to_i if long_poll_duration
|
21
|
+
|
22
|
+
2
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.position
|
26
|
+
0
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module EventStore
|
2
|
+
module HTTP
|
3
|
+
class ReadStream
|
4
|
+
module LogText
|
5
|
+
def self.attributes(stream, position, batch_size, direction, response: nil)
|
6
|
+
text = "Stream: #{stream}, Position: #{position}, BatchSize: #{batch_size}"
|
7
|
+
|
8
|
+
unless response.nil?
|
9
|
+
text << ", StatusCode: #{response.code}, ReasonPhrase: #{response.message}, ContentLength: #{response.body&.bytesize.to_i}"
|
10
|
+
end
|
11
|
+
|
12
|
+
text
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
module EventStore
|
2
|
+
module HTTP
|
3
|
+
class ReadStream
|
4
|
+
module Substitute
|
5
|
+
def self.build
|
6
|
+
ReadStream.build
|
7
|
+
end
|
8
|
+
|
9
|
+
class ReadStream
|
10
|
+
initializer :telemetry_sink
|
11
|
+
|
12
|
+
attr_accessor :body_embed_enabled
|
13
|
+
attr_accessor :long_poll_enabled
|
14
|
+
attr_accessor :rich_embed_enabled
|
15
|
+
|
16
|
+
dependency :telemetry, ::Telemetry
|
17
|
+
|
18
|
+
def self.build
|
19
|
+
telemetry_sink = Telemetry::Sink.new
|
20
|
+
|
21
|
+
instance = new telemetry_sink
|
22
|
+
|
23
|
+
telemetry = ::Telemetry.configure instance
|
24
|
+
telemetry.register telemetry_sink
|
25
|
+
|
26
|
+
instance
|
27
|
+
end
|
28
|
+
|
29
|
+
def call(stream, position: nil, direction: nil, batch_size: nil)
|
30
|
+
unless direction.nil?
|
31
|
+
unless EventStore::HTTP::ReadStream.directions.include? direction
|
32
|
+
raise ArgumentError
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
page = streams.fetch stream do
|
37
|
+
raise EventStore::HTTP::ReadStream::StreamNotFoundError
|
38
|
+
end
|
39
|
+
|
40
|
+
telemetry.record :read, Telemetry::Read.new(stream, position, direction, batch_size)
|
41
|
+
|
42
|
+
page
|
43
|
+
end
|
44
|
+
|
45
|
+
def read?(&block)
|
46
|
+
block ||= proc { true }
|
47
|
+
|
48
|
+
telemetry_sink.recorded? do |record|
|
49
|
+
block.(*record.data.to_a)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def enable_long_poll
|
54
|
+
self.long_poll_enabled = true
|
55
|
+
end
|
56
|
+
|
57
|
+
def embed_rich
|
58
|
+
self.rich_embed_enabled = true
|
59
|
+
end
|
60
|
+
|
61
|
+
def embed_body
|
62
|
+
self.body_embed_enabled = true
|
63
|
+
end
|
64
|
+
|
65
|
+
def set_response(stream, page, position: nil)
|
66
|
+
streams[stream] = page
|
67
|
+
end
|
68
|
+
|
69
|
+
def streams
|
70
|
+
@streams ||= {}
|
71
|
+
end
|
72
|
+
|
73
|
+
alias_method :long_poll_enabled?, :long_poll_enabled
|
74
|
+
alias_method :rich_embed_enabled?, :rich_embed_enabled
|
75
|
+
alias_method :body_embed_enabled?, :body_embed_enabled
|
76
|
+
end
|
77
|
+
|
78
|
+
module Telemetry
|
79
|
+
class Sink
|
80
|
+
include ::Telemetry::Sink
|
81
|
+
|
82
|
+
record :read
|
83
|
+
end
|
84
|
+
|
85
|
+
Read = Struct.new :stream, :position, :direction, :batch_size
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
module EventStore
|
2
|
+
module HTTP
|
3
|
+
class ReadStream
|
4
|
+
include Log::Dependency
|
5
|
+
include Request
|
6
|
+
|
7
|
+
configure :read_stream
|
8
|
+
|
9
|
+
attr_accessor :long_poll_duration
|
10
|
+
attr_accessor :embed
|
11
|
+
|
12
|
+
attr_writer :output_schema
|
13
|
+
|
14
|
+
def output_schema
|
15
|
+
@output_schema ||= default_output_schema
|
16
|
+
end
|
17
|
+
|
18
|
+
def call(stream, position: nil, batch_size: nil, direction: nil)
|
19
|
+
batch_size ||= Defaults.batch_size
|
20
|
+
position ||= Defaults.position
|
21
|
+
direction ||= Defaults.direction
|
22
|
+
|
23
|
+
logger.trace { "Reading stream (#{LogText.attributes stream, position, batch_size, direction})" }
|
24
|
+
|
25
|
+
unless self.class.directions.include? direction
|
26
|
+
error_message = "Invalid direction; not `forward' or `backward' (#{LogText.attributes stream, position, batch_size, direction})"
|
27
|
+
logger.trace { error_message }
|
28
|
+
raise ArgumentError, error_message
|
29
|
+
end
|
30
|
+
|
31
|
+
slice_path = self.slice_path stream, position, batch_size, direction
|
32
|
+
|
33
|
+
request = Net::HTTP::Get.new slice_path
|
34
|
+
request['Accept'] = MediaTypes::Atom.mime
|
35
|
+
request['ES-LongPoll'] = long_poll_duration.to_s if long_poll_duration
|
36
|
+
|
37
|
+
response = connection.request request
|
38
|
+
|
39
|
+
case response
|
40
|
+
when Net::HTTPSuccess
|
41
|
+
page = Transform::Read.(response.body, :json, output_schema)
|
42
|
+
|
43
|
+
logger.info { "Stream read (#{LogText.attributes stream, position, batch_size, direction, response: response}, OutputSchema: #{output_schema})" }
|
44
|
+
|
45
|
+
page
|
46
|
+
|
47
|
+
when Net::HTTPNotFound
|
48
|
+
error_message = "Stream not found (#{LogText.attributes stream, position, batch_size, direction, response: response})"
|
49
|
+
logger.error error_message
|
50
|
+
raise StreamNotFoundError, error_message
|
51
|
+
|
52
|
+
else
|
53
|
+
error_message = "Client error (#{LogText.attributes stream, position, batch_size, direction, response: response})"
|
54
|
+
logger.error error_message
|
55
|
+
raise Error, error_message
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def slice_path(stream, position, batch_size, direction)
|
60
|
+
path = "/streams/#{stream}/#{position}/#{direction}/#{batch_size}"
|
61
|
+
|
62
|
+
if embed
|
63
|
+
path << "?embed=#{embed}"
|
64
|
+
end
|
65
|
+
|
66
|
+
path
|
67
|
+
end
|
68
|
+
|
69
|
+
def default_output_schema
|
70
|
+
case embed
|
71
|
+
when :body
|
72
|
+
MediaTypes::Atom::Page::Embed::Body
|
73
|
+
when :rich
|
74
|
+
MediaTypes::Atom::Page::Embed::Rich
|
75
|
+
else
|
76
|
+
MediaTypes::Atom::Page::Embed::None
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def enable_long_poll
|
81
|
+
self.long_poll_duration = Defaults.long_poll_duration
|
82
|
+
end
|
83
|
+
|
84
|
+
def embed_rich
|
85
|
+
self.embed = :rich
|
86
|
+
end
|
87
|
+
|
88
|
+
def embed_body
|
89
|
+
self.embed = :body
|
90
|
+
end
|
91
|
+
|
92
|
+
def self.directions
|
93
|
+
[:forward, :backward]
|
94
|
+
end
|
95
|
+
|
96
|
+
Error = Class.new StandardError
|
97
|
+
StreamNotFoundError = Class.new Error
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module EventStore
|
2
|
+
module HTTP
|
3
|
+
module Request
|
4
|
+
def self.included(cls)
|
5
|
+
cls.class_exec do
|
6
|
+
dependency :connection, Net::HTTP
|
7
|
+
|
8
|
+
extend Build
|
9
|
+
extend Call
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
Virtual::Method.define self, :call
|
14
|
+
|
15
|
+
Virtual::Method.define self, :configure do |session: nil|
|
16
|
+
end
|
17
|
+
|
18
|
+
module Build
|
19
|
+
def build(connection: nil, session: nil)
|
20
|
+
instance = new
|
21
|
+
|
22
|
+
if session.nil?
|
23
|
+
Connect.configure_connection instance, connection: connection
|
24
|
+
elsif !connection.nil?
|
25
|
+
raise ArgumentError, "Cannot specify both connection and session"
|
26
|
+
else
|
27
|
+
instance.connection = session
|
28
|
+
end
|
29
|
+
|
30
|
+
instance.configure(session: session)
|
31
|
+
instance
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
module Call
|
36
|
+
def call(*arguments, connection: nil, session: nil, **keyword_arguments)
|
37
|
+
instance = build connection: connection, session: session
|
38
|
+
|
39
|
+
if keyword_arguments.empty?
|
40
|
+
instance.(*arguments)
|
41
|
+
else
|
42
|
+
instance.(*arguments, **keyword_arguments)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module EventStore
|
2
|
+
module HTTP
|
3
|
+
class Retry
|
4
|
+
module Substitute
|
5
|
+
def self.build
|
6
|
+
Retry.build
|
7
|
+
end
|
8
|
+
|
9
|
+
class Retry < Retry
|
10
|
+
attr_accessor :error
|
11
|
+
attr_accessor :telemetry_sink
|
12
|
+
|
13
|
+
def self.build
|
14
|
+
instance = new
|
15
|
+
|
16
|
+
::Telemetry.configure instance
|
17
|
+
instance.telemetry_sink = Retry.register_telemetry_sink instance
|
18
|
+
|
19
|
+
instance.retry_duration = 0
|
20
|
+
instance.retry_limit = 1
|
21
|
+
instance
|
22
|
+
end
|
23
|
+
|
24
|
+
def call(&block)
|
25
|
+
super do |_, retries|
|
26
|
+
return_value = block.(self, retries)
|
27
|
+
|
28
|
+
if error = self.error
|
29
|
+
self.error = nil
|
30
|
+
raise error
|
31
|
+
end
|
32
|
+
|
33
|
+
return_value
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def set_error(error)
|
38
|
+
self.error = error
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
module EventStore
|
2
|
+
module HTTP
|
3
|
+
class Retry
|
4
|
+
include Log::Dependency
|
5
|
+
|
6
|
+
configure :retry
|
7
|
+
|
8
|
+
dependency :telemetry, ::Telemetry
|
9
|
+
|
10
|
+
setting :retry_limit
|
11
|
+
setting :retry_duration
|
12
|
+
|
13
|
+
def retry_limit
|
14
|
+
@retry_limit ||= Defaults.retry_limit
|
15
|
+
end
|
16
|
+
|
17
|
+
def retry_duration
|
18
|
+
@retry_duration ||= Defaults.retry_duration
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.build(settings=nil, namespace: nil)
|
22
|
+
settings ||= Settings.instance
|
23
|
+
namespace ||= Array(namespace)
|
24
|
+
|
25
|
+
instance = new
|
26
|
+
::Telemetry.configure instance
|
27
|
+
settings.set instance, namespace
|
28
|
+
instance
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.register_telemetry_sink(instance)
|
32
|
+
sink = Telemetry::Sink.new
|
33
|
+
instance.telemetry.register sink
|
34
|
+
sink
|
35
|
+
end
|
36
|
+
|
37
|
+
def call(&block)
|
38
|
+
retries ||= 0
|
39
|
+
|
40
|
+
logger.trace { "Performing operation (Retries: #{retries}/#{retry_limit})" }
|
41
|
+
|
42
|
+
return_value = block.(self, retries)
|
43
|
+
|
44
|
+
logger.debug { "Operation succeeded (Retries: #{retries}/#{retry_limit})" }
|
45
|
+
|
46
|
+
return_value
|
47
|
+
|
48
|
+
rescue => error
|
49
|
+
if retries == retry_limit
|
50
|
+
logger.error { "Operation failed; retry limit exceeded (Retries: #{retries}/#{retry_limit}, ErrorClass: #{error.class}, ErrorMessage: #{error.message.empty? ? '(none)' : error.message})" }
|
51
|
+
raise error
|
52
|
+
end
|
53
|
+
|
54
|
+
logger.warn { "Operation failed; retrying (Retries: #{retries}/#{retry_limit}, ErrorClass: #{error.class}, ErrorMessage: #{error.message.empty? ? '(none)' : error.message})" }
|
55
|
+
|
56
|
+
retries += 1
|
57
|
+
sleep retry_duration_seconds
|
58
|
+
record_retry error, retries
|
59
|
+
|
60
|
+
retry
|
61
|
+
end
|
62
|
+
|
63
|
+
def failed(error=nil)
|
64
|
+
error ||= Trigger.new
|
65
|
+
|
66
|
+
raise error
|
67
|
+
end
|
68
|
+
|
69
|
+
def record_retry(error, retries)
|
70
|
+
telemetry.record :retried, Telemetry::Retried.new(error, retries, retry_limit)
|
71
|
+
end
|
72
|
+
|
73
|
+
def retry_duration_seconds
|
74
|
+
Rational(retry_duration, 1_000)
|
75
|
+
end
|
76
|
+
|
77
|
+
Trigger = Class.new StandardError
|
78
|
+
|
79
|
+
module Defaults
|
80
|
+
def self.retry_duration
|
81
|
+
value = ENV['EVENT_STORE_HTTP_RETRY_DURATION']
|
82
|
+
|
83
|
+
return value.to_i if value
|
84
|
+
|
85
|
+
300
|
86
|
+
end
|
87
|
+
|
88
|
+
def self.retry_limit
|
89
|
+
value = ENV['EVENT_STORE_HTTP_RETRY_LIMIT']
|
90
|
+
|
91
|
+
return value.to_i if value
|
92
|
+
|
93
|
+
3
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module EventStore
|
2
|
+
module HTTP
|
3
|
+
module Session
|
4
|
+
class Factory
|
5
|
+
include Log::Dependency
|
6
|
+
|
7
|
+
initializer :settings, :namespace
|
8
|
+
|
9
|
+
attr_writer :type
|
10
|
+
|
11
|
+
def type
|
12
|
+
@type ||= get_type
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.build(settings=nil, namespace: nil, type: nil)
|
16
|
+
settings ||= Settings.instance
|
17
|
+
namespace = Array(namespace)
|
18
|
+
|
19
|
+
instance = new settings, namespace
|
20
|
+
instance.type = type unless type.nil?
|
21
|
+
instance
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.call(settings=nil, **arguments)
|
25
|
+
instance = build settings, **arguments
|
26
|
+
instance.()
|
27
|
+
end
|
28
|
+
|
29
|
+
def call
|
30
|
+
logger.trace { "Constructing Session (Type: #{type.inspect})" }
|
31
|
+
|
32
|
+
cls = resolve_class
|
33
|
+
|
34
|
+
instance = cls.new
|
35
|
+
|
36
|
+
settings.set instance, namespace
|
37
|
+
|
38
|
+
Retry.configure instance, settings, namespace: namespace
|
39
|
+
Log::Data.configure instance, Session, attr_name: :data_logger
|
40
|
+
connect = Connect.configure instance, settings, namespace: namespace
|
41
|
+
|
42
|
+
instance.configure
|
43
|
+
|
44
|
+
logger.debug { "Session constructed (Type: #{type.inspect}, Class: #{instance.class})" }
|
45
|
+
|
46
|
+
instance
|
47
|
+
end
|
48
|
+
|
49
|
+
def get_type
|
50
|
+
type = settings.get :type, namespace
|
51
|
+
type ||= Defaults.type
|
52
|
+
type.to_sym
|
53
|
+
end
|
54
|
+
|
55
|
+
def resolve_class
|
56
|
+
self.class.types.fetch type do
|
57
|
+
error_message = "Unknown session type (Type: #{type.inspect}, KnownTypes: #{self.class.types.keys.inspect})"
|
58
|
+
logger.error { error_message }
|
59
|
+
raise UnknownType, error_message
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.types
|
64
|
+
@types ||= {
|
65
|
+
:any_member => AnyMember,
|
66
|
+
:leader => Leader
|
67
|
+
}
|
68
|
+
end
|
69
|
+
|
70
|
+
UnknownType = Class.new StandardError
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module EventStore
|
2
|
+
module HTTP
|
3
|
+
module Session
|
4
|
+
class Leader
|
5
|
+
include Session
|
6
|
+
|
7
|
+
def configure
|
8
|
+
connect.extend Connect::Leader
|
9
|
+
end
|
10
|
+
|
11
|
+
def request(request)
|
12
|
+
request['ES-RequireMaster'] ||= 'True'
|
13
|
+
|
14
|
+
response = super
|
15
|
+
|
16
|
+
if Net::HTTPRedirection === response
|
17
|
+
location = URI.parse response['location']
|
18
|
+
|
19
|
+
leader_ip_address = location.host
|
20
|
+
|
21
|
+
net_http = reconnect leader_ip_address
|
22
|
+
|
23
|
+
reset_request request
|
24
|
+
|
25
|
+
response = request request
|
26
|
+
end
|
27
|
+
|
28
|
+
response
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module EventStore
|
2
|
+
module HTTP
|
3
|
+
module Session
|
4
|
+
module LogText
|
5
|
+
def self.request(request, response=nil)
|
6
|
+
text = %[Action: #{request.method}, Path: #{request.path}, RequestLength: #{request.body&.bytesize.to_i}]
|
7
|
+
|
8
|
+
unless response.nil?
|
9
|
+
text << %[, StatusCode: #{response.code}, ReasonPhrase: #{response.message}, ResponseLength: #{response.body&.bytesize.to_i}]
|
10
|
+
end
|
11
|
+
|
12
|
+
text
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.header_data(message)
|
16
|
+
text = String.new
|
17
|
+
|
18
|
+
message.each_header do |name, value|
|
19
|
+
text << "#{name}: #{value}\n"
|
20
|
+
end
|
21
|
+
|
22
|
+
if text.empty?
|
23
|
+
text << "(none)"
|
24
|
+
else
|
25
|
+
text.insert 0, "\n\n"
|
26
|
+
end
|
27
|
+
|
28
|
+
text
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.body_data(message)
|
32
|
+
if message.body.to_s.empty?
|
33
|
+
'(none)'
|
34
|
+
else
|
35
|
+
"\n\n#{message.body}\n"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module EventStore
|
2
|
+
module HTTP
|
3
|
+
module Session
|
4
|
+
module Read
|
5
|
+
def self.get(settings=nil, namespace: nil)
|
6
|
+
settings = Settings::Read.get settings, namespace: namespace
|
7
|
+
|
8
|
+
Session.build settings
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.configure(receiver, settings=nil, namespace: nil, attr_name: nil, session: nil)
|
12
|
+
attr_name ||= :session
|
13
|
+
|
14
|
+
session ||= get settings, namespace: namespace
|
15
|
+
|
16
|
+
receiver.public_send "#{attr_name}=", session
|
17
|
+
session
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|