event_store_client 1.3.0 → 1.4.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 700f420a0fa9e3fb0352784f3bc0431cac18216130ba397897dfb77c98a4f7c6
4
- data.tar.gz: e408f3a666dd7f1e95634591923bf8df51ce30c6b521cd9042072f551e5ff645
3
+ metadata.gz: dc7d6f48fb89cf1d9ac826310efcbd4eaf5ba60b61b0d9d100d95615e576ad0a
4
+ data.tar.gz: e9214e8026af433ddcd3804f8d6920a3298d7497cceca0dcefae73d41bce8e3e
5
5
  SHA512:
6
- metadata.gz: 2232248c19c04924effd9bab97271f5a0bf3e7b4cf4e56e5453fc32a27c56d587777239b48d0aafc026c265b1086691aa5e8c04e7863209d9bb1e07c046946e6
7
- data.tar.gz: 2db191ee47dae6f22b5858ab85bde4d3129af6220f534d9b11e502150058c7211285afa2562aae70ae08877e21c8d2205c8d1400ec8365e10567e7c5295b7afc
6
+ metadata.gz: 786b74bc83aa6a20682818097f219f139e582428b74aa89378ec587ce9a6bd163c7e9d599392ffdbaee5763768d72d0d0dcf6215cccbdf3c661cc5545a382b31
7
+ data.tar.gz: dd0add2a3050b272c163b67a5a93b25c33cf0f1a1e5008a18bb371faa84a74e44ed6133ccf6ea5f1fb90b86f5bd84f2bfd0dcc2b256f40424f88574762c7f2b2
@@ -11,7 +11,7 @@ module EventStoreClient
11
11
  #
12
12
  def append_to_stream(stream_name, events, options: {})
13
13
  Commands::Streams::Append.new.call(
14
- stream_name, events, options: {}
14
+ stream_name, events, options: options
15
15
  )
16
16
  end
17
17
 
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'grpc'
4
- require 'event_store_client/adapters/grpc/generated/streams_pb.rb'
5
- require 'event_store_client/adapters/grpc/generated/streams_services_pb.rb'
4
+ require 'event_store_client/adapters/grpc/generated/streams_pb'
5
+ require 'event_store_client/adapters/grpc/generated/streams_services_pb'
6
6
 
7
7
  require 'event_store_client/adapters/grpc/commands/command'
8
8
 
@@ -14,45 +14,94 @@ module EventStoreClient
14
14
  use_request EventStore::Client::Streams::AppendReq
15
15
  use_service EventStore::Client::Streams::Streams::Stub
16
16
 
17
+ ALLOWED_EVENT_METADATA = %w[type content-type created_at].freeze
18
+
17
19
  # @api private
18
- # TODO: Add support to verify the expected version
19
- def call(stream, events, options: {}) # rubocop:disable Lint/UnusedMethodArgument,Metrics/LineLength
20
+ def call(stream, events, options: {})
21
+ return unless events.any?
22
+
20
23
  serialized_events = events.map { |event| config.mapper.serialize(event) }
21
24
 
22
- serialized_events.each do |event|
23
- event_metadata = JSON.parse(event.metadata)
24
- custom_metadata = {
25
- "type": event.type,
26
- "created_at": Time.now,
27
- 'content-type': event_metadata['content-type']
28
- }
29
- custom_metadata['encryption'] = event_metadata['encryption'] unless event_metadata['encryption'].nil?
30
- custom_metadata['transaction'] = event_metadata['transaction'] unless event_metadata['transaction'].nil?
31
- event_metadata = event_metadata.select { |k| ['type', 'content-type', 'created_at'].include?(k) }
32
-
33
- payload = [
34
- request.new(
35
- options: {
36
- stream_identifier: {
37
- streamName: stream
38
- },
39
- any: {}
40
- }
41
- ),
42
- request.new(
43
- proposed_message: {
44
- id: {
45
- string: SecureRandom.uuid
46
- },
47
- data: event.data.b,
48
- custom_metadata: JSON.generate(custom_metadata),
49
- metadata: event_metadata
50
- }
51
- )
52
- ]
53
- service.append(payload, metadata: metadata)
25
+ expected_version = options[:expected_version]
26
+
27
+ res = nil
28
+ serialized_events.each_with_index do |event, i|
29
+ expected_version += i if expected_version
30
+ res = append(stream, event, expected_version)
31
+ break if res.failure?
54
32
  end
