event_store_client 1.4.9 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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 +74 -83
  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 -92
  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,92 +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
- logger&.info("Subscription #{subscription.name} received event #{event_data.inspect}")
39
- subscription.subscriber.call(event)
40
-
41
- if Thread.current.thread_variable_get(:terminate)
42
- msg =
43
- "CatchUpSubscriptions: Terminating subscription listener for #{subscription.subscriber}"
44
- logger&.info(msg)
45
- break
46
- end
47
- rescue StandardError => e
48
- subscription.position = old_position
49
- subscription_store.update_position(subscription)
50
- config.error_handler&.call(e)
51
- end
52
- end
53
-
54
- def clean_unused
55
- subscription_store.clean_unused(subscriptions.map(&:name))
56
- end
57
-
58
- def reset
59
- subscription_store.reset(subscriptions)
60
- end
61
-
62
- private
63
-
64
- attr_reader :connection, :subscriptions, :subscription_store, :logger
65
-
66
- def initialize(connection:, subscription_store:)
67
- @connection = connection
68
- @subscription_store = subscription_store
69
- @subscriptions = []
70
- @logger = EventStoreClient.config.logger
71
- end
72
-
73
- def confirmation?(event_data)
74
- event_data.is_a? EventStore::Client::Streams::ReadResp::SubscriptionConfirmation
75
- end
76
-
77
- def recorded_event?(event_data)
78
- event_data.is_a? EventStore::Client::Streams::ReadResp::ReadEvent::RecordedEvent
79
- end
80
-
81
- def prepare_filter_options(filter)
82
- return if filter.nil? || filter.empty?
83
-
84
- {
85
- event_type: filter[:event_type],
86
- stream_identifier: filter[:stream_identifier],
87
- max: FILTER_DEFAULT_MAX,
88
- checkpointIntervalMultiplier: FILTER_DEFAULT_CHECKPOINT_INTERVAL_MULTIPLIER
89
- }.compact
90
- end
91
- end
92
- 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