event_store_client 1.3.0 → 1.4.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/event_store_client/adapters/grpc/client.rb +1 -1
- data/lib/event_store_client/adapters/grpc/commands/streams/append.rb +86 -37
- data/lib/event_store_client/configuration.rb +17 -15
- data/lib/event_store_client/deserialized_event.rb +38 -19
- data/lib/event_store_client/mapper/default.rb +1 -1
- data/lib/event_store_client/mapper/encrypted.rb +1 -1
- data/lib/event_store_client/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dc7d6f48fb89cf1d9ac826310efcbd4eaf5ba60b61b0d9d100d95615e576ad0a
|
4
|
+
data.tar.gz: e9214e8026af433ddcd3804f8d6920a3298d7497cceca0dcefae73d41bce8e3e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 786b74bc83aa6a20682818097f219f139e582428b74aa89378ec587ce9a6bd163c7e9d599392ffdbaee5763768d72d0d0dcf6215cccbdf3c661cc5545a382b31
|
7
|
+
data.tar.gz: dd0add2a3050b272c163b67a5a93b25c33cf0f1a1e5008a18bb371faa84a74e44ed6133ccf6ea5f1fb90b86f5bd84f2bfd0dcc2b256f40424f88574762c7f2b2
|
@@ -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
|
5
|
-
require 'event_store_client/adapters/grpc/generated/streams_services_pb
|
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
|
-
|
19
|
-
|
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
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
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
|
-
|
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
|
-
|
8
|
-
|
9
|
-
|
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
|
-
|
21
|
+
validate(args[:data]) unless args[:skip_validation]
|
22
|
+
|
20
23
|
@data = args.fetch(:data) { {} }
|
21
|
-
@metadata =
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
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
|
-
|
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
|
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
|
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-
|
11
|
+
date: 2021-12-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dry-configurable
|