event_store_client 0.2.8 → 1.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.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +29 -37
  3. data/lib/event_store_client.rb +0 -2
  4. data/lib/event_store_client/adapters/grpc.rb +21 -0
  5. data/lib/event_store_client/adapters/grpc/Protos/cluster.proto +149 -0
  6. data/lib/event_store_client/adapters/grpc/Protos/gossip.proto +44 -0
  7. data/lib/event_store_client/adapters/grpc/Protos/operations.proto +45 -0
  8. data/lib/event_store_client/adapters/grpc/Protos/persistent.proto +180 -0
  9. data/lib/event_store_client/adapters/grpc/Protos/projections.proto +174 -0
  10. data/lib/event_store_client/adapters/grpc/Protos/shared.proto +22 -0
  11. data/lib/event_store_client/adapters/grpc/Protos/streams.proto +242 -0
  12. data/lib/event_store_client/adapters/grpc/Protos/users.proto +119 -0
  13. data/lib/event_store_client/adapters/grpc/client.rb +119 -0
  14. data/lib/event_store_client/adapters/grpc/command_registrar.rb +32 -0
  15. data/lib/event_store_client/adapters/grpc/commands/command.rb +43 -0
  16. data/lib/event_store_client/adapters/grpc/commands/persistent_subscriptions/create.rb +46 -0
  17. data/lib/event_store_client/adapters/grpc/commands/persistent_subscriptions/delete.rb +34 -0
  18. data/lib/event_store_client/adapters/grpc/commands/persistent_subscriptions/read.rb +66 -0
  19. data/lib/event_store_client/adapters/grpc/commands/persistent_subscriptions/settings_schema.rb +38 -0
  20. data/lib/event_store_client/adapters/grpc/commands/persistent_subscriptions/update.rb +48 -0
  21. data/lib/event_store_client/adapters/grpc/commands/projections/create.rb +45 -0
  22. data/lib/event_store_client/adapters/grpc/commands/projections/delete.rb +34 -0
  23. data/lib/event_store_client/adapters/grpc/commands/projections/update.rb +42 -0
  24. data/lib/event_store_client/adapters/grpc/commands/streams/append.rb +57 -0
  25. data/lib/event_store_client/adapters/grpc/commands/streams/delete.rb +35 -0
  26. data/lib/event_store_client/adapters/grpc/commands/streams/link_to.rb +53 -0
  27. data/lib/event_store_client/adapters/grpc/commands/streams/read.rb +80 -0
  28. data/lib/event_store_client/adapters/grpc/commands/streams/read_all.rb +43 -0
  29. data/lib/event_store_client/adapters/grpc/commands/streams/tombstone.rb +35 -0
  30. data/lib/event_store_client/adapters/grpc/connection.rb +50 -0
  31. data/lib/event_store_client/adapters/grpc/generated/cluster_pb.rb +140 -0
  32. data/lib/event_store_client/adapters/grpc/generated/cluster_services_pb.rb +46 -0
  33. data/lib/event_store_client/adapters/grpc/generated/gossip_pb.rb +53 -0
  34. data/lib/event_store_client/adapters/grpc/generated/gossip_services_pb.rb +26 -0
  35. data/lib/event_store_client/adapters/grpc/generated/operations_pb.rb +49 -0
  36. data/lib/event_store_client/adapters/grpc/generated/operations_services_pb.rb +31 -0
  37. data/lib/event_store_client/adapters/grpc/generated/persistent_pb.rb +213 -0
  38. data/lib/event_store_client/adapters/grpc/generated/persistent_services_pb.rb +29 -0
  39. data/lib/event_store_client/adapters/grpc/generated/projections_pb.rb +193 -0
  40. data/lib/event_store_client/adapters/grpc/generated/projections_services_pb.rb +34 -0
  41. data/lib/event_store_client/adapters/grpc/generated/shared_pb.rb +35 -0
  42. data/lib/event_store_client/adapters/grpc/generated/streams_pb.rb +283 -0
  43. data/lib/event_store_client/adapters/grpc/generated/streams_services_pb.rb +29 -0
  44. data/lib/event_store_client/adapters/grpc/generated/users_pb.rb +126 -0
  45. data/lib/event_store_client/adapters/grpc/generated/users_services_pb.rb +33 -0
  46. data/lib/event_store_client/adapters/http.rb +16 -0
  47. data/lib/event_store_client/adapters/http/README.md +16 -0
  48. data/lib/event_store_client/adapters/http/client.rb +160 -0
  49. data/lib/event_store_client/adapters/http/commands/command.rb +27 -0
  50. data/lib/event_store_client/adapters/http/commands/persistent_subscriptions/ack.rb +15 -0
  51. data/lib/event_store_client/adapters/http/commands/persistent_subscriptions/create.rb +31 -0
  52. data/lib/event_store_client/adapters/http/commands/persistent_subscriptions/read.rb +57 -0
  53. data/lib/event_store_client/adapters/http/commands/projections/create.rb +30 -0
  54. data/lib/event_store_client/adapters/http/commands/streams/append.rb +49 -0
  55. data/lib/event_store_client/adapters/http/commands/streams/delete.rb +16 -0
  56. data/lib/event_store_client/adapters/http/commands/streams/link_to.rb +49 -0
  57. data/lib/event_store_client/adapters/http/commands/streams/read.rb +53 -0
  58. data/lib/event_store_client/adapters/http/commands/streams/tombstone.rb +17 -0
  59. data/lib/event_store_client/adapters/http/connection.rb +46 -0
  60. data/lib/event_store_client/adapters/http/request_method.rb +28 -0
  61. data/lib/event_store_client/adapters/in_memory.rb +139 -0
  62. data/lib/event_store_client/broker.rb +16 -5
  63. data/lib/event_store_client/client.rb +17 -69
  64. data/lib/event_store_client/configuration.rb +28 -14
  65. data/lib/event_store_client/data_decryptor.rb +13 -8
  66. data/lib/event_store_client/data_encryptor.rb +7 -6
  67. data/lib/event_store_client/deserialized_event.rb +4 -1
  68. data/lib/event_store_client/event.rb +2 -2
  69. data/lib/event_store_client/mapper/default.rb +0 -1
  70. data/lib/event_store_client/serializer/json.rb +2 -0
  71. data/lib/event_store_client/subscriptions.rb +4 -13
  72. data/lib/event_store_client/types.rb +3 -1
  73. data/lib/event_store_client/value_objects/read_direction.rb +43 -0
  74. data/lib/event_store_client/version.rb +1 -1
  75. metadata +97 -15
  76. data/lib/event_store_client/store_adapter.rb +0 -10
  77. data/lib/event_store_client/store_adapter/api/client.rb +0 -224
  78. data/lib/event_store_client/store_adapter/api/connection.rb +0 -43
  79. data/lib/event_store_client/store_adapter/api/request_method.rb +0 -30
  80. data/lib/event_store_client/store_adapter/in_memory.rb +0 -160
