event_store_client 1.4.9 → 2.0.0
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 +30 -145
- data/docs/appending_events.md +155 -0
- data/docs/catch_up_subscriptions.md +253 -0
- data/docs/configuration.md +83 -0
- data/docs/deleting_streams.md +25 -0
- data/docs/encrypting_events.md +84 -0
- data/docs/linking_events.md +149 -0
- data/docs/reading_events.md +200 -0
- data/lib/event_store_client/adapters/grpc/client.rb +244 -105
- data/lib/event_store_client/adapters/grpc/cluster/gossip_discover.rb +131 -0
- data/lib/event_store_client/adapters/grpc/cluster/insecure_connection.rb +21 -0
- data/lib/event_store_client/adapters/grpc/cluster/member.rb +18 -0
- data/lib/event_store_client/adapters/grpc/cluster/queryless_discover.rb +25 -0
- data/lib/event_store_client/adapters/grpc/cluster/secure_connection.rb +71 -0
- data/lib/event_store_client/adapters/grpc/command_registrar.rb +7 -7
- data/lib/event_store_client/adapters/grpc/commands/command.rb +63 -25
- data/lib/event_store_client/adapters/grpc/commands/gossip/cluster_info.rb +24 -0
- data/lib/event_store_client/adapters/grpc/commands/streams/append.rb +43 -68
- data/lib/event_store_client/adapters/grpc/commands/streams/append_multiple.rb +44 -0
- data/lib/event_store_client/adapters/grpc/commands/streams/delete.rb +21 -17
- data/lib/event_store_client/adapters/grpc/commands/streams/hard_delete.rb +39 -0
- data/lib/event_store_client/adapters/grpc/commands/streams/link_to.rb +7 -52
- data/lib/event_store_client/adapters/grpc/commands/streams/link_to_multiple.rb +44 -0
- data/lib/event_store_client/adapters/grpc/commands/streams/read.rb +20 -85
- data/lib/event_store_client/adapters/grpc/commands/streams/read_paginated.rb +174 -0
- data/lib/event_store_client/adapters/grpc/commands/streams/subscribe.rb +31 -106
- data/lib/event_store_client/adapters/grpc/connection.rb +56 -36
- data/lib/event_store_client/adapters/grpc/discover.rb +75 -0
- data/lib/event_store_client/adapters/grpc/generated/cluster_pb.rb +106 -18
- data/lib/event_store_client/adapters/grpc/generated/cluster_services_pb.rb +12 -12
- data/lib/event_store_client/adapters/grpc/generated/code_pb.rb +34 -0
- data/lib/event_store_client/adapters/grpc/generated/gossip_pb.rb +3 -2
- data/lib/event_store_client/adapters/grpc/generated/gossip_services_pb.rb +3 -3
- data/lib/event_store_client/adapters/grpc/generated/monitoring_pb.rb +25 -0
- data/lib/event_store_client/adapters/grpc/generated/monitoring_services_pb.rb +26 -0
- data/lib/event_store_client/adapters/grpc/generated/operations_pb.rb +2 -1
- data/lib/event_store_client/adapters/grpc/generated/operations_services_pb.rb +8 -7
- data/lib/event_store_client/adapters/grpc/generated/persistent_pb.rb +199 -38
- data/lib/event_store_client/adapters/grpc/generated/persistent_services_pb.rb +7 -3
- data/lib/event_store_client/adapters/grpc/generated/projections_pb.rb +9 -26
- data/lib/event_store_client/adapters/grpc/generated/projections_services_pb.rb +4 -3
- data/lib/event_store_client/adapters/grpc/generated/serverfeatures_pb.rb +29 -0
- data/lib/event_store_client/adapters/grpc/generated/serverfeatures_services_pb.rb +26 -0
- data/lib/event_store_client/adapters/grpc/generated/shared_pb.rb +54 -12
- data/lib/event_store_client/adapters/grpc/generated/status_pb.rb +23 -0
- data/lib/event_store_client/adapters/grpc/generated/streams_pb.rb +104 -64
- data/lib/event_store_client/adapters/grpc/generated/streams_services_pb.rb +3 -2
- data/lib/event_store_client/adapters/grpc/generated/users_services_pb.rb +2 -2
- data/lib/event_store_client/adapters/grpc/options/streams/read_options.rb +78 -0
- data/lib/event_store_client/adapters/grpc/options/streams/write_options.rb +39 -0
- data/lib/event_store_client/adapters/grpc/shared/event_deserializer.rb +52 -0
- data/lib/event_store_client/adapters/grpc/shared/options/filter_options.rb +76 -0
- data/lib/event_store_client/adapters/grpc/shared/options/stream_options.rb +91 -0
- data/lib/event_store_client/adapters/grpc/shared/streams/process_response.rb +28 -0
- data/lib/event_store_client/adapters/grpc/shared/streams/process_responses.rb +33 -0
- data/lib/event_store_client/adapters/grpc.rb +28 -12
- data/lib/event_store_client/configuration.rb +39 -54
- data/lib/event_store_client/connection/url.rb +57 -0
- data/lib/event_store_client/connection/url_parser.rb +144 -0
- data/lib/event_store_client/data_decryptor.rb +2 -9
- data/lib/event_store_client/deserialized_event.rb +35 -10
- data/lib/event_store_client/encryption_metadata.rb +0 -1
- data/lib/event_store_client/event.rb +4 -2
- data/lib/event_store_client/extensions/options_extension.rb +87 -0
- data/lib/event_store_client/mapper/default.rb +12 -9
- data/lib/event_store_client/mapper/encrypted.rb +18 -17
- data/lib/event_store_client/types.rb +1 -1
- data/lib/event_store_client/utils.rb +30 -0
- data/lib/event_store_client/version.rb +1 -1
- data/lib/event_store_client.rb +8 -7
- metadata +74 -83
- data/lib/event_store_client/adapters/grpc/Protos/cluster.proto +0 -149
- data/lib/event_store_client/adapters/grpc/Protos/gossip.proto +0 -44
- data/lib/event_store_client/adapters/grpc/Protos/operations.proto +0 -45
- data/lib/event_store_client/adapters/grpc/Protos/persistent.proto +0 -180
- data/lib/event_store_client/adapters/grpc/Protos/projections.proto +0 -174
- data/lib/event_store_client/adapters/grpc/Protos/shared.proto +0 -22
- data/lib/event_store_client/adapters/grpc/Protos/streams.proto +0 -242
- data/lib/event_store_client/adapters/grpc/Protos/users.proto +0 -119
- data/lib/event_store_client/adapters/grpc/README.md +0 -16
- data/lib/event_store_client/adapters/grpc/commands/persistent_subscriptions/create.rb +0 -46
- data/lib/event_store_client/adapters/grpc/commands/persistent_subscriptions/delete.rb +0 -34
- data/lib/event_store_client/adapters/grpc/commands/persistent_subscriptions/read.rb +0 -77
- data/lib/event_store_client/adapters/grpc/commands/persistent_subscriptions/settings_schema.rb +0 -38
- data/lib/event_store_client/adapters/grpc/commands/persistent_subscriptions/update.rb +0 -48
- data/lib/event_store_client/adapters/grpc/commands/projections/create.rb +0 -48
- data/lib/event_store_client/adapters/grpc/commands/projections/delete.rb +0 -34
- data/lib/event_store_client/adapters/grpc/commands/projections/update.rb +0 -44
- data/lib/event_store_client/adapters/grpc/commands/streams/read_all.rb +0 -43
- data/lib/event_store_client/adapters/grpc/commands/streams/tombstone.rb +0 -35
- data/lib/event_store_client/adapters/http/README.md +0 -16
- data/lib/event_store_client/adapters/http/client.rb +0 -161
- data/lib/event_store_client/adapters/http/commands/command.rb +0 -27
- data/lib/event_store_client/adapters/http/commands/persistent_subscriptions/ack.rb +0 -15
- data/lib/event_store_client/adapters/http/commands/persistent_subscriptions/create.rb +0 -35
- data/lib/event_store_client/adapters/http/commands/persistent_subscriptions/read.rb +0 -60
- data/lib/event_store_client/adapters/http/commands/projections/create.rb +0 -33
- data/lib/event_store_client/adapters/http/commands/projections/update.rb +0 -31
- data/lib/event_store_client/adapters/http/commands/streams/append.rb +0 -49
- data/lib/event_store_client/adapters/http/commands/streams/delete.rb +0 -16
- data/lib/event_store_client/adapters/http/commands/streams/link_to.rb +0 -49
- data/lib/event_store_client/adapters/http/commands/streams/read.rb +0 -52
- data/lib/event_store_client/adapters/http/commands/streams/tombstone.rb +0 -17
- data/lib/event_store_client/adapters/http/connection.rb +0 -46
- data/lib/event_store_client/adapters/http/request_method.rb +0 -28
- data/lib/event_store_client/adapters/http.rb +0 -17
- data/lib/event_store_client/adapters/in_memory.rb +0 -144
- data/lib/event_store_client/broker.rb +0 -40
- data/lib/event_store_client/catch_up_subscription.rb +0 -42
- data/lib/event_store_client/catch_up_subscriptions.rb +0 -92
- data/lib/event_store_client/client.rb +0 -73
- data/lib/event_store_client/error_handler.rb +0 -10
- data/lib/event_store_client/subscription.rb +0 -23
- data/lib/event_store_client/subscriptions.rb +0 -38
- data/lib/event_store_client/value_objects/read_direction.rb +0 -43
@@ -1,8 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'grpc'
|
4
|
-
require 'event_store_client/adapters/grpc/connection'
|
5
|
-
|
6
3
|
module EventStoreClient
|
7
4
|
module GRPC
|
8
5
|
class CommandRegistrar
|
@@ -19,13 +16,16 @@ module EventStoreClient
|
|
19
16
|
end
|
20
17
|
|
21
18
|
def self.request(command_klass)
|
22
|
-
@commands
|
19
|
+
@commands.dig(command_klass, :request)
|
23
20
|
end
|
24
21
|
|
22
|
+
# @param command_klass [Class]
|
23
|
+
# Examples:
|
24
|
+
# - EventStoreClient::GRPC::Commands::Streams::Append
|
25
|
+
# - EventStoreClient::GRPC::Commands::Streams::Read
|
26
|
+
# @return [Object] GRPC service class
|
25
27
|
def self.service(command_klass)
|
26
|
-
|
27
|
-
@commands[command_klass][:service]
|
28
|
-
)
|
28
|
+
@commands.dig(command_klass, :service)
|
29
29
|
end
|
30
30
|
end
|
31
31
|
end
|
@@ -1,43 +1,81 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'dry-monads'
|
4
|
-
require 'event_store_client/adapters/grpc/command_registrar'
|
5
|
-
|
6
3
|
module EventStoreClient
|
7
4
|
module GRPC
|
8
5
|
module Commands
|
9
6
|
class Command
|
10
|
-
|
11
|
-
|
12
|
-
|
7
|
+
class << self
|
8
|
+
def use_request(request_klass)
|
9
|
+
CommandRegistrar.register_request(self, request: request_klass)
|
10
|
+
end
|
13
11
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
12
|
+
def use_service(service_klass)
|
13
|
+
CommandRegistrar.register_service(self, service: service_klass)
|
14
|
+
end
|
15
|
+
end
|
18
16
|
|
19
|
-
|
20
|
-
|
21
|
-
end
|
17
|
+
include Configuration
|
18
|
+
include Dry::Monads[:try, :result]
|
22
19
|
|
23
|
-
|
24
|
-
|
25
|
-
end
|
20
|
+
attr_reader :connection
|
21
|
+
private :connection
|
26
22
|
|
27
|
-
|
28
|
-
|
29
|
-
|
23
|
+
# @param conn_options [Hash]
|
24
|
+
# @option conn_options [String] :host
|
25
|
+
# @option conn_options [Integer] :port
|
26
|
+
# @option conn_options [String] :username
|
27
|
+
# @option conn_options [String] :password
|
28
|
+
def initialize(**conn_options)
|
29
|
+
@connection = EventStoreClient::GRPC::Connection.new(**conn_options)
|
30
|
+
end
|
30
31
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
end
|
32
|
+
# Override it in your implementation of command.
|
33
|
+
def call
|
34
|
+
raise NotImplementedError
|
35
35
|
end
|
36
36
|
|
37
|
+
# @return [Hash]
|
37
38
|
def metadata
|
39
|
+
return {} unless connection.class.secure?
|
40
|
+
|
38
41
|
credentials =
|
39
|
-
Base64.encode64("#{
|
40
|
-
{ 'authorization' => "Basic #{credentials
|
42
|
+
Base64.encode64("#{connection.username}:#{connection.password}").delete("\n")
|
43
|
+
{ 'authorization' => "Basic #{credentials}" }
|
44
|
+
end
|
45
|
+
|
46
|
+
# @return GRPC params class to be used in the request.
|
47
|
+
# E.g.EventStore::Client::Streams::ReadReq
|
48
|
+
def request
|
49
|
+
CommandRegistrar.request(self.class)
|
50
|
+
end
|
51
|
+
|
52
|
+
# @return GRPC request stub class. E.g. EventStore::Client::Streams::Streams::Stub
|
53
|
+
def service
|
54
|
+
connection.call(CommandRegistrar.service(self.class))
|
55
|
+
end
|
56
|
+
|
57
|
+
# @return [Hash] connection options' hash
|
58
|
+
def connection_options
|
59
|
+
@connection.options_hash
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def retry_request(skip_retry: false)
|
65
|
+
return yield if skip_retry
|
66
|
+
|
67
|
+
retries = 0
|
68
|
+
begin
|
69
|
+
yield
|
70
|
+
rescue ::GRPC::Unavailable => e
|
71
|
+
sleep config.eventstore_url.grpc_retry_interval / 1000.0
|
72
|
+
retries += 1
|
73
|
+
if retries <= config.eventstore_url.grpc_retry_attempts
|
74
|
+
config.logger&.debug("Request failed. Reason: #{e.class}. Retying.")
|
75
|
+
retry
|
76
|
+
end
|
77
|
+
raise
|
78
|
+
end
|
41
79
|
end
|
42
80
|
end
|
43
81
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'event_store_client/adapters/grpc/generated/shared_pb'
|
4
|
+
require 'event_store_client/adapters/grpc/generated/gossip_pb'
|
5
|
+
require 'event_store_client/adapters/grpc/generated/gossip_services_pb'
|
6
|
+
|
7
|
+
module EventStoreClient
|
8
|
+
module GRPC
|
9
|
+
module Commands
|
10
|
+
module Gossip
|
11
|
+
class ClusterInfo < Command
|
12
|
+
use_request EventStore::Client::Empty
|
13
|
+
use_service EventStore::Client::Gossip::Gossip::Stub
|
14
|
+
|
15
|
+
# @api private
|
16
|
+
# @see {EventStoreClient::GRPC::Client#cluster_info}
|
17
|
+
def call
|
18
|
+
Success(retry_request { service.read(request.new, metadata: metadata) })
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -1,11 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'grpc'
|
4
3
|
require 'event_store_client/adapters/grpc/generated/streams_pb'
|
5
4
|
require 'event_store_client/adapters/grpc/generated/streams_services_pb'
|
6
5
|
|
7
|
-
require 'event_store_client/adapters/grpc/commands/command'
|
8
|
-
|
9
6
|
module EventStoreClient
|
10
7
|
module GRPC
|
11
8
|
module Commands
|
@@ -17,91 +14,69 @@ module EventStoreClient
|
|
17
14
|
ALLOWED_EVENT_METADATA = %w[type content-type created_at].freeze
|
18
15
|
|
19
16
|
# @api private
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
res = append(stream, event, expected_version)
|
31
|
-
break if res.failure?
|
17
|
+
# @see {EventStoreClient::GRPC::Client#append_to_stream}
|
18
|
+
def call(stream_name, event, options:, &blk)
|
19
|
+
payload =
|
20
|
+
[
|
21
|
+
request.new(options: options(stream_name, options)),
|
22
|
+
request.new(proposed_message: proposed_message(event))
|
23
|
+
]
|
24
|
+
yield(*payload) if blk
|
25
|
+
response = retry_request(skip_retry: config.eventstore_url.throw_on_append_failure) do
|
26
|
+
service.append(payload, metadata: metadata)
|
32
27
|
end
|
33
|
-
|
34
|
-
|
28
|
+
validate_response(response)
|
29
|
+
rescue ::GRPC::Unavailable => e
|
30
|
+
Failure(e)
|
35
31
|
end
|
36
32
|
|
37
33
|
private
|
38
34
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
35
|
+
# @param event [EventStoreClient::DeserializedEvent]
|
36
|
+
# @return [EventStore::Client::Streams::AppendReq::ProposedMessage]
|
37
|
+
def proposed_message(event)
|
38
|
+
serialized_event = config.mapper.serialize(event)
|
39
|
+
event_metadata = JSON.parse(serialized_event.metadata)
|
40
|
+
custom_metadata = custom_metadata(serialized_event.type, event_metadata)
|
41
|
+
opts =
|
42
|
+
{
|
43
|
+
id: {
|
44
|
+
string: serialized_event.id
|
45
|
+
},
|
46
|
+
data: serialized_event.data.b,
|
47
|
+
custom_metadata: custom_metadata.to_json,
|
48
|
+
metadata: event_metadata.slice(*ALLOWED_EVENT_METADATA)
|
49
|
+
}
|
50
|
+
EventStore::Client::Streams::AppendReq::ProposedMessage.new(opts)
|
54
51
|
end
|
55
52
|
|
53
|
+
# @param event_type [String]
|
54
|
+
# @param event_metadata [Hash]
|
55
|
+
# @return [Hash]
|
56
56
|
def custom_metadata(event_type, event_metadata)
|
57
57
|
{
|
58
58
|
type: event_type,
|
59
|
-
created_at: Time.
|
59
|
+
created_at: Time.now.utc,
|
60
60
|
encryption: event_metadata['encryption'],
|
61
61
|
'content-type': event_metadata['content-type'],
|
62
62
|
transaction: event_metadata['transaction']
|
63
63
|
}.compact
|
64
64
|
end
|
65
65
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
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
|
-
}
|
66
|
+
# @param stream_name [String]
|
67
|
+
# @param options [Hash]
|
68
|
+
# @return [EventStore::Client::Streams::AppendReq::Options]
|
69
|
+
def options(stream_name, options)
|
70
|
+
opts = Options::Streams::WriteOptions.new(stream_name, options).request_options
|
71
|
+
EventStore::Client::Streams::AppendReq::Options.new(opts)
|
96
72
|
end
|
97
73
|
|
74
|
+
# @param resp [EventStore::Client::Streams::AppendResp]
|
75
|
+
# @return [Dry::Monads::Success, Dry::Monads::Failure]
|
98
76
|
def validate_response(resp)
|
99
|
-
return Success() if resp.success
|
77
|
+
return Success(resp) if resp.success
|
100
78
|
|
101
|
-
Failure(
|
102
|
-
"current version: #{resp.wrong_expected_version.current_revision} | "\
|
103
|
-
"expected: #{resp.wrong_expected_version.expected_revision}"
|
104
|
-
)
|
79
|
+
Failure(resp.wrong_expected_version)
|
105
80
|
end
|
106
81
|
end
|
107
82
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# rubocop:disable Naming/PredicateName
|
4
|
+
|
5
|
+
module EventStoreClient
|
6
|
+
module GRPC
|
7
|
+
module Commands
|
8
|
+
module Streams
|
9
|
+
class AppendMultiple < Command
|
10
|
+
# @api private
|
11
|
+
# @see {EventStoreClient::GRPC::Client#append_to_stream}
|
12
|
+
def call(stream_name, events, options:, &blk)
|
13
|
+
result = []
|
14
|
+
events.each.with_index do |event, index|
|
15
|
+
response = Commands::Streams::Append.new(**connection_options).call(
|
16
|
+
stream_name, event, options: options
|
17
|
+
) do |req_opts, proposed_msg_opts|
|
18
|
+
req_opts.options.revision += index if has_revision_option?(req_opts.options)
|
19
|
+
|
20
|
+
yield(req_opts, proposed_msg_opts) if blk
|
21
|
+
end
|
22
|
+
result.push(response)
|
23
|
+
break if response.failure?
|
24
|
+
end
|
25
|
+
result
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
# Even if #revision is not set explicitly - its value defaults to 0. Thus, you can't
|
31
|
+
# detect whether #revision is set just by calling #revision method. Instead - check if
|
32
|
+
# option does not set #no_stream, #any or #stream_exists options - they are self-exclusive
|
33
|
+
# options and only one of them can be active at a time
|
34
|
+
# @param options [EventStore::Client::Streams::AppendReq::Options]
|
35
|
+
# @return [Boolean]
|
36
|
+
def has_revision_option?(options)
|
37
|
+
[options.no_stream, options.any, options.stream_exists].all?(&:nil?)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
# rubocop:enable Naming/PredicateName
|
@@ -1,10 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'grpc'
|
4
|
-
require 'event_store_client/adapters/grpc/generated/
|
5
|
-
require 'event_store_client/adapters/grpc/generated/projections_services_pb.rb'
|
6
|
-
|
7
|
-
require 'event_store_client/adapters/grpc/commands/command'
|
3
|
+
require 'event_store_client/adapters/grpc/generated/streams_pb'
|
4
|
+
require 'event_store_client/adapters/grpc/generated/streams_services_pb'
|
8
5
|
|
9
6
|
module EventStoreClient
|
10
7
|
module GRPC
|
@@ -14,19 +11,26 @@ module EventStoreClient
|
|
14
11
|
use_request EventStore::Client::Streams::DeleteReq
|
15
12
|
use_service EventStore::Client::Streams::Streams::Stub
|
16
13
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
service.delete(request.new(options: opts), metadata: metadata)
|
27
|
-
Success()
|
14
|
+
# @api private
|
15
|
+
# @see {EventStoreClient::GRPC::Client#delete_stream}
|
16
|
+
def call(stream_name, options:, &blk)
|
17
|
+
options = normalize_options(stream_name, options)
|
18
|
+
yield options if blk
|
19
|
+
Success(
|
20
|
+
retry_request { service.delete(request.new(options: options), metadata: metadata) }
|
21
|
+
)
|
28
22
|
rescue ::GRPC::FailedPrecondition
|
29
|
-
Failure(:
|
23
|
+
Failure(:stream_not_found)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
# @param stream_name [String]
|
29
|
+
# @param options [Hash]
|
30
|
+
# @return [EventStore::Client::Streams::TombstoneReq::Options]
|
31
|
+
def normalize_options(stream_name, options)
|
32
|
+
opts = Options::Streams::WriteOptions.new(stream_name, options).request_options
|
33
|
+
EventStore::Client::Streams::DeleteReq::Options.new(opts)
|
30
34
|
end
|
31
35
|
end
|
32
36
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'event_store_client/adapters/grpc/generated/streams_pb'
|
4
|
+
require 'event_store_client/adapters/grpc/generated/streams_services_pb'
|
5
|
+
|
6
|
+
module EventStoreClient
|
7
|
+
module GRPC
|
8
|
+
module Commands
|
9
|
+
module Streams
|
10
|
+
class HardDelete < Command
|
11
|
+
use_request EventStore::Client::Streams::TombstoneReq
|
12
|
+
use_service EventStore::Client::Streams::Streams::Stub
|
13
|
+
|
14
|
+
# @api private
|
15
|
+
# @see {EventStoreClient::GRPC::Client#hard_delete_stream}
|
16
|
+
def call(stream_name, options:, &blk)
|
17
|
+
options = normalize_options(stream_name, options)
|
18
|
+
yield options if blk
|
19
|
+
Success(
|
20
|
+
retry_request { service.delete(request.new(options: options), metadata: metadata) }
|
21
|
+
)
|
22
|
+
rescue ::GRPC::FailedPrecondition
|
23
|
+
Failure(:stream_not_found)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
# @param stream_name [String]
|
29
|
+
# @param options [Hash]
|
30
|
+
# @return [EventStore::Client::Streams::TombstoneReq::Options]
|
31
|
+
def normalize_options(stream_name, options)
|
32
|
+
opts = Options::Streams::WriteOptions.new(stream_name, options).request_options
|
33
|
+
EventStore::Client::Streams::TombstoneReq::Options.new(opts)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -1,62 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'securerandom'
|
4
|
-
require 'grpc'
|
5
|
-
require 'event_store_client/adapters/grpc/generated/streams_pb.rb'
|
6
|
-
require 'event_store_client/adapters/grpc/generated/streams_services_pb.rb'
|
7
|
-
|
8
|
-
require 'event_store_client/adapters/grpc/commands/command'
|
9
|
-
|
10
3
|
module EventStoreClient
|
11
4
|
module GRPC
|
12
5
|
module Commands
|
13
6
|
module Streams
|
14
7
|
class LinkTo < Command
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
custom_metadata = JSON.generate(
|
23
|
-
"type": '$>',
|
24
|
-
"created_at": Time.now,
|
25
|
-
"encryption": event.metadata['encryption'] || ''
|
26
|
-
)
|
27
|
-
|
28
|
-
event_metadata = event.metadata.tap do |h|
|
29
|
-
h['type'] = '$>'
|
30
|
-
h['content-type'] = 'application/json'
|
31
|
-
h.delete('encryption')
|
32
|
-
end
|
33
|
-
|
34
|
-
event_id = event.id
|
35
|
-
event_id = SecureRandom.uuid if event.id.nil? || event.id.empty?
|
36
|
-
|
37
|
-
payload = [
|
38
|
-
request.new(
|
39
|
-
options: {
|
40
|
-
stream_identifier: {
|
41
|
-
streamName: stream_name
|
42
|
-
},
|
43
|
-
any: {}
|
44
|
-
}
|
45
|
-
),
|
46
|
-
request.new(
|
47
|
-
proposed_message: {
|
48
|
-
id: {
|
49
|
-
string: event_id
|
50
|
-
},
|
51
|
-
data: event.title,
|
52
|
-
custom_metadata: custom_metadata,
|
53
|
-
metadata: event_metadata
|
54
|
-
}
|
55
|
-
)
|
56
|
-
]
|
57
|
-
service.append(payload, metadata: metadata)
|
58
|
-
end
|
59
|
-
Success()
|
8
|
+
# @see {EventStoreClient::GRPC::Client#hard_delete_stream}
|
9
|
+
def call(stream_name, event, options:, &blk)
|
10
|
+
append_cmd = Append.new(**connection_options)
|
11
|
+
link_event = EventStoreClient::DeserializedEvent.new(
|
12
|
+
id: event.id, type: '$>', data: event.title
|
13
|
+
)
|
14
|
+
append_cmd.call(stream_name, link_event, options: options, &blk)
|
60
15
|
end
|
61
16
|
end
|
62
17
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# rubocop:disable Naming/PredicateName
|
4
|
+
|
5
|
+
module EventStoreClient
|
6
|
+
module GRPC
|
7
|
+
module Commands
|
8
|
+
module Streams
|
9
|
+
class LinkToMultiple < Command
|
10
|
+
# @api private
|
11
|
+
# @see {EventStoreClient::GRPC::Client#link_to}
|
12
|
+
def call(stream_name, events, options:, &blk)
|
13
|
+
result = []
|
14
|
+
link_cmd = Commands::Streams::LinkTo.new(**connection_options)
|
15
|
+
events.each.with_index do |event, index|
|
16
|
+
response =
|
17
|
+
link_cmd.call(stream_name, event, options: options) do |req_opts, proposed_msg_opts|
|
18
|
+
req_opts.options.revision += index if has_revision_option?(req_opts.options)
|
19
|
+
|
20
|
+
yield(req_opts, proposed_msg_opts) if blk
|
21
|
+
end
|
22
|
+
result.push(response)
|
23
|
+
break if response.failure?
|
24
|
+
end
|
25
|
+
result
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
# Even if #revision is not set explicitly - its value defaults to 0. Thus, you can't
|
31
|
+
# detect whether #revision is set just by calling #revision method. Instead - check if
|
32
|
+
# option does not set #no_stream, #any or #stream_exists options - they are self-exclusive
|
33
|
+
# options and only one of them can be active at a time
|
34
|
+
# @param options [EventStore::Client::Streams::AppendReq::Options]
|
35
|
+
# @return [Boolean]
|
36
|
+
def has_revision_option?(options)
|
37
|
+
[options.no_stream, options.any, options.stream_exists].all?(&:nil?)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
# rubocop:enable Naming/PredicateName
|