55
- Success(events)
33
+
34
+ res.success? ? Success(events) : Failure(res.failure)
35
+ end
36
+
37
+ private
38
+
39
+ def append(stream, event, expected_version)
40
+ event_metadata = JSON.parse(event.metadata)
41
+
42
+ payload = append_request_payload(
43
+ options(stream, expected_version),
44
+ message(
45
+ data: event.data.b,
46
+ event_metadata: event_metadata.select { |k| ALLOWED_EVENT_METADATA.include?(k) },
47
+ custom_metadata: custom_metadata(event.type, event_metadata)
48
+ )
49
+ )
50
+
51
+ resp = service.append(payload, metadata: metadata)
52
+
53
+ validate_response(resp)
54
+ end
55
+
56
+ def custom_metadata(event_type, event_metadata)
57
+ {
58
+ type: event_type,
59
+ created_at: Time.current,
60
+ encryption: event_metadata['encryption'],
61
+ 'content-type': event_metadata['content-type'],
62
+ transaction: event_metadata['transaction']
63
+ }.compact
64
+ end
65
+
66
+ def append_request_payload(options, message)
67
+ [
68
+ request.new(
69
+ options: options
70
+ ),
71
+ request.new(
72
+ proposed_message: message
73
+ )
74
+ ]
75
+ end
76
+
77
+ def options(stream, expected_version)
78
+ {
79
+ stream_identifier: {
80
+ streamName: stream
81
+ },
82
+ revision: expected_version,
83
+ any: (expected_version ? nil : {})
84
+ }.compact
85
+ end
86
+
87
+ def message(data:, event_metadata:, custom_metadata:)
88
+ {
89
+ id: {
90
+ string: SecureRandom.uuid
91
+ },
92
+ data: data,
93
+ custom_metadata: JSON.generate(custom_metadata),
94
+ metadata: event_metadata
95
+ }
96
+ end
97
+
98
+ def validate_response(resp)
99
+ return Success() if resp.success
100
+
101
+ Failure(
102
+ "current version: #{resp.wrong_expected_version.current_revision} | "\
103
+ "expected: #{resp.wrong_expected_version.expected_revision}"
104
+ )
56
105
  end
57
106
  end
58
107
  end
@@ -8,35 +8,37 @@ module EventStoreClient
8
8
 
9
9
  # Supported adapters: %i[api in_memory grpc]
10
10
  #
11
- setting :adapter, :grpc
12
- setting :verify_ssl, true
11
+ setting :adapter, default: :grpc
12
+ setting :verify_ssl, default: true
13
13
 
14
- setting :error_handler, ErrorHandler.new
15
- setting :eventstore_url, 'http://localhost:2113' do |value|
14
+ setting :error_handler, default: ErrorHandler.new
15
+ setting :eventstore_url, default: 'http://localhost:2113' do |value|
16
16
  value.is_a?(URI) ? value : URI(value)
17
17
  end
18
18
 
19
- setting :eventstore_user, 'admin'
20
- setting :eventstore_password, 'changeit'
19
+ setting :eventstore_user, default: 'admin'
20
+ setting :eventstore_password, default: 'changeit'
21
21
 
22
- setting :db_port, 2113
22
+ setting :db_port, default: 2113
23
23
 
24
- setting :per_page, 20
25
- setting :pid_path, 'tmp/poll.pid'
24
+ setting :per_page, default: 20
25
+ setting :pid_path, default: 'tmp/poll.pid'
26
26
 
27
- setting :service_name, 'default'
27
+ setting :service_name, default: 'default'
28
28
 
29
- setting :mapper, Mapper::Default.new
29
+ setting :mapper, default: Mapper::Default.new
30
+
31
+ setting :default_event_class, default: EventStoreClient::DeserializedEvent
30
32
 
