event_store_client 0.2.0 → 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +8 -0
- data/lib/event_store_client.rb +1 -9
- data/lib/event_store_client/broker.rb +4 -3
- data/lib/event_store_client/client.rb +13 -5
- data/lib/event_store_client/configuration.rb +36 -17
- data/lib/event_store_client/data_decryptor.rb +1 -1
- data/lib/event_store_client/data_encryptor.rb +1 -1
- data/lib/event_store_client/encryption_metadata.rb +1 -1
- data/lib/event_store_client/event.rb +2 -2
- data/lib/event_store_client/mapper/default.rb +2 -1
- data/lib/event_store_client/mapper/encrypted.rb +3 -3
- data/lib/event_store_client/serializer/json.rb +4 -0
- data/lib/event_store_client/store_adapter/api/client.rb +66 -9
- data/lib/event_store_client/store_adapter/api/connection.rb +13 -6
- data/lib/event_store_client/store_adapter/in_memory.rb +41 -6
- data/lib/event_store_client/subscriptions.rb +2 -1
- data/lib/event_store_client/version.rb +1 -1
- metadata +28 -16
- data/lib/event_store_client/connection.rb +0 -112
- data/lib/event_store_client/endpoint.rb +0 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: daaf4a7e189d14224fa8b520345b9108f6c9c02316d57742d599b3fe5fb15e22
|
4
|
+
data.tar.gz: 9eb7350e33cd14b7e9aff5ed2d8cf313838b6fe1df739ba5c4348111f18ec323
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 803a1ac900741c28a9437135e48343d015eec4d55c3b1df5d536575bed13341f276aa85d24cb177cdf376284b1be7a0220b8b1bdde4bab558481b39f6ae930a4
|
7
|
+
data.tar.gz: 0fa249206dcbe74719fae1ba82e85de615d332cd82dc69d890154839e2fcccc7e6feb4269afc94fb9d46156816582a71a71afe364767c005e6ac101545c4b6e8
|
data/README.md
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+

