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,119 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EventStoreClient
4
+ module GRPC
5
+ class Client
6
+ include Configuration
7
+ # Appends given events to the stream
8
+ # @param [String] Stream name to append events to
9
+ # @param [Array](each: EventStoreClient::DeserializedEvent) list of events to publish
10
+ # @return Dry::Monads::Result::Success or Dry::Monads::Result::Failure
11
+ #
12
+ def append_to_stream(stream_name, events, options: {})
13
+ Commands::Streams::Append.new.call(
14
+ stream_name, events, options: {}
15
+ )
16
+ end
17
+
18
+ # Softly deletes the given stream
19
+ # @param [String] Stream name to delete
20
+ # @param options [Hash] additional options to the request
21
+ # @return Dry::Monads::Result::Success or Dry::Monads::Result::Failure
22
+ #
23
+ def delete_stream(stream_name, options: {})
24
+ Commands::Streams::Delete.new.call(
25
+ stream_name, options: options
26
+ )
27
+ end
28
+
29
+ # Completely removes the given stream
30
+ # @param [String] Stream name to delete
31
+ # @param options [Hash] additional options to the request
32
+ # @return Dry::Monads::Result::Success or Dry::Monads::Result::Failure
33
+ #
34
+ def tombstone_stream(stream_name, options: {})
35
+ Commands::Streams::Tombstone.new.call(stream_name, options: options)
36
+ end
37
+
38
+ # Reads a page of events from the given stream
39
+ # @param [String] Stream name to read events from
40
+ # @param options [Hash] additional options to the request
41
+ # @return Dry::Monads::Result::Success with returned events or Dry::Monads::Result::Failure
42
+ #
43
+ def read(stream_name, options: {})
44
+ Commands::Streams::Read.new.call(stream_name, options: options)
45
+ end
46
+
47
+ # Reads all events from the given stream
48
+ # @param [String] Stream name to read events from
49
+ # @param options [Hash] additional options to the request
50
+ # @return Dry::Monads::Result::Success with returned events or Dry::Monads::Result::Failure
51
+ #
52
+ def read_all_from_stream(stream_name, options: {})
53
+ Commands::Streams::ReadAll.new.call(stream_name, options: options)
54
+ end
55
+
56
+ # Creates the subscription for the given stream
57
+ # @param [EventStoreClient::Subscription] subscription to observe
58
+ # @param options [Hash] additional options to the request
59
+ # @return Dry::Monads::Result::Success or Dry::Monads::Result::Failure
60
+ #
61
+ def subscribe_to_stream(subscription, options: {})
62
+ join_streams(subscription.name, subscription.observed_streams)
63
+ Commands::PersistentSubscriptions::Create.new.call(
64
+ subscription.stream,
65
+ subscription.name,
66
+ options: options
67
+ )
68
+ end
69
+
70
+ # Links given events with the given stream
71
+ # @param [String] Stream name to link events to
72
+ # @param [Array](each: EventStoreClient::DeserializedEvent) a list of events to link
73
+ # @param expected_version [Integer] expected number of events in the stream
74
+ # @return Dry::Monads::Result::Success or Dry::Monads::Result::Failure
75
+ #
76
+ def link_to(stream_name, events, options: {})
77
+ Commands::Streams::LinkTo.new.call(stream_name, events, options: options)
78
+ end
79
+
80
+ # Runs the persistent subscription indeinitely
81
+ # @param [EventStoreClient::Subscription] subscription to observe
82
+ # @param options [Hash] additional options to the request
83
+ # @return - Nothing, it is a blocking operation, yields the given block with event instead
84
+ #
85
+ def listen(subscription, options: {})
86
+ consume_feed(subscription, options: options) do |event|
87
+ yield event if block_given?
88
+ end
89
+ rescue StandardError => e
90
+ config.error_handler&.call(e)
91
+ end
92
+
93
+ private
94
+
95
+ # Joins multiple streams into the new one under the given name
96
+ # @param [String] Name of the stream containing the ones to join
97
+ # @param [Array] (each: String) list of streams to join together
98
+ # @return Dry::Monads::Result::Success or Dry::Monads::Result::Failure
99
+ #
100
+ def join_streams(name, streams)
101
+ Commands::Projections::Create.new.call(name, streams)
102
+ end
103
+
104
+ # @api private
105
+ # Consumes the new events from the subscription
106
+ # @param [EventStoreClient::Subscription] subscription to observe
107
+ # @param options [Hash] additional options to the request
108
+ # @return Dry::Monads::Result::Success or Dry::Monads::Result::Failure
109
+ #
110
+ def consume_feed(subscription, options: {})
111
+ Commands::PersistentSubscriptions::Read.new.call(
112
+ subscription.stream, subscription.name, options: options
113
+ ) do |event|
114
+ yield event if block_given?
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'grpc'
4
+ require 'event_store_client/adapters/grpc/connection'
5
+
6
+ module EventStoreClient
7
+ module GRPC
8
+ class CommandRegistrar
9
+ @commands = {}
10
+
11
+ def self.register_request(command_klass, request:)
12
+ @commands[command_klass] ||= {}
13
+ @commands[command_klass][:request] = request
14
+ end
15
+
16
+ def self.register_service(command_klass, service:)
17
+ @commands[command_klass] ||= {}
18
+ @commands[command_klass][:service] = service
19
+ end
20
+
21
+ def self.request(command_klass)
22
+ @commands[command_klass][:request]
23
+ end
24
+
25
+ def self.service(command_klass)
26
+ EventStoreClient::GRPC::Connection.new.call(
27
+ @commands[command_klass][:service]
28
+ )
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,43 @@
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 GRPC
8
+ module Commands
9
+ class Command
10
+ include Configuration
11
+
12
+ def self.inherited(klass)
13
+ super
14
+ klass.class_eval do
15
+ include Dry::Monads[:result]
16
+
17
+ def self.use_request(request_klass)
18
+ CommandRegistrar.register_request(self, request: request_klass)
19
+ end
20
+
21
+ def self.use_service(service_klass)
22
+ CommandRegistrar.register_service(self, service: service_klass)
23
+ end
24
+
25
+ def request
26
+ CommandRegistrar.request(self.class)
27
+ end
28
+
29
+ def service
30
+ CommandRegistrar.service(self.class)
31
+ end
32
+ end
33
+ end
34
+
35
+ def metadata
36
+ credentials =
37
+ Base64.encode64("#{config.eventstore_user}:#{config.eventstore_password}")
38
+ { 'authorization' => "Basic #{credentials.delete("\n")}" }
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'grpc'
4
+ require 'event_store_client/adapters/grpc/generated/persistent_pb.rb'
5
+ require 'event_store_client/adapters/grpc/generated/persistent_services_pb.rb'
6
+
7
+ require 'event_store_client/adapters/grpc/commands/command'
8
+ require 'event_store_client/adapters/grpc/commands/persistent_subscriptions/settings_schema'
9
+
10
+ module EventStoreClient
11
+ module GRPC
12
+ module Commands
13
+ module PersistentSubscriptions
14
+ class Create < Command
15
+ use_request EventStore::Client::PersistentSubscriptions::CreateReq
16
+ use_service EventStore::Client::PersistentSubscriptions::PersistentSubscriptions::Stub
17
+
18
+ # Creates persistent subscription in a given group
19
+ # @param [String] name of the stream to subscribe
20
+ # @param [String] name of the subscription group
21
+ # @param [Hash] options - additional settings to be set on subscription.
22
+ # Refer to SettingsSchema for detailed attributes allowed
23
+ # @return [Dry::Monads::Result::Success, Dry::Monads::Result::Failure]
24
+ #
25
+ def call(stream, group, options: {})
26
+ schema = SettingsSchema.call(options)
27
+ return Failure(schema.errors) if schema.failure?
28
+ opts =
29
+ {
30
+ stream_identifier: {
31
+ streamName: stream
32
+ },
33
+ group_name: group,
34
+ settings: schema.to_h
35
+ }
36
+
37
+ service.create(request.new(options: opts), metadata: metadata)
38
+ Success()
39
+ rescue ::GRPC::AlreadyExists
40
+ Failure(:conflict)
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'grpc'
4
+ require 'event_store_client/adapters/grpc/generated/persistent_pb.rb'
5
+ require 'event_store_client/adapters/grpc/generated/persistent_services_pb.rb'
6
+
7
+ require 'event_store_client/adapters/grpc/commands/command'
8
+
9
+ module EventStoreClient
10
+ module GRPC
11
+ module Commands
12
+ module PersistentSubscriptions
13
+ class Delete < Command
14
+ use_request EventStore::Client::PersistentSubscriptions::DeleteReq
15
+ use_service EventStore::Client::PersistentSubscriptions::PersistentSubscriptions::Stub
16
+
17
+ def call(stream, group)
18
+ opts =
19
+ {
20
+ stream_identifier: {
21
+ streamName: stream
22
+ },
23
+ group_name: group
24
+ }
25
+ service.delete(request.new(options: opts), metadata: metadata)
26
+ Success()
27
+ rescue ::GRPC::NotFound
28
+ Failure(:not_found)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'grpc'
4
+ require 'event_store_client/adapters/grpc/generated/persistent_pb.rb'
5
+ require 'event_store_client/adapters/grpc/generated/persistent_services_pb.rb'
6
+
7
+ require 'event_store_client/adapters/grpc/commands/command'
8
+ require 'event_store_client/adapters/grpc/commands/persistent_subscriptions/settings_schema'
9
+ require 'irb'
10
+ module EventStoreClient
11
+ module GRPC
12
+ module Commands
13
+ module PersistentSubscriptions
14
+ class Read < Command
15
+ use_request EventStore::Client::PersistentSubscriptions::ReadReq
16
+ use_service EventStore::Client::PersistentSubscriptions::PersistentSubscriptions::Stub
17
+
18
+ # Read given persistent subscription
19
+ # @param [String] name of the stream to subscribe
20
+ # @param [String] name of the subscription group
21
+ # @param [Hash] options - additional settings to be set on subscription.
22
+ # Refer to SettingsSchema for detailed attributes allowed
23
+ # @return [Dry::Monads::Result::Success, Dry::Monads::Result::Failure]
24
+ #
25
+ def call(stream, group, options: {})
26
+ count = options[:count].to_i
27
+ opts =
28
+ {
29
+ stream_identifier: {
30
+ streamName: stream
31
+ },
32
+ buffer_size: count,
33
+ group_name: group,
34
+ uuid_option: {
35
+ structured: {}
36
+ }
37
+ }
38
+
39
+ requests = [request.new(options: opts)] # please notice that it's an array. Should be?
40
+
41
+ service.read(requests, metadata: metadata).each do |res|
42
+ next if res.subscription_confirmation
43
+ yield deserialize_event(res.event.event) if block_given?
44
+ end
45
+ Success()
46
+ end
47
+
48
+ private
49
+
50
+ def deserialize_event(entry)
51
+ binding.irb if event.data.include?('00735ff8-2d12-4bc7-8db2-af432baacdf1')
52
+ event = EventStoreClient::Event.new(
53
+ id: entry.id.string,
54
+ title: "#{entry.stream_revision}@#{entry.stream_identifier.streamName}",
55
+ type: entry.metadata['type'],
56
+ data: entry.data || '{}',
57
+ metadata: (entry.metadata.to_h || {}).to_json
58
+ )
59
+
60
+ config.mapper.deserialize(event)
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'grpc'
4
+ require 'event_store_client/adapters/grpc/generated/persistent_pb.rb'
5
+ require 'event_store_client/adapters/grpc/generated/persistent_services_pb.rb'
6
+
7
+ require 'event_store_client/adapters/grpc/commands/command'
8
+
9
+ module EventStoreClient
10
+ module GRPC
11
+ module Commands
12
+ module PersistentSubscriptions
13
+ # Ensures the proper format of the parameters passed to the subscirption request
14
+ #
15
+ SettingsSchema = Dry::Schema.Params do
16
+ optional(:resolve_links).value(Dry::Types['bool'].default(true))
17
+ optional(:revision).value(Dry::Types['integer'])
18
+ optional(:extra_statistics).value(Dry::Types['bool'])
19
+ optional(:max_retry_count).value(Dry::Types['integer'])
20
+ optional(:min_checkpoint_count).value(Dry::Types['integer'])
21
+ optional(:max_checkpoint_count).value(Dry::Types['integer'])
22
+ optional(:max_subscriber_count).value(Dry::Types['integer'])
23
+ optional(:live_buffer_size).value(Dry::Types['integer'])
24
+ optional(:read_batch_size).value(Dry::Types['integer'])
25
+ optional(:history_buffer_size).value(Dry::Types['integer'].default(500))
26
+ optional(:message_timeout_ms).value(Dry::Types['integer'].default(10_000))
27
+ # optional(:message_timeout_ticks).value(Dry::Types['integer'].default(10000))
28
+
29
+ optional(:checkpoint_after_ms).value(Dry::Types['integer'].default(1000))
30
+ optional(:named_consumer_strategy).value(
31
+ Dry::Types['symbol'].default(:RoundRobin),
32
+ included_in?: %i[DispatchToSingle RoundRobin Pinned]
33
+ )
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'grpc'
4
+ require 'event_store_client/adapters/grpc/generated/persistent_pb.rb'
5
+ require 'event_store_client/adapters/grpc/generated/persistent_services_pb.rb'
6
+
7
+ require 'event_store_client/adapters/grpc/commands/command'
8
+ require 'event_store_client/adapters/grpc/commands/persistent_subscriptions/settings_schema'
9
+
10
+ module EventStoreClient
11
+ module GRPC
12
+ module Commands
13
+ module PersistentSubscriptions
14
+ class Update < Command
15
+ use_request EventStore::Client::PersistentSubscriptions::UpdateReq
16
+ use_service EventStore::Client::PersistentSubscriptions::PersistentSubscriptions::Stub
17
+
18
+ # Creates persistent subscription in a given group
19
+ # @param [String] name of the subscription stream to update
20
+ # @param [String] name of the subscription group
21
+ # @param [Hash] options - additional settings to be set on subscription.
22
+ # Refer to EventStoreClient::GRPC::Commands::SettingsSchema
23
+ # for detailed attributes schema
24
+ # @return [Dry::Monads::Result::Success, Dry::Monads::Result::Failure]
25
+ #
26
+ def call(stream, group, options: {})
27
+ schema = SettingsSchema.call(options)
28
+ return Failure(schema.errors) if schema.failure?
29
+
30
+ opts =
31
+ {
32
+ stream_identifier: {
33
+ streamName: stream
34
+ },
35
+ group_name: group,
36
+ settings: schema.to_h
37
+ }
38
+ service.update(request.new(options: opts), metadata: metadata)
39
+ Success()
40
+ rescue ::GRPC::Unknown => e
41
+ return Failure(:not_found) if e.message.include?('DoesNotExist')
42
+ raise e
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'grpc'
4
+ require 'event_store_client/adapters/grpc/generated/projections_pb.rb'
5
+ require 'event_store_client/adapters/grpc/generated/projections_services_pb.rb'
6
+
7
+ require 'event_store_client/adapters/grpc/commands/command'
8
+
9
+ module EventStoreClient
10
+ module GRPC
11
+ module Commands
12
+ module Projections
13
+ class Create < Command
14
+ use_request EventStore::Client::Projections::CreateReq
15
+ use_service EventStore::Client::Projections::Projections::Stub
16
+
17
+ def call(name, streams)
18
+ data = <<~STRING
19
+ fromStreams(#{streams})
20
+ .when({
21
+ $any: function(s,e) {
22
+ linkTo("#{name}", e)
23
+ }
24
+ })
25
+ STRING
26
+
27
+ options =
28
+ {
29
+ query: data,
30
+ continuous: {
31
+ name: name,
32
+ track_emitted_streams: true
33
+ }
34
+ }
35
+
36
+ service.create(request.new(options: options), metadata: metadata)
37
+ Success()
38
+ rescue ::GRPC::Unknown => e
39
+ Failure(:conflict) if e.message.include?('Conflict')
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end