@@ -0,0 +1,29 @@
1
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
2
+ # Source: streams.proto for package 'event_store.client.streams'
3
+
4
+ require 'grpc'
5
+ require 'event_store_client/adapters/grpc/generated/streams_pb'
6
+
7
+ module EventStore
8
+ module Client
9
+ module Streams
10
+ module Streams
11
+ class Service
12
+
13
+ include GRPC::GenericService
14
+
15
+ self.marshal_class_method = :encode
16
+ self.unmarshal_class_method = :decode
17
+ self.service_name = 'event_store.client.streams.Streams'
18
+
19
+ rpc :Read, ::EventStore::Client::Streams::ReadReq, stream(::EventStore::Client::Streams::ReadResp)
20
+ rpc :Append, stream(::EventStore::Client::Streams::AppendReq), ::EventStore::Client::Streams::AppendResp
21
+ rpc :Delete, ::EventStore::Client::Streams::DeleteReq, ::EventStore::Client::Streams::DeleteResp
22
+ rpc :Tombstone, ::EventStore::Client::Streams::TombstoneReq, ::EventStore::Client::Streams::TombstoneResp
23
+ end
24
+
25
+ Stub = Service.rpc_stub_class
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,126 @@
1
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
2
+ # source: users.proto
3
+
4
+ require 'google/protobuf'
5
+
6
+ Google::Protobuf::DescriptorPool.generated_pool.build do
7
+ add_file("users.proto", :syntax => :proto3) do
8
+ add_message "event_store.client.users.CreateReq" do
9
+ optional :options, :message, 1, "event_store.client.users.CreateReq.Options"
10
+ end
11
+ add_message "event_store.client.users.CreateReq.Options" do
12
+ optional :login_name, :string, 1
13
+ optional :password, :string, 2
14
+ optional :full_name, :string, 3
15
+ repeated :groups, :string, 4
16
+ end
17
+ add_message "event_store.client.users.CreateResp" do
18
+ end
19
+ add_message "event_store.client.users.UpdateReq" do
20
+ optional :options, :message, 1, "event_store.client.users.UpdateReq.Options"
21
+ end
22
+ add_message "event_store.client.users.UpdateReq.Options" do
23
+ optional :login_name, :string, 1
24
+ optional :password, :string, 2
25
+ optional :full_name, :string, 3
26
+ repeated :groups, :string, 4
27
+ end
28
+ add_message "event_store.client.users.UpdateResp" do
29
+ end
30
+ add_message "event_store.client.users.DeleteReq" do
31
+ optional :options, :message, 1, "event_store.client.users.DeleteReq.Options"
32
+ end
33
+ add_message "event_store.client.users.DeleteReq.Options" do
34
+ optional :login_name, :string, 1
35
+ end
36
+ add_message "event_store.client.users.DeleteResp" do
37
+ end
38
+ add_message "event_store.client.users.EnableReq" do
39
+ optional :options, :message, 1, "event_store.client.users.EnableReq.Options"
40
+ end
41
+ add_message "event_store.client.users.EnableReq.Options" do
42
+ optional :login_name, :string, 1
43
+ end
44
+ add_message "event_store.client.users.EnableResp" do
45
+ end
46
+ add_message "event_store.client.users.DisableReq" do
47
+ optional :options, :message, 1, "event_store.client.users.DisableReq.Options"
48
+ end
49
+ add_message "event_store.client.users.DisableReq.Options" do
50
+ optional :login_name, :string, 1
51
+ end
52
+ add_message "event_store.client.users.DisableResp" do
53
+ end
54
+ add_message "event_store.client.users.DetailsReq" do
55
+ optional :options, :message, 1, "event_store.client.users.DetailsReq.Options"
56
+ end
57
+ add_message "event_store.client.users.DetailsReq.Options" do
58
+ optional :login_name, :string, 1
59
+ end
60
+ add_message "event_store.client.users.DetailsResp" do
61
+ optional :user_details, :message, 1, "event_store.client.users.DetailsResp.UserDetails"
62
+ end
63
+ add_message "event_store.client.users.DetailsResp.UserDetails" do
64
+ optional :login_name, :string, 1
65
+ optional :full_name, :string, 2
66
+ repeated :groups, :string, 3
67
+ optional :last_updated, :message, 4, "event_store.client.users.DetailsResp.UserDetails.DateTime"
68
+ optional :disabled, :bool, 5
69
+ end
70
+ add_message "event_store.client.users.DetailsResp.UserDetails.DateTime" do
71
+ optional :ticks_since_epoch, :int64, 1
72
+ end
73
+ add_message "event_store.client.users.ChangePasswordReq" do
74
+ optional :options, :message, 1, "event_store.client.users.ChangePasswordReq.Options"
75
+ end
76
+ add_message "event_store.client.users.ChangePasswordReq.Options" do
77
+ optional :login_name, :string, 1
78
+ optional :current_password, :string, 2
79
+ optional :new_password, :string, 3
80
+ end
81
+ add_message "event_store.client.users.ChangePasswordResp" do
82
+ end
83
+ add_message "event_store.client.users.ResetPasswordReq" do
84
+ optional :options, :message, 1, "event_store.client.users.ResetPasswordReq.Options"
85
+ end
86
+ add_message "event_store.client.users.ResetPasswordReq.Options" do
87
+ optional :login_name, :string, 1
88
+ optional :new_password, :string, 2
89
+ end
90
+ add_message "event_store.client.users.ResetPasswordResp" do
91
+ end
92
+ end
93
+ end
94
+
95
+ module EventStore
96
+ module Client
97
+ module Users
98
+ CreateReq = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("event_store.client.users.CreateReq").msgclass
99
+ CreateReq::Options = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("event_store.client.users.CreateReq.Options").msgclass
100
+ CreateResp = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("event_store.client.users.CreateResp").msgclass
101
+ UpdateReq = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("event_store.client.users.UpdateReq").msgclass
102
+ UpdateReq::Options = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("event_store.client.users.UpdateReq.Options").msgclass
103
+ UpdateResp = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("event_store.client.users.UpdateResp").msgclass
104
+ DeleteReq = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("event_store.client.users.DeleteReq").msgclass
105
+ DeleteReq::Options = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("event_store.client.users.DeleteReq.Options").msgclass
106
+ DeleteResp = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("event_store.client.users.DeleteResp").msgclass
107
+ EnableReq = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("event_store.client.users.EnableReq").msgclass
108
+ EnableReq::Options = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("event_store.client.users.EnableReq.Options").msgclass
109
+ EnableResp = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("event_store.client.users.EnableResp").msgclass
110
+ DisableReq = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("event_store.client.users.DisableReq").msgclass
111
+ DisableReq::Options = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("event_store.client.users.DisableReq.Options").msgclass
112
+ DisableResp = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("event_store.client.users.DisableResp").msgclass
113
+ DetailsReq = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("event_store.client.users.DetailsReq").msgclass
114
+ DetailsReq::Options = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("event_store.client.users.DetailsReq.Options").msgclass
115
+ DetailsResp = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("event_store.client.users.DetailsResp").msgclass
116
+ DetailsResp::UserDetails = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("event_store.client.users.DetailsResp.UserDetails").msgclass
117
+ DetailsResp::UserDetails::DateTime = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("event_store.client.users.DetailsResp.UserDetails.DateTime").msgclass
118
+ ChangePasswordReq = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("event_store.client.users.ChangePasswordReq").msgclass
119
+ ChangePasswordReq::Options = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("event_store.client.users.ChangePasswordReq.Options").msgclass
120
+ ChangePasswordResp = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("event_store.client.users.ChangePasswordResp").msgclass
121
+ ResetPasswordReq = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("event_store.client.users.ResetPasswordReq").msgclass
122
+ ResetPasswordReq::Options = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("event_store.client.users.ResetPasswordReq.Options").msgclass
123
+ ResetPasswordResp = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("event_store.client.users.ResetPasswordResp").msgclass
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,33 @@
1
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
2
+ # Source: users.proto for package 'event_store.client.users'
3
+
4
+ require 'grpc'
5
+ require 'users_pb'
6
+
7
+ module EventStore
8
+ module Client
9
+ module Users
10
+ module Users
11
+ class Service
12
+
13
+ include GRPC::GenericService
14
+
15
+ self.marshal_class_method = :encode
16
+ self.unmarshal_class_method = :decode
17
+ self.service_name = 'event_store.client.users.Users'
18
+
19
+ rpc :Create, ::EventStore::Client::Users::CreateReq, ::EventStore::Client::Users::CreateResp
20
+ rpc :Update, ::EventStore::Client::Users::UpdateReq, ::EventStore::Client::Users::UpdateResp
21
+ rpc :Delete, ::EventStore::Client::Users::DeleteReq, ::EventStore::Client::Users::DeleteResp
22
+ rpc :Disable, ::EventStore::Client::Users::DisableReq, ::EventStore::Client::Users::DisableResp
23
+ rpc :Enable, ::EventStore::Client::Users::EnableReq, ::EventStore::Client::Users::EnableResp
24
+ rpc :Details, ::EventStore::Client::Users::DetailsReq, stream(::EventStore::Client::Users::DetailsResp)
25
+ rpc :ChangePassword, ::EventStore::Client::Users::ChangePasswordReq, ::EventStore::Client::Users::ChangePasswordResp
26
+ rpc :ResetPassword, ::EventStore::Client::Users::ResetPasswordReq, ::EventStore::Client::Users::ResetPasswordResp
27
+ end
28
+
29
+ Stub = Service.rpc_stub_class
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'event_store_client/adapters/http/commands/command'
4
+
5
+ require 'event_store_client/adapters/http/commands/persistent_subscriptions/create'
6
+ require 'event_store_client/adapters/http/commands/persistent_subscriptions/read'
7
+
8
+ require 'event_store_client/adapters/http/commands/projections/create'
9
+
10
+ require 'event_store_client/adapters/http/commands/streams/append'
11
+ require 'event_store_client/adapters/http/commands/streams/delete'
12
+ require 'event_store_client/adapters/http/commands/streams/link_to'
13
+ require 'event_store_client/adapters/http/commands/streams/read'
14
+ require 'event_store_client/adapters/http/commands/streams/tombstone'
15
+
16
+ require 'event_store_client/adapters/http/client'
@@ -0,0 +1,16 @@
1
+ ### HTTP adapter
2
+
3
+ This adapter targets the EventstoreDB version `>= "5.*"
4
+
5
+ For detailed docs about the http protocol see [EventStoreDB Http Documentation](https://developers.eventstore.com/server/5.0.8/http-api/)
6
+
7
+ ### Configuration
8
+
9
+ As by default EventStoreClient uses gRPC adapter, to switch to http you need to configure it first.
10
+ Place the snippet below in your initializer or when you boot your application.
11
+
12
+ ```ruby
13
+ EventStoreClient.configure do |config|
14
+ config.adapter = :api
15
+ end
16
+ ```
@@ -0,0 +1,160 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'event_store_client/adapters/http/connection'
4
+ require 'dry/monads/result'
5
+
6
+ module EventStoreClient
7
+ module HTTP
8
+ class Client
9
+ include Configuration
10
+ include Dry::Monads[:result]
11
+ # Appends given events to the stream
12
+ # @param [String] Stream name to append events to
13
+ # @param [Array](each: EventStoreClient::DeserializedEvent) list of events to publish
14
+ # @return Dry::Monads::Result::Success or Dry::Monads::Result::Failure
15
+ #
16
+ def append_to_stream(stream_name, events, options: {})
17
+ Commands::Streams::Append.new(connection).call(
18
+ stream_name, events, options: options
19
+ )
20
+ end
21
+
22
+ # Softly deletes the given stream
23
+ # @param [String] Stream name to delete
24
+ # @param options [Hash] additional options to the request
25
+ # @return Dry::Monads::Result::Success or Dry::Monads::Result::Failure
26
+ #
27
+ def delete_stream(stream_name, options: {})
28
+ Commands::Streams::Delete.new(connection).call(
29
+ stream_name, options: options
30
+ )
31
+ end
32
+
33
+ # Completely removes the given stream
34
+ # @param [String] Stream name to delete
35
+ # @param options [Hash] additional options to the request
36
+ # @return Dry::Monads::Result::Success or Dry::Monads::Result::Failure
37
+ #
38
+ def tombstone_stream(stream_name, options: {})
39
+ Commands::Streams::Tombstone.new(connection).call(
40
+ stream_name, options: options
41
+ )
42
+ end
43
+
44
+ # Reads a page of events from the given stream
45
+ # @param [String] Stream name to read events from
46
+ # @param options [Hash] additional options to the request
47
+ # @return Dry::Monads::Result::Success with returned events or Dry::Monads::Result::Failure
48
+ #
49
+ def read(stream_name, options: {})
50
+ Commands::Streams::Read.new(connection).call(
51
+ stream_name, options: options
52
+ )
53
+ end
54
+
55
+ # Reads all events from the given stream
56
+ # @param [String] Stream name to read events from
57
+ # @param options [Hash] additional options to the request
58
+ # @return Dry::Monads::Result::Success with returned events or Dry::Monads::Result::Failure
59
+ #
60
+ def read_all_from_stream(stream_name, options: {})
61
+ start ||= options[:start] || 0
62
+ count ||= options[:count] || 20
63
+ events = []
64
+ failed_requests_count = 0
65
+
66
+ while failed_requests_count < 3
67
+ res = read(stream_name, options: options.merge(start: start, count: count))
68
+ if res.failure?
69
+ failed_requests_count += 1
70
+ else
71
+ break if res.value!.empty?
72
+ events += res.value!
73
+ failed_requests_count = 0
74
+ start += count
75
+ end
76
+ end
77
+ return Failure(:connection_failed) if failed_requests_count >= 3
78
+
79
+ Success(events)
80
+ end
81
+
82
+ # Creates the subscription for the given stream
83
+ # @param [EventStoreClient::Subscription] subscription to observe
84
+ # @param options [Hash] additional options to the request
85
+ # @return Dry::Monads::Result::Success or Dry::Monads::Result::Failure
86
+ #
87
+ def subscribe_to_stream(subscription, options: {})
88
+ join_streams(subscription.name, subscription.observed_streams)
89
+ Commands::PersistentSubscriptions::Create.new(connection).call(
90
+ subscription.stream,
91
+ subscription.name,
92
+ options: options
93
+ )
94
+ end
95
+
96
+ # Links given events with the given stream
97
+ # @param [String] Stream name to link events to
98
+ # @param [Array](each: EventStoreClient::DeserializedEvent) a list of events to link
99
+ # @param expected_version [Integer] expected number of events in the stream
100
+ # @return Dry::Monads::Result::Success or Dry::Monads::Result::Failure
101
+ #
102
+ def link_to(stream_name, events, options: {})
103
+ Commands::Streams::LinkTo.new(connection).call(
104
+ stream_name, events, options: options
105
+ )
106
+ end
107
+
108
+ # Runs the persistent subscription indeinitely
109
+ # @param [EventStoreClient::Subscription] subscription to observe
110
+ # @param options [Hash] additional options to the request
111
+ # @return - Nothing, it is a blocking operation, yields the given block with event instead
112
+ #
113
+ def listen(subscription, options: {})
114
+ loop do
115
+ begin
116
+ consume_feed(subscription) do |event|
117
+ yield event if block_given?
118
+ end
119
+ rescue StandardError => e
120
+ config.error_handler&.call(e)
121
+ end
122
+ sleep(options[:interval] || 5) # wait for events to be processed
123
+ end
124
+ end
125
+
126
+ private
127
+
128
+ attr_reader :connection
129
+
130
+ def initialize
131
+ @connection =
132
+ Connection.new(config.eventstore_url, ssl: { verify: config.verify_ssl })
133
+ end
134
+
135
+ # @api private
136
+ # Joins multiple streams into the new one under the given name
137
+ # @param [String] Name of the stream containing the ones to join
138
+ # @param [Array] (each: String) list of streams to join together
139
+ # @return Dry::Monads::Result::Success or Dry::Monads::Result::Failure
140
+ #
141
+ def join_streams(name, streams, options: {})
142
+ Commands::Projections::Create.new(connection).call(name, streams, options: options)
143
+ end
144
+
145
+ # @api private
146
+ # Consumes the new events from the subscription
147
+ # @param [EventStoreClient::Subscription] subscription to observe
148
+ # @param options [Hash] additional options to the request
149
+ # @return Dry::Monads::Result::Success or Dry::Monads::Result::Failure
150
+ #
151
+ def consume_feed(subscription, options: {})
152
+ Commands::PersistentSubscriptions::Read.new(connection).call(
153
+ subscription.stream, subscription.name, options: options
154
+ ) do |event|
155
+ yield event if block_given?
156
+ end
157
+ end
158
+ end
159
+ end
160
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'dry-monads'
4
+ require 'event_store_client/adapters/grpc/command_registrar'
5
+
6
+ module EventStoreClient
7
+ module HTTP
8
+ module Commands
9
+ class Command
10
+ def self.inherited(klass)
11
+ super
12
+ klass.class_eval do
13
+ include Dry::Monads[:result]
14
+ end
15
+ end
16
+
17
+ protected
18
+
19
+ attr_reader :connection
20
+
21
+ def initialize(connection)
22
+ @connection = connection
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EventStoreClient
4
+ module HTTP
5
+ module Commands
6
+ module PersistentSubscriptions
7
+ class Ack < Command
8
+ def call(url)
9
+ connection.call(:post, url)
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EventStoreClient
4
+ module HTTP
5
+ module Commands
6
+ module PersistentSubscriptions
7
+ class Create < Command
8
+ def call(stream_name, subscription_name, options: {})
9
+ stats = options[:stats] || true
10
+ start = options[:start] || 0
11
+ retries = options[:retries] || 5
12
+
13
+ connection.call(
14
+ :put,
15
+ "/subscriptions/#{stream_name}/#{subscription_name}",
16
+ body: {
17
+ extraStatistics: stats,
18
+ startFrom: start,
19
+ maxRetryCount: retries,
20
+ resolveLinkTos: true
21
+ },
22
+ headers: {
23
+ 'Content-Type' => 'application/json'
24
+ }
25
+ )
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end