31
33
  setting :subscriptions_repo
32
34
 
33
35
  setting :logger
34
36
 
35
- setting :socket_error_retry_sleep, 0.5
36
- setting :socket_error_retry_count, 3
37
+ setting :socket_error_retry_sleep, default: 0.5
38
+ setting :socket_error_retry_count, default: 3
37
39
 
38
- setting :grpc_unavailable_retry_sleep, 0.5
39
- setting :grpc_unavailable_retry_count, 3
40
+ setting :grpc_unavailable_retry_sleep, default: 0.5
41
+ setting :grpc_unavailable_retry_count, default: 3
40
42
 
41
43
  def self.configure
42
44
  yield(config) if block_given?
@@ -4,36 +4,55 @@ require 'dry/schema'
4
4
 
5
5
  module EventStoreClient
6
6
  class DeserializedEvent
7
- attr_reader :id
8
- attr_reader :type
9
- attr_reader :title
10
- attr_reader :data
11
- attr_reader :metadata
12
-
13
- def schema
14
- Dry::Schema.Params do
15
- end
16
- end
7
+ InvalidDataError = Class.new(StandardError)
8
+ private_constant :InvalidDataError
9
+
10
+ attr_reader :id, :type, :title, :data, :metadata
17
11
 
12
+ # @args [Hash] opts
13
+ # @option opts [Boolean] :skip_validation
14
+ # @option opts [Hash] :data
15
+ # @option opts [Hash] :metadata
16
+ # @option opts [String] :type
17
+ # @option opts [String] :title
18
+ # @option opts [UUID] :id
19
+ #
18
20
  def initialize(args = {})
19
- validation = schema.call(args[:data] || {}) unless args[:skip_validation]
21
+ validate(args[:data]) unless args[:skip_validation]
22
+
20
23
  @data = args.fetch(:data) { {} }
21
- @metadata = args.fetch(:metadata) { {} }.merge(
22
- 'type' => self.class.name,
23
- 'content-type' => content_type
24
- )
25
- if !args[:skip_validation] && validation.errors.any?
26
- @metadata.merge!('validation-errors' => validation.errors.to_h)
27
- end
24
+ @metadata =
25
+ args.fetch(:metadata) { {} }
26
+ .merge(
27
+ 'type' => self.class.name,
28
+ 'content-type' => payload_content_type
29
+ )
30
+
28
31
  @type = args[:type] || self.class.name
29
32
  @title = args[:title]
30
33
  @id = args[:id]
31
34
  end
32
35
 
33
- def content_type
36
+ # event schema
37
+ def schema; end
38
+
39
+ # content type of the event data
40
+ def payload_content_type
34
41
  return 'application/json' if EventStoreClient.config.adapter == :grpc
35
42
 
36
43
  'application/vnd.eventstore.events+json'
37
44
  end
45
+
46
+ private
47
+
48
+ def validate(data)
49
+ return unless schema
50
+
51
+ validation = schema.call(data || {})
52
+
53
+ return unless validation.errors.any?
54
+
55
+ raise(InvalidDataError.new(message: "#{schema.class.name} #{validation.errors.to_h}"))
56
+ end
38
57
  end
39
58
  end
@@ -20,7 +20,7 @@ module EventStoreClient
20
20
  begin
21
21
  Object.const_get(event.type)
22
22
  rescue NameError
23
- EventStoreClient::DeserializedEvent
23
+ EventStoreClient.config.default_event_class
24
24
  end
25
25
  event_class.new(
26
26
  skip_validation: true,
@@ -68,7 +68,7 @@ module EventStoreClient
68
68
  begin
69
69
  Object.const_get(event.type)
70
70
  rescue NameError
71
- EventStoreClient::DeserializedEvent
71
+ EventStoreClient.config.default_event_class
72
72
  end
73
73
 
74
74
  event_class.new(
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module EventStoreClient
4
- VERSION = '1.3.0'
4
+ VERSION = '1.4.3'
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: 1.3.0
4
+ version: 1.4.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sebastian Wilgosz
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-08-09 00:00:00.000000000 Z
11
+ date: 2021-12-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dry-configurable