event_store_client 1.4.8 → 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.
Files changed (116) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +30 -145
  3. data/docs/appending_events.md +155 -0
  4. data/docs/catch_up_subscriptions.md +253 -0
  5. data/docs/configuration.md +83 -0
  6. data/docs/deleting_streams.md +25 -0
  7. data/docs/encrypting_events.md +84 -0
  8. data/docs/linking_events.md +149 -0
  9. data/docs/reading_events.md +200 -0
  10. data/lib/event_store_client/adapters/grpc/client.rb +244 -105
  11. data/lib/event_store_client/adapters/grpc/cluster/gossip_discover.rb +131 -0
  12. data/lib/event_store_client/adapters/grpc/cluster/insecure_connection.rb +21 -0
  13. data/lib/event_store_client/adapters/grpc/cluster/member.rb +18 -0
  14. data/lib/event_store_client/adapters/grpc/cluster/queryless_discover.rb +25 -0
  15. data/lib/event_store_client/adapters/grpc/cluster/secure_connection.rb +71 -0
  16. data/lib/event_store_client/adapters/grpc/command_registrar.rb +7 -7
  17. data/lib/event_store_client/adapters/grpc/commands/command.rb +63 -25
  18. data/lib/event_store_client/adapters/grpc/commands/gossip/cluster_info.rb +24 -0
  19. data/lib/event_store_client/adapters/grpc/commands/streams/append.rb +43 -68
  20. data/lib/event_store_client/adapters/grpc/commands/streams/append_multiple.rb +44 -0
  21. data/lib/event_store_client/adapters/grpc/commands/streams/delete.rb +21 -17
  22. data/lib/event_store_client/adapters/grpc/commands/streams/hard_delete.rb +39 -0
  23. data/lib/event_store_client/adapters/grpc/commands/streams/link_to.rb +7 -52
  24. data/lib/event_store_client/adapters/grpc/commands/streams/link_to_multiple.rb +44 -0
  25. data/lib/event_store_client/adapters/grpc/commands/streams/read.rb +20 -85
  26. data/lib/event_store_client/adapters/grpc/commands/streams/read_paginated.rb +174 -0
  27. data/lib/event_store_client/adapters/grpc/commands/streams/subscribe.rb +31 -106
  28. data/lib/event_store_client/adapters/grpc/connection.rb +56 -36
  29. data/lib/event_store_client/adapters/grpc/discover.rb +75 -0
  30. data/lib/event_store_client/adapters/grpc/generated/cluster_pb.rb +106 -18
  31. data/lib/event_store_client/adapters/grpc/generated/cluster_services_pb.rb +12 -12
  32. data/lib/event_store_client/adapters/grpc/generated/code_pb.rb +34 -0
  33. data/lib/event_store_client/adapters/grpc/generated/gossip_pb.rb +3 -2
  34. data/lib/event_store_client/adapters/grpc/generated/gossip_services_pb.rb +3 -3
  35. data/lib/event_store_client/adapters/grpc/generated/monitoring_pb.rb +25 -0
  36. data/lib/event_store_client/adapters/grpc/generated/monitoring_services_pb.rb +26 -0
  37. data/lib/event_store_client/adapters/grpc/generated/operations_pb.rb +2 -1
  38. data/lib/event_store_client/adapters/grpc/generated/operations_services_pb.rb +8 -7
  39. data/lib/event_store_client/adapters/grpc/generated/persistent_pb.rb +199 -38
  40. data/lib/event_store_client/adapters/grpc/generated/persistent_services_pb.rb +7 -3
  41. data/lib/event_store_client/adapters/grpc/generated/projections_pb.rb +9 -26
  42. data/lib/event_store_client/adapters/grpc/generated/projections_services_pb.rb +4 -3
  43. data/lib/event_store_client/adapters/grpc/generated/serverfeatures_pb.rb +29 -0
  44. data/lib/event_store_client/adapters/grpc/generated/serverfeatures_services_pb.rb +26 -0
  45. data/lib/event_store_client/adapters/grpc/generated/shared_pb.rb +54 -12
  46. data/lib/event_store_client/adapters/grpc/generated/status_pb.rb +23 -0
  47. data/lib/event_store_client/adapters/grpc/generated/streams_pb.rb +104 -64
  48. data/lib/event_store_client/adapters/grpc/generated/streams_services_pb.rb +3 -2
  49. data/lib/event_store_client/adapters/grpc/generated/users_services_pb.rb +2 -2
  50. data/lib/event_store_client/adapters/grpc/options/streams/read_options.rb +78 -0
  51. data/lib/event_store_client/adapters/grpc/options/streams/write_options.rb +39 -0
  52. data/lib/event_store_client/adapters/grpc/shared/event_deserializer.rb +52 -0
  53. data/lib/event_store_client/adapters/grpc/shared/options/filter_options.rb +76 -0
  54. data/lib/event_store_client/adapters/grpc/shared/options/stream_options.rb +91 -0
  55. data/lib/event_store_client/adapters/grpc/shared/streams/process_response.rb +28 -0
  56. data/lib/event_store_client/adapters/grpc/shared/streams/process_responses.rb +33 -0
  57. data/lib/event_store_client/adapters/grpc.rb +28 -12
  58. data/lib/event_store_client/configuration.rb +39 -54
  59. data/lib/event_store_client/connection/url.rb +57 -0
  60. data/lib/event_store_client/connection/url_parser.rb +144 -0
  61. data/lib/event_store_client/data_decryptor.rb +2 -9
  62. data/lib/event_store_client/deserialized_event.rb +35 -10
  63. data/lib/event_store_client/encryption_metadata.rb +0 -1
  64. data/lib/event_store_client/event.rb +4 -2
  65. data/lib/event_store_client/extensions/options_extension.rb +87 -0
  66. data/lib/event_store_client/mapper/default.rb +12 -9
  67. data/lib/event_store_client/mapper/encrypted.rb +18 -17
  68. data/lib/event_store_client/types.rb +1 -1
  69. data/lib/event_store_client/utils.rb +30 -0
  70. data/lib/event_store_client/version.rb +1 -1
  71. data/lib/event_store_client.rb +8 -7
  72. metadata +72 -81
  73. data/lib/event_store_client/adapters/grpc/Protos/cluster.proto +0 -149
  74. data/lib/event_store_client/adapters/grpc/Protos/gossip.proto +0 -44
  75. data/lib/event_store_client/adapters/grpc/Protos/operations.proto +0 -45
  76. data/lib/event_store_client/adapters/grpc/Protos/persistent.proto +0 -180
  77. data/lib/event_store_client/adapters/grpc/Protos/projections.proto +0 -174
  78. data/lib/event_store_client/adapters/grpc/Protos/shared.proto +0 -22
  79. data/lib/event_store_client/adapters/grpc/Protos/streams.proto +0 -242
  80. data/lib/event_store_client/adapters/grpc/Protos/users.proto +0 -119
  81. data/lib/event_store_client/adapters/grpc/README.md +0 -16
  82. data/lib/event_store_client/adapters/grpc/commands/persistent_subscriptions/create.rb +0 -46
  83. data/lib/event_store_client/adapters/grpc/commands/persistent_subscriptions/delete.rb +0 -34
  84. data/lib/event_store_client/adapters/grpc/commands/persistent_subscriptions/read.rb +0 -77
  85. data/lib/event_store_client/adapters/grpc/commands/persistent_subscriptions/settings_schema.rb +0 -38
  86. data/lib/event_store_client/adapters/grpc/commands/persistent_subscriptions/update.rb +0 -48
  87. data/lib/event_store_client/adapters/grpc/commands/projections/create.rb +0 -48
  88. data/lib/event_store_client/adapters/grpc/commands/projections/delete.rb +0 -34
  89. data/lib/event_store_client/adapters/grpc/commands/projections/update.rb +0 -44
  90. data/lib/event_store_client/adapters/grpc/commands/streams/read_all.rb +0 -43
  91. data/lib/event_store_client/adapters/grpc/commands/streams/tombstone.rb +0 -35
  92. data/lib/event_store_client/adapters/http/README.md +0 -16
  93. data/lib/event_store_client/adapters/http/client.rb +0 -161
  94. data/lib/event_store_client/adapters/http/commands/command.rb +0 -27
  95. data/lib/event_store_client/adapters/http/commands/persistent_subscriptions/ack.rb +0 -15
  96. data/lib/event_store_client/adapters/http/commands/persistent_subscriptions/create.rb +0 -35
  97. data/lib/event_store_client/adapters/http/commands/persistent_subscriptions/read.rb +0 -60
  98. data/lib/event_store_client/adapters/http/commands/projections/create.rb +0 -33
  99. data/lib/event_store_client/adapters/http/commands/projections/update.rb +0 -31
  100. data/lib/event_store_client/adapters/http/commands/streams/append.rb +0 -49
  101. data/lib/event_store_client/adapters/http/commands/streams/delete.rb +0 -16
  102. data/lib/event_store_client/adapters/http/commands/streams/link_to.rb +0 -49
  103. data/lib/event_store_client/adapters/http/commands/streams/read.rb +0 -52
  104. data/lib/event_store_client/adapters/http/commands/streams/tombstone.rb +0 -17
  105. data/lib/event_store_client/adapters/http/connection.rb +0 -46
  106. data/lib/event_store_client/adapters/http/request_method.rb +0 -28
  107. data/lib/event_store_client/adapters/http.rb +0 -17
  108. data/lib/event_store_client/adapters/in_memory.rb +0 -144
  109. data/lib/event_store_client/broker.rb +0 -40
  110. data/lib/event_store_client/catch_up_subscription.rb +0 -42
  111. data/lib/event_store_client/catch_up_subscriptions.rb +0 -91
  112. data/lib/event_store_client/client.rb +0 -73
  113. data/lib/event_store_client/error_handler.rb +0 -10
  114. data/lib/event_store_client/subscription.rb +0 -23
  115. data/lib/event_store_client/subscriptions.rb +0 -38
  116. data/lib/event_store_client/value_objects/read_direction.rb +0 -43
