event_store_client 0.2.0 → 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 721e082b623b85e16696eb5844e8684757e31f10bf067b264fab176439a8b13f
4
- data.tar.gz: 00bed48b77fe8ea55edcb25840b4f111758efca348507a5395970b6cfecffe00
3
+ metadata.gz: daaf4a7e189d14224fa8b520345b9108f6c9c02316d57742d599b3fe5fb15e22
4
+ data.tar.gz: 9eb7350e33cd14b7e9aff5ed2d8cf313838b6fe1df739ba5c4348111f18ec323
5
5
  SHA512:
6
- metadata.gz: b882a2aa01f9d40debf44418c2e232307c414ec77688822615e7aaa911586523700286d1581c68b3916246ccff8cd098a8211646910d5d995e9bc71306fd852f
7
- data.tar.gz: 6f3f2d4dc03dcfdfc7355bd9a4bbf1bb519b6dfc14b33feff7cc285facaf4f28977ed3ff119a3b55e51dfeb1201aaca29b2341b64fa52570e8528a9ba49e5e70
6
+ metadata.gz: 803a1ac900741c28a9437135e48343d015eec4d55c3b1df5d536575bed13341f276aa85d24cb177cdf376284b1be7a0220b8b1bdde4bab558481b39f6ae930a4
7
+ data.tar.gz: 0fa249206dcbe74719fae1ba82e85de615d332cd82dc69d890154839e2fcccc7e6feb4269afc94fb9d46156816582a71a71afe364767c005e6ac101545c4b6e8
data/README.md CHANGED
@@ -1,3 +1,6 @@
1
+ ![Run tests](https://github.com/yousty/event_store_client/workflows/Run%20tests/badge.svg?branch=master&event=push)
2
+ [![Gem Version](https://badge.fury.io/rb/event_store_client.svg)](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).
@@ -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/endpoint'
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
- new_events = connection.consume_feed(subscription.stream, subscription.name)
8
- next if new_events.none?
9
- new_events.each { |event| subscription.subscriber.call(event) }
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.publish(stream: stream, events: events, expected_version: expected_version)
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
- connection.read(stream, direction: direction, start: start, all: all)
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::Configuration.instance
92
+ EventStoreClient.config
85
93
  end
86
94
 
87
95
  def initialize
88
96
  @threads = []
89
- @connection ||= Connection.new
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-struct'
4
- require 'singleton'
3
+ require 'dry-configurable'
5
4
 
6
5
  module EventStoreClient
7
- class Configuration
8
- include Singleton
6
+ extend Dry::Configurable
9
7
 
10
- attr_accessor :per_page, :service_name, :mapper, :error_handler, :pid_path, :adapter
8
+ # Supported adapters: %i[api in_memory]
9
+ #
10
+ setting :adapter, :api
11
11
 
12
- def configure
13
- yield(self) if block_given?
14
- end
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
- private
25
+ setting :service_name, 'default'
17
26
 
18
- def initialize
19
- @per_page = 20
20
- @pid_path = 'tmp/poll.pid'
21
- @mapper = Mapper::Default.new
22
- @service_name = 'default'
23
- @error_handler = nil
24
- @adapter = EventStoreClient::StoreAdapter::Api::Client.new(
25
- host: 'http://localhost', port: 2113, per_page: per_page
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[:es_encrypted], cipher: key.cipher, iv: key.iv
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) }
@@ -11,7 +11,7 @@ module EventStoreClient
11
11
  encrypt_attributes(
12
12
  key: key,
13
13
  data: encrypted_data,
14
- attributes: encryption_metadata[:attributes]
14
+ attributes: encryption_metadata[:attributes].map(&:to_s)
15
15
  )
16
16
  end
17
17
 
@@ -17,7 +17,7 @@ module EventStoreClient
17
17
  attr_reader :data, :schema
18
18
 
19
19
  def initialize(data:, schema:)
20
- @data = data
20
+ @data = data.transform_keys(&:to_sym)
21
21
  @schema = schema
22
22
  end
23
23
  end
@@ -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::Strict::String.default('{}')
13
- attribute :metadata, Types::Strict::String.default('{}')
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
- type: event.class.to_s,
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
@@ -3,10 +3,14 @@
3
3
  module Serializer
4
4
  module Json
5
5
  def self.deserialize(data)
6
+ return data if data.is_a?(Hash)
7
+
6
8
  JSON.parse(data)
7
9
  end
8
10
 
9
11
  def self.serialize(data)
12
+ return data if data.is_a?(String)
13
+
10
14
  JSON.generate(data)
11
15
  end
12
16
  end
@@ -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(events)
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
- response
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 :endpoint, :per_page
161
+ attr_reader :uri, :per_page, :connection_options, :mapper
119
162
 
120
- def initialize(host:, port:, per_page: 20)
121
- @endpoint = Endpoint.new(host: host, port: port)
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(endpoint).call
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
- url: endpoint.url,
12
- headers: DEFAULT_HEADERS
11
+ {
12
+ url: uri.to_s,
13
+ headers: DEFAULT_HEADERS
14
+ }.merge(options)
13
15
  ) do |conn|
14
- conn.basic_auth(ENV['EVENT_STORE_USER'], ENV['EVENT_STORE_PASSWORD'])
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 initialize(endpoint)
22
- @endpoint = endpoint
23
+ def config
24
+ EventStoreClient.config
23
25
  end
24
26
 
25
- attr_reader :endpoint
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 :endpoint, :per_page
87
+ attr_reader :per_page, :mapper
68
88
 
69
- def initialize(host:, port:, per_page: 20)
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
- "http://#{endpoint.url}/streams/#{stream_name}/#{batch_size}/#{direction}/#{count}",
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.subscribe(subscription.stream, name: subscription.name)
30
+ connection.subscribe_to_stream(subscription.stream, subscription.name)
30
31
  end
31
32
 
32
33
  attr_reader :connection, :subscriptions, :service
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module EventStoreClient
4
- VERSION = '0.2.0'
4
+ VERSION = '0.2.5'
5
5
  end
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.0
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-04-27 00:00:00.000000000 Z
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.4.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.4.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.1.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.1.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: 0.17.0
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: 0.17.0
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.0.6
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
@@ -1,14 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'dry-struct'
4
-
5
- module EventStoreClient
6
- class Endpoint < Dry::Struct
7
- attribute :host, Types::String
8
- attribute :port, Types::Coercible::Integer
9
-
10
- def url
11
- "#{host}:#{port}"
12
- end
13
- end
14
- end