|
2
|
+
[](https://badge.fury.io/rb/event_store_client)
|
3
|
+
|
1
4
|
# EventStoreClient
|
2
5
|
|
3
6
|
An easy-to use API client for connecting ruby applications with https://eventstore.org/
|
@@ -252,6 +255,11 @@ Do you want to contribute? Welcome!
|
|
252
255
|
2. Create Issue
|
253
256
|
3. Create PR ;)
|
254
257
|
|
258
|
+
### Publishing new version
|
259
|
+
|
260
|
+
1. Push commit with updated `version.rb` file to the `release` branch. The new version will be automatically pushed to [rubygems](https://rubygems.org).
|
261
|
+
2. Create release on github including change log.
|
262
|
+
|
255
263
|
## License
|
256
264
|
|
257
265
|
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/lib/event_store_client.rb
CHANGED
@@ -1,27 +1,19 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module EventStoreClient
|
4
|
-
def self.configure(&block)
|
5
|
-
config = Configuration.instance
|
6
|
-
config.configure(&block)
|
7
|
-
end
|
8
4
|
end
|
9
5
|
|
10
|
-
require 'event_store_client/configuration'
|
11
6
|
require 'event_store_client/types'
|
12
7
|
require 'event_store_client/event'
|
13
8
|
require 'event_store_client/deserialized_event'
|
14
|
-
|
15
9
|
require 'event_store_client/serializer/json'
|
16
10
|
|
17
11
|
require 'event_store_client/mapper'
|
18
12
|
|
19
|
-
require 'event_store_client/
|
13
|
+
require 'event_store_client/configuration'
|
20
14
|
|
21
15
|
require 'event_store_client/store_adapter'
|
22
16
|
|
23
|
-
require 'event_store_client/connection'
|
24
|
-
|
25
17
|
require 'event_store_client/subscription'
|
26
18
|
require 'event_store_client/subscriptions'
|
27
19
|
require 'event_store_client/broker'
|
@@ -4,9 +4,10 @@ module EventStoreClient
|
|
4
4
|
class Broker
|
5
5
|
def call(subscriptions)
|
6
6
|
subscriptions.each do |subscription|
|
7
|
-
|
8
|
-
next if
|
9
|
-
|
7
|
+
res = connection.consume_feed(subscription.stream, subscription.name) || { events: [] }
|
8
|
+
next if res[:events].none?
|
9
|
+
res[:events].each { |event| subscription.subscriber.call(event) }
|
10
|
+
connection.ack(res[:ack_uri])
|
10
11
|
end
|
11
12
|
end
|
12
13
|
|
@@ -8,13 +8,21 @@ module EventStoreClient
|
|
8
8
|
WrongExpectedEventVersion = Class.new(StandardError)
|
9
9
|
|
10
10
|
def publish(stream:, events:, expected_version: nil)
|
11
|
-
connection.
|
11
|
+
connection.append_to_stream(stream, events, expected_version: expected_version)
|
12
12
|
rescue StoreAdapter::Api::Client::WrongExpectedEventVersion => e
|
13
13
|
raise WrongExpectedEventVersion.new(e.message)
|
14
14
|
end
|
15
15
|
|
16
|
-
def read(stream, direction: 'forward', start: 0, all: false)
|
17
|
-
|
16
|
+
def read(stream, direction: 'forward', start: 0, all: false, resolve_links: true)
|
17
|
+
if all
|
18
|
+
connection.read_all_from_stream(
|
19
|
+
stream, start: start, direction: direction, resolve_links: resolve_links
|
20
|
+
)
|
21
|
+
else
|
22
|
+
connection.read(
|
23
|
+
stream, start: start, direction: direction, resolve_links: resolve_links
|
24
|
+
)
|
25
|
+
end
|
18
26
|
end
|
19
27
|
|
20
28
|
def subscribe(subscriber, to: [], polling: true)
|
@@ -81,12 +89,12 @@ module EventStoreClient
|
|
81
89
|
attr_reader :subscriptions, :broker, :error_handler
|
82
90
|
|
83
91
|
def config
|
84
|
-
EventStoreClient
|
92
|
+
EventStoreClient.config
|
85
93
|
end
|
86
94
|
|
87
95
|
def initialize
|
88
96
|
@threads = []
|
89
|
-
@connection ||=
|
97
|
+
@connection ||= EventStoreClient.adapter
|
90
98
|
@error_handler ||= config.error_handler
|
91
99
|
@service_name ||= 'default'
|
92
100
|
@broker ||= Broker.new(connection: connection)
|
@@ -1,28 +1,47 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'dry-
|
4
|
-
require 'singleton'
|
3
|
+
require 'dry-configurable'
|
5
4
|
|
6
5
|
module EventStoreClient
|
7
|
-
|
8
|
-
include Singleton
|
6
|
+
extend Dry::Configurable
|
9
7
|
|
10
|
-
|
8
|
+
# Supported adapters: %i[api in_memory]
|
9
|
+
#
|
10
|
+
setting :adapter, :api
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
setting :error_handler
|
13
|
+
setting :eventstore_url, 'http://localhost:2113' do |value|
|
14
|
+
value.is_a?(URI) ? value : URI(value)
|
15
|
+
end
|
16
|
+
|
17
|
+
setting :eventstore_user, 'admin'
|
18
|
+
setting :eventstore_password, 'changeit'
|
19
|
+
|
20
|
+
setting :db_port, 2113
|
21
|
+
|
22
|
+
setting :per_page, 20
|
23
|
+
setting :pid_path, 'tmp/poll.pid'
|
15
24
|
|
16
|
-
|
25
|
+
setting :service_name, 'default'
|
17
26
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
27
|
+
setting :mapper, Mapper::Default.new
|
28
|
+
|
29
|
+
def self.configure
|
30
|
+
yield(config) if block_given?
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.adapter
|
34
|
+
case config.adapter
|
35
|
+
when :api
|
36
|
+
StoreAdapter::Api::Client.new(
|
37
|
+
config.eventstore_url,
|
38
|
+
per_page: config.per_page,
|
39
|
+
mapper: config.mapper,
|
40
|
+
connection_options: {}
|
41
|
+
)
|
42
|
+
else
|
43
|
+
StoreAdapter::InMemory.new(
|
44
|
+
mapper: config.mapper, per_page: config.per_page
|
26
45
|
)
|
27
46
|
end
|
28
47
|
end
|
@@ -28,7 +28,7 @@ module EventStoreClient
|
|
28
28
|
|
29
29
|
def decrypt_attributes(key:, data:, attributes:)
|
30
30
|
decrypted_text = key_repository.decrypt(
|
31
|
-
key_id: key.id, text: data[
|
31
|
+
key_id: key.id, text: data['es_encrypted'], cipher: key.cipher, iv: key.iv
|
32
32
|
)
|
33
33
|
decrypted = JSON.parse(decrypted_text).transform_keys(&:to_s)
|
34
34
|
decrypted.each { |key, value| data[key] = value if data.key?(key) }
|
@@ -9,8 +9,8 @@ module EventStoreClient
|
|
9
9
|
attribute :id, Types::Strict::String.optional.default(nil)
|
10
10
|
attribute :type, Types::Strict::String
|
11
11
|
attribute :title, Types::Strict::String.optional.default(nil)
|
12
|
-
attribute :data, Types::
|
13
|
-
attribute :metadata, Types::
|
12
|
+
attribute :data, Types::Coercible::String.default('{}')
|
13
|
+
attribute :metadata, Types::Coercible::String.default('{}')
|
14
14
|
|
15
15
|
private
|
16
16
|
|
@@ -5,7 +5,8 @@ module EventStoreClient
|
|
5
5
|
class Default
|
6
6
|
def serialize(event)
|
7
7
|
Event.new(
|
8
|
-
|
8
|
+
id: event.respond_to?(:id) ? event.id : nil,
|
9
|
+
type: (event.respond_to?(:type) ? event.type : nil) || event.class.to_s,
|
9
10
|
data: serializer.serialize(event.data),
|
10
11
|
metadata: serializer.serialize(event.metadata)
|
11
12
|
)
|
@@ -26,13 +26,13 @@ module EventStoreClient
|
|
26
26
|
event.class.respond_to?(:encryption_schema) &&
|
27
27
|
event.class.encryption_schema
|
28
28
|
)
|
29
|
-
encryptor = DataEncryptor.new(
|
29
|
+
encryptor = EventStoreClient::DataEncryptor.new(
|
30
30
|
data: event.data,
|
31
31
|
schema: encryption_schema,
|
32
32
|
repository: key_repository
|
33
33
|
)
|
34
34
|
encryptor.call
|
35
|
-
Event.new(
|
35
|
+
EventStoreClient::Event.new(
|
36
36
|
data: serializer.serialize(encryptor.encrypted_data),
|
37
37
|
metadata: serializer.serialize(
|
38
38
|
event.metadata.merge(encryption: encryptor.encryption_metadata)
|
@@ -52,7 +52,7 @@ module EventStoreClient
|
|
52
52
|
def deserialize(event)
|
53
53
|
metadata = serializer.deserialize(event.metadata)
|
54
54
|
encryption_schema = serializer.deserialize(event.metadata)['encryption']
|
55
|
-
decrypted_data = DataDecryptor.new(
|
55
|
+
decrypted_data = EventStoreClient::DataDecryptor.new(
|
56
56
|
data: serializer.deserialize(event.data),
|
57
57
|
schema: encryption_schema,
|
58
58
|
repository: key_repository
|
@@ -7,14 +7,16 @@ module EventStoreClient
|
|
7
7
|
WrongExpectedEventVersion = Class.new(StandardError)
|
8
8
|
|
9
9
|
def append_to_stream(stream_name, events, expected_version: nil)
|
10
|
+
serialized_events = events.map { |event| mapper.serialize(event) }
|
10
11
|
headers = {
|
11
12
|
'ES-ExpectedVersion' => expected_version&.to_s
|
12
13
|
}.reject { |_key, val| val.nil? || val.empty? }
|
13
14
|
|
14
|
-
data = build_events_data(
|
15
|
+
data = build_events_data(serialized_events)
|
15
16
|
response = make_request(:post, "/streams/#{stream_name}", body: data, headers: headers)
|
16
17
|
validate_response(response, expected_version)
|
17
18
|
response
|
19
|
+
serialized_events
|
18
20
|
end
|
19
21
|
|
20
22
|
def delete_stream(stream_name, hard_delete: false)
|
@@ -31,11 +33,39 @@ module EventStoreClient
|
|
31
33
|
'Accept' => 'application/vnd.eventstore.atom+json'
|
32
34
|
}
|
33
35
|
|
34
|
-
make_request(
|
36
|
+
response = make_request(
|
35
37
|
:get,
|
36
38
|
"/streams/#{stream_name}/#{start}/#{direction}/#{count}",
|
37
39
|
headers: headers
|
38
40
|
)
|
41
|
+
return [] if response.body.nil? || response.body.empty?
|
42
|
+
JSON.parse(response.body)['entries'].map do |entry|
|
43
|
+
deserialize_event(entry)
|
44
|
+
end.reverse
|
45
|
+
end
|
46
|
+
|
47
|
+
def read_all_from_stream(stream, start: 0, resolve_links: true)
|
48
|
+
count = per_page
|
49
|
+
events = []
|
50
|
+
failed_requests_count = 0
|
51
|
+
|
52
|
+
while failed_requests_count < 3
|
53
|
+
begin
|
54
|
+
response =
|
55
|
+
read(stream, start: start, direction: 'forward', resolve_links: resolve_links)
|
56
|
+
failed_requests_count += 1 && next unless response.success? || response.status == 404
|
57
|
+
rescue Faraday::ConnectionFailed
|
58
|
+
failed_requests_count += 1
|
59
|
+
next
|
60
|
+
end
|
61
|
+
failed_requests_count = 0
|
62
|
+
break if response.body.nil? || response.body.empty?
|
63
|
+
entries = JSON.parse(response.body)['entries']
|
64
|
+
break if entries.empty?
|
65
|
+
events += entries.map { |entry| deserialize_event(entry) }.reverse
|
66
|
+
start += count
|
67
|
+
end
|
68
|
+
events
|
39
69
|
end
|
40
70
|
|
41
71
|
def join_streams(name, streams)
|
@@ -79,18 +109,31 @@ module EventStoreClient
|
|
79
109
|
subscription_name,
|
80
110
|
count: 1,
|
81
111
|
long_poll: 0,
|
82
|
-
resolve_links: true
|
112
|
+
resolve_links: true,
|
113
|
+
per_page: 20
|
83
114
|
)
|
84
115
|
headers = long_poll.positive? ? { 'ES-LongPoll' => long_poll.to_s } : {}
|
85
116
|
headers['Content-Type'] = 'application/vnd.eventstore.competingatom+json'
|
86
117
|
headers['Accept'] = 'application/vnd.eventstore.competingatom+json'
|
87
118
|
headers['ES-ResolveLinktos'] = resolve_links.to_s
|
88
119
|
|
89
|
-
make_request(
|
120
|
+
response = make_request(
|
90
121
|
:get,
|
91
122
|
"/subscriptions/#{stream_name}/#{subscription_name}/#{count}",
|
92
123
|
headers: headers
|
93
124
|
)
|
125
|
+
|
126
|
+
return { events: [] } if response.body || response.body.empty?
|
127
|
+
|
128
|
+
body = JSON.parse(response.body)
|
129
|
+
|
130
|
+
ack_info = body['links'].find { |link| link['relation'] == 'ackAll' }
|
131
|
+
return unless ack_info
|
132
|
+
ack_uri = ack_info['uri']
|
133
|
+
events = body['entries'].map do |entry|
|
134
|
+
deserialize_event(entry)
|
135
|
+
end
|
136
|
+
{ ack_uri: ack_uri, events: events }
|
94
137
|
end
|
95
138
|
|
96
139
|
def link_to(stream_name, events, expected_version: nil)
|
@@ -106,7 +149,7 @@ module EventStoreClient
|
|
106
149
|
headers: headers
|
107
150
|
)
|
108
151
|
validate_response(response, expected_version)
|
109
|
-
|
152
|
+
true
|
110
153
|
end
|
111
154
|
|
112
155
|
def ack(url)
|
@@ -115,11 +158,13 @@ module EventStoreClient
|
|
115
158
|
|
116
159
|
private
|
117
160
|
|
118
|
-
attr_reader :
|
161
|
+
attr_reader :uri, :per_page, :connection_options, :mapper
|
119
162
|
|
120
|
-
def initialize(
|
121
|
-
@
|
163
|
+
def initialize(uri, per_page: 20, mapper:, connection_options: {})
|
164
|
+
@uri = uri
|
122
165
|
@per_page = per_page
|
166
|
+
@mapper = mapper
|
167
|
+
@connection_options = connection_options
|
123
168
|
end
|
124
169
|
|
125
170
|
def build_events_data(events)
|
@@ -153,7 +198,7 @@ module EventStoreClient
|
|
153
198
|
end
|
154
199
|
|
155
200
|
def connection
|
156
|
-
@connection ||= Api::Connection.new(
|
201
|
+
@connection ||= Api::Connection.new(uri, connection_options).call
|
157
202
|
end
|
158
203
|
|
159
204
|
def validate_response(resp, expected_version)
|
@@ -163,6 +208,18 @@ module EventStoreClient
|
|
163
208
|
"expected: #{expected_version}"
|
164
209
|
)
|
165
210
|
end
|
211
|
+
|
212
|
+
def deserialize_event(entry)
|
213
|
+
event = EventStoreClient::Event.new(
|
214
|
+
id: entry['eventId'],
|
215
|
+
title: entry['title'],
|
216
|
+
type: entry['eventType'],
|
217
|
+
data: entry['data'] || '{}',
|
218
|
+
metadata: entry['isMetaData'] ? entry['metaData'] : '{}'
|
219
|
+
)
|
220
|
+
|
221
|
+
mapper.deserialize(event)
|
222
|
+
end
|
166
223
|
end
|
167
224
|
end
|
168
225
|
end
|
@@ -8,21 +8,28 @@ module EventStoreClient
|
|
8
8
|
class Connection
|
9
9
|
def call
|
10
10
|
Faraday.new(
|
11
|
-
|
12
|
-
|
11
|
+
{
|
12
|
+
url: uri.to_s,
|
13
|
+
headers: DEFAULT_HEADERS
|
14
|
+
}.merge(options)
|
13
15
|
) do |conn|
|
14
|
-
conn.basic_auth(
|
16
|
+
conn.basic_auth(config.eventstore_user, config.eventstore_password)
|
15
17
|
conn.adapter Faraday.default_adapter
|
16
18
|
end
|
17
19
|
end
|
18
20
|
|
19
21
|
private
|
20
22
|
|
21
|
-
def
|
22
|
-
|
23
|
+
def config
|
24
|
+
EventStoreClient.config
|
23
25
|
end
|
24
26
|
|
25
|
-
|
27
|
+
def initialize(uri, options = {})
|
28
|
+
@uri = uri
|
29
|
+
@options = options
|
30
|
+
end
|
31
|
+
|
32
|
+
attr_reader :uri, :options
|
26
33
|
|
27
34
|
DEFAULT_HEADERS = {
|
28
35
|
'Content-Type' => 'application/vnd.eventstore.events+json'
|
@@ -13,7 +13,6 @@ module EventStoreClient
|
|
13
13
|
|
14
14
|
def append_to_stream(stream_name, events, expected_version: nil) # rubocop:disable Lint/UnusedMethodArgument,Metrics/LineLength
|
15
15
|
event_store[stream_name] = [] unless event_store.key?(stream_name)
|
16
|
-
|
17
16
|
[events].flatten.each do |event|
|
18
17
|
event_store[stream_name].unshift(
|
19
18
|
'eventId' => event.id,
|
@@ -33,7 +32,27 @@ module EventStoreClient
|
|
33
32
|
read_stream_backward(stream_name, start: start)
|
34
33
|
end
|
35
34
|
|
36
|
-
Response.new(response.to_json, 200)
|
35
|
+
res = Response.new(response.to_json, 200)
|
36
|
+
|
37
|
+
return [] if res.body.nil? || res.body.empty?
|
38
|
+
JSON.parse(res.body)['entries'].map do |entry|
|
39
|
+
deserialize_event(entry)
|
40
|
+
end.reverse
|
41
|
+
end
|
42
|
+
|
43
|
+
def read_all_from_stream(stream_name, direction: 'forward', start: 0, resolve_links: true)
|
44
|
+
response =
|
45
|
+
if direction == 'forward'
|
46
|
+
read_stream_forward(stream_name, start: start)
|
47
|
+
else
|
48
|
+
read_stream_backward(stream_name, start: start)
|
49
|
+
end
|
50
|
+
res = Response.new(response.to_json, 200)
|
51
|
+
|
52
|
+
return [] if res.body.nil? || res.body.empty?
|
53
|
+
JSON.parse(res.body)['entries'].map do |entry|
|
54
|
+
deserialize_event(entry)
|
55
|
+
end.reverse
|
37
56
|
end
|
38
57
|
|
39
58
|
def subscribe_to_stream(stream_name, subscription_name, **)
|
@@ -54,6 +73,7 @@ module EventStoreClient
|
|
54
73
|
|
55
74
|
def link_to(stream_name, events, **)
|
56
75
|
append_to_stream(stream_name, events)
|
76
|
+
events
|
57
77
|
end
|
58
78
|
|
59
79
|
def ack(url)
|
@@ -64,11 +84,11 @@ module EventStoreClient
|
|
64
84
|
|
65
85
|
private
|
66
86
|
|
67
|
-
attr_reader :
|
87
|
+
attr_reader :per_page, :mapper
|
68
88
|
|
69
|
-
def initialize(
|
70
|
-
@endpoint = Endpoint.new(host: host, port: port)
|
89
|
+
def initialize(mapper:, per_page: 20)
|
71
90
|
@per_page = per_page
|
91
|
+
@mapper = mapper
|
72
92
|
@event_store = {}
|
73
93
|
end
|
74
94
|
|
@@ -115,11 +135,26 @@ module EventStoreClient
|
|
115
135
|
else
|
116
136
|
[{
|
117
137
|
'uri' =>
|
118
|
-
"
|
138
|
+
"/streams/#{stream_name}/#{batch_size}/#{direction}/#{count}",
|
119
139
|
'relation' => direction
|
120
140
|
}]
|
121
141
|
end
|
122
142
|
end
|
143
|
+
|
144
|
+
private
|
145
|
+
|
146
|
+
def deserialize_event(entry)
|
147
|
+
data = (entry['data'].is_a?(Hash) ? entry['data'].to_json.presence : entry['data']) || '{}'
|
148
|
+
event = EventStoreClient::Event.new(
|
149
|
+
id: entry['eventId'],
|
150
|
+
title: entry['title'],
|
151
|
+
type: entry['eventType'],
|
152
|
+
data: data,
|
153
|
+
metadata: entry['isMetaData'] ? entry['metaData'] : '{}'
|
154
|
+
)
|
155
|
+
|
156
|
+
mapper.deserialize(event)
|
157
|
+
end
|
123
158
|
end
|
124
159
|
end
|
125
160
|
end
|
@@ -25,8 +25,9 @@ module EventStoreClient
|
|
25
25
|
private
|
26
26
|
|
27
27
|
def create_subscription(subscription)
|
28
|
+
# store position somewhere.
|
28
29
|
connection.join_streams(subscription.name, subscription.observed_streams)
|
29
|
-
connection.
|
30
|
+
connection.subscribe_to_stream(subscription.stream, subscription.name)
|
30
31
|
end
|
31
32
|
|
32
33
|
attr_reader :connection, :subscriptions, :service
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: event_store_client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sebastian Wilgosz
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-12-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dry-schema
|
@@ -16,56 +16,70 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 1
|
19
|
+
version: '1'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 1
|
26
|
+
version: '1'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: dry-struct
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 1
|
33
|
+
version: '1'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 1
|
40
|
+
version: '1'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: faraday
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
47
|
+
version: '1.0'
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
54
|
+
version: '1.0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rss
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - "
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: 0.2.8
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - "
|
66
|
+
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: 0.2.8
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: dry-configurable
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0.11'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0.11'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: rspec
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -108,12 +122,10 @@ files:
|
|
108
122
|
- lib/event_store_client/broker.rb
|
109
123
|
- lib/event_store_client/client.rb
|
110
124
|
- lib/event_store_client/configuration.rb
|
111
|
-
- lib/event_store_client/connection.rb
|
112
125
|
- lib/event_store_client/data_decryptor.rb
|
113
126
|
- lib/event_store_client/data_encryptor.rb
|
114
127
|
- lib/event_store_client/deserialized_event.rb
|
115
128
|
- lib/event_store_client/encryption_metadata.rb
|
116
|
-
- lib/event_store_client/endpoint.rb
|
117
129
|
- lib/event_store_client/event.rb
|
118
130
|
- lib/event_store_client/mapper.rb
|
119
131
|
- lib/event_store_client/mapper/default.rb
|
@@ -133,7 +145,7 @@ licenses:
|
|
133
145
|
- MIT
|
134
146
|
metadata:
|
135
147
|
allowed_push_host: https://rubygems.org
|
136
|
-
post_install_message:
|
148
|
+
post_install_message:
|
137
149
|
rdoc_options: []
|
138
150
|
require_paths:
|
139
151
|
- lib
|
@@ -148,8 +160,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
148
160
|
- !ruby/object:Gem::Version
|
149
161
|
version: '0'
|
150
162
|
requirements: []
|
151
|
-
rubygems_version: 3.
|
152
|
-
signing_key:
|
163
|
+
rubygems_version: 3.1.4
|
164
|
+
signing_key:
|
153
165
|
specification_version: 4
|
154
166
|
summary: Ruby integration for https://eventstore.org
|
155
167
|
test_files: []
|
@@ -1,112 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module EventStoreClient
|
4
|
-
class Connection
|
5
|
-
def publish(stream:, events:, expected_version: nil)
|
6
|
-
serialized_events = events.map { |event| mapper.serialize(event) }
|
7
|
-
client.append_to_stream(
|
8
|
-
stream, serialized_events, expected_version: expected_version
|
9
|
-
)
|
10
|
-
serialized_events
|
11
|
-
end
|
12
|
-
|
13
|
-
def read(stream, direction:, start:, all:, resolve_links: true)
|
14
|
-
return read_all_from_stream(stream, start: start, resolve_links: resolve_links) if all
|
15
|
-
read_from_stream(
|
16
|
-
stream, direction: direction, start: start, resolve_links: resolve_links
|
17
|
-
)
|
18
|
-
end
|
19
|
-
|
20
|
-
def delete_stream(stream); end
|
21
|
-
|
22
|
-
def join_streams(name, streams)
|
23
|
-
client.join_streams(name, streams)
|
24
|
-
end
|
25
|
-
|
26
|
-
def subscribe(stream, name:)
|
27
|
-
client.subscribe_to_stream(stream, name)
|
28
|
-
end
|
29
|
-
|
30
|
-
def consume_feed(stream, subscription)
|
31
|
-
response = client.consume_feed(stream, subscription)
|
32
|
-
return [] unless response.body
|
33
|
-
body = JSON.parse(response.body)
|
34
|
-
|
35
|
-
ack = body['links'].find { |link| link['relation'] == 'ackAll' }
|
36
|
-
return unless ack
|
37
|
-
ack_uri = ack['uri']
|
38
|
-
events = body['entries'].map do |entry|
|
39
|
-
deserialize_event(entry)
|
40
|
-
end
|
41
|
-
client.ack(ack_uri)
|
42
|
-
events
|
43
|
-
end
|
44
|
-
|
45
|
-
def link_to(stream, events, expected_version: nil)
|
46
|
-
client.link_to(stream, events, expected_version: expected_version)
|
47
|
-
|
48
|
-
true
|
49
|
-
end
|
50
|
-
|
51
|
-
private
|
52
|
-
|
53
|
-
attr_reader :mapper, :per_page, :client
|
54
|
-
|
55
|
-
def config
|
56
|
-
EventStoreClient::Configuration.instance
|
57
|
-
end
|
58
|
-
|
59
|
-
def initialize
|
60
|
-
@per_page = config.per_page
|
61
|
-
@mapper = config.mapper
|
62
|
-
@client = config.adapter
|
63
|
-
end
|
64
|
-
|
65
|
-
def read_from_stream(stream, direction:, start:, resolve_links:)
|
66
|
-
response =
|
67
|
-
client.read(
|
68
|
-
stream, start: start, direction: direction, resolve_links: resolve_links
|
69
|
-
)
|
70
|
-
return [] if response.body.nil? || response.body.empty?
|
71
|
-
JSON.parse(response.body)['entries'].map do |entry|
|
72
|
-
deserialize_event(entry)
|
73
|
-
end.reverse
|
74
|
-
end
|
75
|
-
|
76
|
-
def read_all_from_stream(stream, start:, resolve_links:)
|
77
|
-
count = per_page
|
78
|
-
events = []
|
79
|
-
failed_requests_count = 0
|
80
|
-
|
81
|
-
while failed_requests_count < 3
|
82
|
-
begin
|
83
|
-
response =
|
84
|
-
client.read(stream, start: start, direction: 'forward', resolve_links: resolve_links)
|
85
|
-
failed_requests_count += 1 && next unless response.success? || response.status == 404
|
86
|
-
rescue Faraday::ConnectionFailed
|
87
|
-
failed_requests_count += 1
|
88
|
-
next
|
89
|
-
end
|
90
|
-
failed_requests_count = 0
|
91
|
-
break if response.body.nil? || response.body.empty?
|
92
|
-
entries = JSON.parse(response.body)['entries']
|
93
|
-
break if entries.empty?
|
94
|
-
events += entries.map { |entry| deserialize_event(entry) }.reverse
|
95
|
-
start += count
|
96
|
-
end
|
97
|
-
events
|
98
|
-
end
|
99
|
-
|
100
|
-
def deserialize_event(entry)
|
101
|
-
event = EventStoreClient::Event.new(
|
102
|
-
id: entry['eventId'],
|
103
|
-
title: entry['title'],
|
104
|
-
type: entry['eventType'],
|
105
|
-
data: entry['data'] || '{}',
|
106
|
-
metadata: entry['isMetaData'] ? entry['metaData'] : '{}'
|
107
|
-
)
|
108
|
-
|
109
|
-
mapper.deserialize(event)
|
110
|
-
end
|
111
|
-
end
|
112
|
-
end
|