@@ -1,17 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module EventStoreClient
4
- module HTTP
5
- module Commands
6
- module Streams
7
- class Tombstone < Command
8
- def call(stream_name, options: {}) # rubocop:disable Lint/UnusedMethodArgument
9
- headers = { 'ES-HardDelete' => 'true' }
10
- connection.call(:delete, "/streams/#{stream_name}", body: {}, headers: headers)
11
- Success()
12
- end
13
- end
14
- end
15
- end
16
- end
17
- end
@@ -1,46 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'faraday'
4
- require 'event_store_client/adapters/http/request_method'
5
-
6
- module EventStoreClient
7
- module HTTP
8
- class Connection
9
- include Configuration
10
-
11
- def call(method_name, path, body: {}, headers: {})
12
- method = RequestMethod.new(method_name)
13
- connection.send(method.to_s, path) do |req|
14
- req.headers = req.headers.merge(headers)
15
- req.body = body.is_a?(String) ? body : body.to_json
16
- req.params['embed'] = 'body' if method == :get
17
- end
18
- end
19
-
20
- private
21
-
22
- def initialize(uri, options = {})
23
- @connection = set_connection(uri, options)
24
- end
25
-
26
- attr_reader :options, :connection
27
-
28
- DEFAULT_HEADERS = {
29
- 'Content-Type' => 'application/vnd.eventstore.events+json'
30
- # 'Accept' => 'application/vnd.eventstore.atom+json',
31
- }.freeze
32
-
33
- def set_connection(uri, connection_options)
34
- Faraday.new(
35
- {
36
- url: uri.to_s,
37
- headers: DEFAULT_HEADERS
38
- }.merge(connection_options)
39
- ) do |conn|
40
- conn.basic_auth(config.eventstore_user, config.eventstore_password)
41
- conn.adapter Faraday.default_adapter
42
- end
43
- end
44
- end
45
- end
46
- end
@@ -1,28 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module EventStoreClient
4
- module HTTP
5
- class RequestMethod
6
- InvalidMethodError = Class.new(StandardError)
7
- def ==(other)
8
- name == other.to_s
9
- end
10
-
11
- def to_s
12
- name
13
- end
14
-
15
- private
16
-
17
- attr_reader :name
18
-
19
- SUPPORTED_METHODS = %w[get post put delete].freeze
20
-
21
- def initialize(name)
22
- raise InvalidMethodError unless SUPPORTED_METHODS.include?(name.to_s)
23
-
24
- @name = name.to_s
25
- end
26
- end
27
- end
28
- end
@@ -1,17 +0,0 @@
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
- require 'event_store_client/adapters/http/commands/projections/update'
10
-
11
- require 'event_store_client/adapters/http/commands/streams/append'
12
- require 'event_store_client/adapters/http/commands/streams/delete'
13
- require 'event_store_client/adapters/http/commands/streams/link_to'
14
- require 'event_store_client/adapters/http/commands/streams/read'
15
- require 'event_store_client/adapters/http/commands/streams/tombstone'
16
-
17
- require 'event_store_client/adapters/http/client'
@@ -1,144 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'dry/monads'
4
-
5
- module EventStoreClient
6
- class InMemory
7
- Response = Struct.new(:body, :status) do
8
- def success?
9
- status == 200
10
- end
11
- end
12
-
13
- attr_reader :event_store
14
-
15
- def append_to_stream(stream_name, events, options: {}) # rubocop:disable Lint/UnusedMethodArgument,Metrics/LineLength
16
- event_store[stream_name] = [] unless event_store.key?(stream_name)
17
- [events].flatten.each do |event|
18
- event_store[stream_name].unshift(
19
- 'eventId' => event.id,
20
- 'data' => event.data,
21
- 'eventType' => event.type,
22
- 'metaData' => event.metadata,
23
- 'positionEventNumber' => event_store[stream_name].length
24
- )
25
- end
26
- Dry::Monads::Success(events)
27
- end
28
-
29
- def delete_stream(stream_name, options: {}) # rubocop:disable Lint/UnusedMethodArgument
30
- event_store.delete(stream_name)
31
- end
32
-
33
- def tombstone_stream(stream_name, options: {}) # rubocop:disable Lint/UnusedMethodArgument
34
- event_store.delete(stream_name)
35
- end
36
-
37
- def read(stream_name, options: {})
38
- start = options[:start] == 'head' ? options[:start] : options[:start].to_i
39
- direction = options[:direction] || 'forward'
40
- response =
41
- if %w[forward forwards].include?(direction)
42
- read_stream_forward(stream_name, start: start)
43
- else
44
- read_stream_backward(stream_name, start: start)
45
- end
46
-
47
- res = Response.new(response.to_json, 200)
48
-
49
- return [] if res.body.nil? || res.body.empty?
50
- skip_decryption = options[:skip_decryption] || false
51
- events = JSON.parse(res.body)['entries'].map do |entry|
52
- deserialize_event(entry, skip_decryption: skip_decryption)
53
- end.reverse
54
- Dry::Monads::Success(events)
55
- end
56
-
57
- def read_all_from_stream(stream_name, options: {})
58
- read(stream_name, options: options)
59
- end
60
-
61
- def subscribe_to_stream(subscription, **)
62
- # TODO: implement method body
63
- end
64
-
65
- def link_to(stream_name, events, **)
66
- append_to_stream(stream_name, events)
67
- end
68
-
69
- def listen(subscription, options: {})
70
- # TODO: implement method body
71
- end
72
-
73
- private
74
-
75
- attr_reader :per_page, :mapper
76
-
77
- def initialize(mapper:, per_page: 20)
78
- @per_page = per_page
79
- @mapper = mapper
80
- @event_store = {}
81
- end
82
-
83
- def read_stream_backward(stream_name, start: 0)
84
- response = {
85
- 'entries' => [],
86
- 'links' => []
87
- }
88
- return response unless event_store.key?(stream_name)
89
-
90
- start = start == 'head' ? event_store[stream_name].length - 1 : start
91
- last_index = (start - per_page)
92
- response['entries'] = event_store[stream_name].select do |event|
93
- event['positionEventNumber'] > last_index &&
94
- event['positionEventNumber'] <= start
95
- end
96
- response['links'] = links(stream_name, last_index, 'next', response['entries'], per_page)
97
-
98
- response
99
- end
100
-
101
- def read_stream_forward(stream_name, start: 0)
102
- response = {
103
- 'entries' => [],
104
- 'links' => []
105
- }
106
-
107
- return response unless event_store.key?(stream_name)
108
-
109
- last_index = start + per_page
110
- response['entries'] = event_store[stream_name].select do |event|
111
- event['positionEventNumber'] < last_index &&
112
- event['positionEventNumber'] >= start
113
- end
114
- response['links'] =
115
- links(stream_name, last_index, 'previous', response['entries'], per_page)
116
-
117
- response
118
- end
119
-
120
- def links(stream_name, batch_size, direction, entries, count)
121
- if entries.empty? || batch_size.negative?
122
- []
123
- else
124
- [{
125
- 'uri' =>
126
- "/streams/#{stream_name}/#{batch_size}/#{direction}/#{count}",
127
- 'relation' => direction
128
- }]
129
- end
130
- end
131
-
132
- def deserialize_event(entry, skip_decryption: false)
133
- event = EventStoreClient::Event.new(
134
- id: entry['eventId'],
135
- title: entry['title'],
136
- type: entry['eventType'],
137
- data: entry['data'].to_json || '{}',
138
- metadata: entry['isMetaData'] ? entry['metaData'] : '{}'
139
- )
140
-
141
- mapper.deserialize(event, skip_decryption: skip_decryption)
142
- end
143
- end
144
- end
@@ -1,40 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module EventStoreClient
4
- class Broker
5
- include Configuration
6
-
7
- # Distributes known subscriptions to multiple threads
8
- # @param [EventStoreClient::Subscriptions]
9
- # @param wait [Boolean] (Optional) Controls if broker should block
10
- # main app process (useful for debugging)
11
- #
12
- def call(subscriptions, wait: false)
13
- Signal.trap('TERM') do
14
- Thread.new { logger&.info('Broker: TERM Signal has been received') }
15
- threads.each do |thread|
16
- thread.thread_variable_set(:terminate, true)
17
- end
18
- Thread.new { logger&.info('Broker: Terminate variable for subscription threads set') }
19
- end
20
-
21
- subscriptions.each do |subscription|
22
- threads << Thread.new do
23
- subscriptions.listen(subscription)
24
- end
25
- end
26
- threads.each(&:join) if wait
27
- end
28
-
29
- private
30
-
31
- attr_reader :connection, :logger
32
- attr_accessor :threads
33
-
34
- def initialize(connection:)
35
- @connection = connection
36
- @threads = []
37
- @logger = EventStoreClient.config.logger
38
- end
39
- end
40
- end
@@ -1,42 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module EventStoreClient
4
- class CatchUpSubscription
5
- attr_reader :subscriber, :filter
6
- attr_accessor :position
7
-
8
- def options
9
- {
10
- filter: @filter,
11
- without_system_events: @without_system_events,
12
- all: {
13
- position: {
14
- commit_position: position[:commit_position],
15
- prepare_position: position[:prepare_position]
16
- }
17
- }
18
- }.compact
19
- end
20
-
21
- def name
22
- self.class.name(subscriber)
23
- end
24
-
25
- def self.name(subscriber)
26
- subscriber.class.to_s
27
- end
28
-
29
- private
30
-
31
- def initialize(subscriber, filter: nil, position: nil)
32
- @filter = filter
33
- @subscriber = subscriber
34
- @position = position
35
- @position ||= {
36
- commit_position: 0,
37
- prepare_position: 0
38
- }
39
- @without_system_events = true
40
- end
41
- end
42
- end
@@ -1,91 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module EventStoreClient
4
- class CatchUpSubscriptions
5
- FILTER_DEFAULT_MAX = 32
6
- FILTER_DEFAULT_CHECKPOINT_INTERVAL_MULTIPLIER = 10000
7
-
8
- include Configuration
9
-
10
- def create_or_load(subscriber, filter: {})
11
- filter_options = prepare_filter_options(filter)
12
- position = subscription_store.load_all_position(CatchUpSubscription.name(subscriber))
13
-
14
- subscription = CatchUpSubscription.new(subscriber, position: position, filter: filter_options)
15
- subscription_store.add(subscription) unless position
16
-
17
- subscriptions << subscription unless @subscriptions.find { |s| s.name == subscription.name }
18
- subscription
19
- end
20
-
21
- def each
22
- subscriptions.each { |subscription| yield(subscription) }
23
- end
24
-
25
- def listen(subscription)
26
- connection.subscribe(subscription.options) do |event_data|
27
- next if recorded_event?(event_data)
28
- next if confirmation?(event_data)
29
-
30
- new_position = event_data[0]
31
- event = event_data[1]
32
-
33
- old_position = subscription.position
34
- subscription.position = new_position
35
- subscription_store.update_position(subscription)
36
- next unless event
37
-
38
- subscription.subscriber.call(event)
39
-
40
- if Thread.current.thread_variable_get(:terminate)
41
- msg =
42
- "CatchUpSubscriptions: Terminating subscription listener for #{subscription.subscriber}"
43
- logger&.info(msg)
44
- break
45
- end
46
- rescue StandardError => e
47
- subscription.position = old_position
48
- subscription_store.update_position(subscription)
49
- config.error_handler&.call(e)
50
- end
51
- end
52
-
53
- def clean_unused
54
- subscription_store.clean_unused(subscriptions.map(&:name))
55
- end
56
-
57
- def reset
58
- subscription_store.reset(subscriptions)
59
- end
60
-
61
- private
62
-
63
- attr_reader :connection, :subscriptions, :subscription_store, :logger
64
-
65
- def initialize(connection:, subscription_store:)
66
- @connection = connection
67
- @subscription_store = subscription_store
68
- @subscriptions = []
69
- @logger = EventStoreClient.config.logger
70
- end
71
-
72
- def confirmation?(event_data)
73
- event_data.is_a? EventStore::Client::Streams::ReadResp::SubscriptionConfirmation
74
- end
75
-
76
- def recorded_event?(event_data)
77
- event_data.is_a? EventStore::Client::Streams::ReadResp::ReadEvent::RecordedEvent
78
- end
79
-
80
- def prepare_filter_options(filter)
81
- return if filter.nil? || filter.empty?
82
-
83
- {
84
- event_type: filter[:event_type],
85
- stream_identifier: filter[:stream_identifier],
86
- max: FILTER_DEFAULT_MAX,
87
- checkpointIntervalMultiplier: FILTER_DEFAULT_CHECKPOINT_INTERVAL_MULTIPLIER
88
- }.compact
89
- end
90
- end
91
- end
@@ -1,73 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'dry-struct'
4
-
5
- module EventStoreClient
6
- class Client
7
- include Configuration
8
-
9
- NoCallMethodOnSubscriber = Class.new(StandardError)
10
- WrongExpectedEventVersion = Class.new(StandardError)
11
-
12
- def publish(stream:, events:, options: {})
13
- res = connection.append_to_stream(stream, events, options: options)
14
- raise WrongExpectedEventVersion.new(res.failure) if res.failure?
15
- res
16
- end
17
-
18
- def read(stream, options: {})
19
- if options[:all]
20
- connection.read_all_from_stream(stream, options: options)
21
- else
22
- connection.read(stream, options: options)
23
- end
24
- end
25
-
26
- def subscribe(subscriber, to: [], options: {})
27
- raise NoCallMethodOnSubscriber unless subscriber.respond_to?(:call)
28
- @subscriptions.create(subscriber, to, options: options)
29
- end
30
-
31
- def subscribe_to_all(subscriber, filter=nil)
32
- raise NoCallMethodOnSubscriber unless subscriber.respond_to?(:call)
33
-
34
- @subscriptions.create_or_load(subscriber, filter: filter)
35
- end
36
-
37
- def reset_subscriptions
38
- return unless @subscriptions.respond_to?(:reset)
39
-
40
- @subscriptions.reset
41
- end
42
-
43
- def listen(wait: false)
44
- broker.call(@subscriptions, wait: wait)
45
- end
46
-
47
- # rubocop:disable Metrics/CyclomaticComplexity
48
- def link_to(stream:, events:, options: {})
49
- raise ArgumentError if !stream || stream == ''
50
- raise ArgumentError if events.nil? || (events.is_a?(Array) && events.empty?)
51
- res = connection.link_to(stream, events, options: options)
52
- raise WrongExpectedEventVersion.new(e.message) if res.failure?
53
-
54
- res.success?
55
- end
56
- # rubocop:enable Metrics/CyclomaticComplexity
57
-
58
- attr_accessor :connection
59
-
60
- private
61
-
62
- attr_reader :subscriptions, :broker, :error_handler
63
-
64
- def initialize
65
- @threads = []
66
- @connection = EventStoreClient.adapter
67
- @error_handler = config.error_handler
68
- @broker = Broker.new(connection: connection)
69
- @subscriptions = config.subscriptions_repo
70
- @subscriptions ||= Subscriptions.new(connection: connection, service: config.service_name)
71
- end
72
- end
73
- end
@@ -1,10 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module EventStoreClient
4
- class ErrorHandler
5
- def call(error)
6
- puts error
7
- puts error.backtrace
8
- end
9
- end
10
- end
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module EventStoreClient
4
- class Subscription
5
- attr_reader :stream, :subscriber, :name, :observed_streams
6
-
7
- private
8
-
9
- def initialize(subscriber, service:, event_types:)
10
- subscriber_class =
11
- if subscriber.class.name == 'Class'
12
- subscriber.name
13
- else
14
- subscriber.class.name
15
- end
16
- @name = subscriber_class.to_s
17
- @name = "#{service}-" + @name if service != ''
18
- @subscriber = subscriber
19
- @stream = name
20
- @observed_streams = event_types.reduce([]) { |r, type| r << "$et-#{type}" }
21
- end
22
- end
23
- end
@@ -1,38 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module EventStoreClient
4
- class Subscriptions
5
- def create(subscriber, event_types, options: {})
6
- subscription = Subscription.new(subscriber, event_types: event_types, service: service)
7
-
8
- unless @subscriptions.detect { |sub| sub.name == subscription.name }
9
- connection.subscribe_to_stream(subscription, options: options)
10
- subscriptions << subscription
11
- end
12
-
13
- subscription
14
- end
15
-
16
- def each
17
- subscriptions.each do |subscription|
18
- yield(subscription)
19
- end
20
- end
21
-
22
- def listen(subscription)
23
- connection.listen(subscription, options: { interval: 1, count: 10 }) do |event|
24
- subscription.subscriber.call(event)
25
- end
26
- end
27
-
28
- private
29
-
30
- attr_reader :connection, :subscriptions, :service
31
-
32
- def initialize(connection:, service: 'default')
33
- @connection = connection
34
- @service = service
35
- @subscriptions = []
36
- end
37
- end
38
- end
@@ -1,43 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module EventStoreClient
4
- class ReadDirection
5
- Invalid = Class.new(StandardError)
6
-
7
- def to_sym
8
- value
9
- end
10
-
11
- def to_s
12
- value.to_s
13
- end
14
-
15
- private
16
-
17
- attr_reader :value
18
-
19
- def initialize(str)
20
- schema = Schema.new(direction: str)
21
-
22
- unless %w[forwards backwards].include?(schema.direction)
23
- raise Invalid.new('Allowed values: "forwards", "backwards"')
24
- end
25
-
26
- @value = schema.direction.capitalize.to_sym
27
- end
28
-
29
-
30
- class Schema < Dry::Struct
31
- schema schema.strict
32
-
33
- # resolve default types on nil
34
- transform_types do |type|
35
- type.constructor do |value|
36
- value.is_a?(String) ? value.downcase : value
37
- end
38
- end
39
-
40
- attribute :direction, Dry::Types['string']
41
- end
42
- end
43
- end