event_store_client 2.3.0 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/docs/appending_events.md +15 -19
- data/docs/catch_up_subscriptions.md +34 -67
- data/docs/configuration.md +0 -2
- data/docs/deleting_streams.md +13 -1
- data/docs/encrypting_events.md +1 -3
- data/docs/linking_events.md +19 -23
- data/docs/reading_events.md +32 -59
- data/lib/event_store_client/adapters/grpc/client.rb +13 -9
- data/lib/event_store_client/adapters/grpc/commands/command.rb +0 -2
- data/lib/event_store_client/adapters/grpc/commands/gossip/cluster_info.rb +1 -1
- data/lib/event_store_client/adapters/grpc/commands/streams/append.rb +11 -5
- data/lib/event_store_client/adapters/grpc/commands/streams/append_multiple.rb +2 -6
- data/lib/event_store_client/adapters/grpc/commands/streams/delete.rb +7 -5
- data/lib/event_store_client/adapters/grpc/commands/streams/hard_delete.rb +7 -5
- data/lib/event_store_client/adapters/grpc/commands/streams/link_to_multiple.rb +5 -10
- data/lib/event_store_client/adapters/grpc/commands/streams/read_paginated.rb +5 -8
- data/lib/event_store_client/adapters/grpc/commands/streams/subscribe.rb +3 -5
- data/lib/event_store_client/adapters/grpc/shared/streams/process_response.rb +6 -8
- data/lib/event_store_client/adapters/grpc/shared/streams/process_responses.rb +11 -13
- data/lib/event_store_client/adapters/grpc.rb +0 -1
- data/lib/event_store_client/deserialized_event.rb +21 -3
- data/lib/event_store_client/errors.rb +95 -0
- data/lib/event_store_client/mapper/default.rb +1 -1
- data/lib/event_store_client/mapper/encrypted.rb +2 -2
- data/lib/event_store_client/serializer/event_deserializer.rb +4 -2
- data/lib/event_store_client/serializer/event_serializer.rb +41 -17
- data/lib/event_store_client/version.rb +1 -1
- data/lib/event_store_client.rb +3 -1
- metadata +19 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b9e8e4782cfd1b70376d4531ae7452d721e7af3078f23a2c6d345e654fed5d1d
|
4
|
+
data.tar.gz: b7de94d902e0ff87747b5f58f3740c580473514638901ed666fc07d98fc47b7f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 03015ede0f74da75119247433579079ee2d71a9ab9f347d23a2f52915c5bc3441574f098a9509843325c5dd568c95c6c77681a7aaa81c364b90397e95181f929
|
7
|
+
data.tar.gz: 10f9a45843bc18f0e2e35294b9dee0c7e0c1f9a33e1e4c41881f407c82ee5df4714aaef6f6d4879b271f7ef6ea032e7e765d0f97ff23b99046a68ff2b230bffb
|
data/docs/appending_events.md
CHANGED
@@ -14,11 +14,11 @@ event = SomethingHappened.new(
|
|
14
14
|
id: SecureRandom.uuid, type: 'some-event', data: { user_id: SecureRandom.uuid, title: "Something happened" }
|
15
15
|
)
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
17
|
+
begin
|
18
|
+
EventStoreClient.client.append_to_stream('some-stream', event)
|
19
|
+
# => EventStore::Client::Streams::AppendResp
|
20
|
+
rescue EventStoreClient::WrongExpectedVersionError => e
|
21
|
+
puts e.message
|
22
22
|
end
|
23
23
|
```
|
24
24
|
|
@@ -37,15 +37,13 @@ event2 = SomethingHappened.new(
|
|
37
37
|
id: SecureRandom.uuid, type: 'some-event', data: { user_id: SecureRandom.uuid, title: "Something happened 2" }
|
38
38
|
)
|
39
39
|
|
40
|
-
|
41
|
-
|
42
|
-
#
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
end
|
40
|
+
begin
|
41
|
+
EventStoreClient.client.append_to_stream('some-stream', [event1, event2])
|
42
|
+
# => Array<EventStore::Client::Streams::AppendResp>
|
43
|
+
rescue EventStoreClient::WrongExpectedVersionError => e
|
44
|
+
puts e.message
|
45
|
+
puts e.caused_by # event which caused the error
|
47
46
|
end
|
48
|
-
|
49
47
|
```
|
50
48
|
|
51
49
|
## Working with EventStoreClient::DeserializedEvent
|
@@ -62,8 +60,8 @@ EventStoreClient::DeserializedEvent.new(
|
|
62
60
|
type: 'some-event-name',
|
63
61
|
# Event data. Optional. Will default to `{}` (empty hash) if omitted
|
64
62
|
data: { foo: :bar },
|
65
|
-
# Optional.
|
66
|
-
|
63
|
+
# Optional. You can put here any value which is not supposed to be present in data.
|
64
|
+
custom_metadata: {}
|
67
65
|
)
|
68
66
|
```
|
69
67
|
|
@@ -128,13 +126,11 @@ event1 = SomethingHappened.new(
|
|
128
126
|
event2 = SomethingHappened.new(
|
129
127
|
type: 'some-event', data: {}
|
130
128
|
)
|
131
|
-
|
132
|
-
type: 'some-event', data: {}
|
133
|
-
)
|
129
|
+
|
134
130
|
# Pre-populate stream with some event
|
135
131
|
EventStoreClient.client.append_to_stream(stream_name, event1)
|
136
132
|
# Get the revision number of latest event
|
137
|
-
revision = EventStoreClient.client.read(stream_name).
|
133
|
+
revision = EventStoreClient.client.read(stream_name).last.stream_revision
|
138
134
|
# Expected revision matches => will succeed
|
139
135
|
EventStoreClient.client.append_to_stream(stream_name, event2, options: { expected_revision: revision })
|
140
136
|
# Will fail with revisions mismatch error
|
@@ -17,13 +17,8 @@ When you need to process all the events in the store, including historical event
|
|
17
17
|
The most simple stream subscription looks like the following:
|
18
18
|
|
19
19
|
```ruby
|
20
|
-
handler = proc do |
|
21
|
-
|
22
|
-
event = result.success # retrieve a result
|
23
|
-
# ... do something with event
|
24
|
-
else # result.failure?
|
25
|
-
puts result.failure # prints error
|
26
|
-
end
|
20
|
+
handler = proc do |event|
|
21
|
+
p event
|
27
22
|
end
|
28
23
|
EventStoreClient.client.subscribe_to_stream('some-stream', handler: handler)
|
29
24
|
```
|
@@ -32,13 +27,8 @@ The provided handler will be called for every event in the stream. You may provi
|
|
32
27
|
|
33
28
|
```ruby
|
34
29
|
class SomeStreamHandler
|
35
|
-
def call(
|
36
|
-
|
37
|
-
event = result.success # retrieve a result
|
38
|
-
# ... do something with event
|
39
|
-
else # result.failure?
|
40
|
-
puts result.failure # prints error
|
41
|
-
end
|
30
|
+
def call(event)
|
31
|
+
p event
|
42
32
|
end
|
43
33
|
end
|
44
34
|
EventStoreClient.client.subscribe_to_stream('some-stream', handler: SomeStreamHandler.new)
|
@@ -49,13 +39,8 @@ EventStoreClient.client.subscribe_to_stream('some-stream', handler: SomeStreamHa
|
|
49
39
|
Subscribing to `$all` is much the same as subscribing to a single stream. The handler will be called for every event appended after the starting position.
|
50
40
|
|
51
41
|
```ruby
|
52
|
-
handler = proc do |
|
53
|
-
|
54
|
-
event = result.success # retrieve a result
|
55
|
-
# ... do something with event
|
56
|
-
else # result.failure?
|
57
|
-
puts result.failure # prints error
|
58
|
-
end
|
42
|
+
handler = proc do |event|
|
43
|
+
p event
|
59
44
|
end
|
60
45
|
EventStoreClient.client.subscribe_to_all(handler: handler)
|
61
46
|
```
|
@@ -75,7 +60,7 @@ To subscribe to a stream from a specific position, you need to provide a _stream
|
|
75
60
|
The following subscribes to the stream `some-stream` at position `20`, this means that events `21` and onward will be handled:
|
76
61
|
|
77
62
|
```ruby
|
78
|
-
EventStoreClient.client.subscribe_to_stream('some-stream', handler: proc { |
|
63
|
+
EventStoreClient.client.subscribe_to_stream('some-stream', handler: proc { |event| }, options: { from_revision: 20 })
|
79
64
|
```
|
80
65
|
|
81
66
|
### Subscribing to $all
|
@@ -85,7 +70,7 @@ Subscribing to the `$all` stream is much like subscribing to a regular stream. T
|
|
85
70
|
The following `$all` subscription will subscribe from the event after the one at commit position `1056` and prepare position `1056`:
|
86
71
|
|
87
72
|
```ruby
|
88
|
-
EventStoreClient.client.subscribe_to_all(handler: proc { |
|
73
|
+
EventStoreClient.client.subscribe_to_all(handler: proc { |event| }, options: { from_position: { commit_position: 1056, prepare_position: 1056 } })
|
89
74
|
```
|
90
75
|
|
91
76
|
Please note that the given position needs to be a legitimate position in the `$all` stream.
|
@@ -95,13 +80,13 @@ Please note that the given position needs to be a legitimate position in the `$a
|
|
95
80
|
You can subscribe to a stream to get live updates by subscribing to the end of the stream:
|
96
81
|
|
97
82
|
```ruby
|
98
|
-
EventStoreClient.client.subscribe_to_stream('some-stream', handler: proc { |
|
83
|
+
EventStoreClient.client.subscribe_to_stream('some-stream', handler: proc { |event| }, options: { from_revision: :end })
|
99
84
|
```
|
100
85
|
|
101
86
|
And the same works with `$all` :
|
102
87
|
|
103
88
|
```ruby
|
104
|
-
EventStoreClient.client.subscribe_to_all(handler: proc { |
|
89
|
+
EventStoreClient.client.subscribe_to_all(handler: proc { |event| }, options: { from_position: :end })
|
105
90
|
```
|
106
91
|
|
107
92
|
This won't read through the history of the stream, but will rather notify the handler when a new event appears in the respective stream.
|
@@ -115,7 +100,7 @@ Link-to events point to events in other streams in EventStoreDB. These are gener
|
|
115
100
|
When reading a stream you can specify whether to resolve link-to's or not. By default, link-to events are not resolved. You can change this behaviour by setting the `resolve_link_tos` option to `true`:
|
116
101
|
|
117
102
|
```ruby
|
118
|
-
EventStoreClient.client.subscribe_to_stream('$et-myEventType', handler: proc { |
|
103
|
+
EventStoreClient.client.subscribe_to_stream('$et-myEventType', handler: proc { |event| }, options: { resolve_link_tos: true })
|
119
104
|
```
|
120
105
|
|
121
106
|
## Handling subscription drops
|
@@ -124,14 +109,9 @@ An application, which hosts the subscription, can go offline for a period of tim
|
|
124
109
|
|
125
110
|
```ruby
|
126
111
|
checkpoint = :start
|
127
|
-
handler = proc do |
|
128
|
-
|
129
|
-
|
130
|
-
handle_event(event)
|
131
|
-
checkpoint = event.stream_revision
|
132
|
-
else
|
133
|
-
# do something in case of error
|
134
|
-
end
|
112
|
+
handler = proc do |event|
|
113
|
+
handle_event(event)
|
114
|
+
checkpoint = event.stream_revision
|
135
115
|
end
|
136
116
|
|
137
117
|
EventStoreClient.client.subscribe_to_stream('some-stream', handler: handler, options: { from_revision: checkpoint })
|
@@ -141,14 +121,9 @@ When subscribed to `$all` you want to keep the position of the event in the `$al
|
|
141
121
|
|
142
122
|
```ruby
|
143
123
|
checkpoint = :start
|
144
|
-
handler = proc do |
|
145
|
-
|
146
|
-
|
147
|
-
handle_event(event)
|
148
|
-
checkpoint = { prepare_position: event.prepare_position, commit_position: event.commit_position }
|
149
|
-
else
|
150
|
-
# do something in case of error
|
151
|
-
end
|
124
|
+
handler = proc do |event|
|
125
|
+
handle_event(event)
|
126
|
+
checkpoint = { prepare_position: event.prepare_position, commit_position: event.commit_position }
|
152
127
|
end
|
153
128
|
|
154
129
|
EventStoreClient.client.subscribe_to_all(handler: handler, options: { from_position: checkpoint })
|
@@ -156,28 +131,20 @@ EventStoreClient.client.subscribe_to_all(handler: handler, options: { from_posit
|
|
156
131
|
|
157
132
|
### Checkpoints and other responses
|
158
133
|
|
159
|
-
By default `event_store_client` will skip such EventStore DB responses as checkpoints, confirmations, etc. If you would like to handle them in the subscription handler, you can provide the`skip_deserialization` keyword argument, and then handle deserialization by yourself:
|
134
|
+
By default `event_store_client` will skip such EventStore DB responses as checkpoints, confirmations, etc. If you would like to handle them in the subscription handler, you can provide the `skip_deserialization` keyword argument, and then handle deserialization by yourself:
|
160
135
|
|
161
136
|
```ruby
|
162
137
|
checkpoint = :start
|
163
|
-
handler = proc do |
|
164
|
-
if
|
165
|
-
|
166
|
-
if response.checkpoint
|
167
|
-
handle_checkpoint(response.checkpoint)
|
168
|
-
else
|
169
|
-
result = EventStoreClient::GRPC::Shared::Streams::ProcessResponse.new.call(
|
170
|
-
response,
|
171
|
-
false,
|
172
|
-
false
|
173
|
-
)
|
174
|
-
if result&.success?
|
175
|
-
event = result.success
|
176
|
-
handle_event(event)
|
177
|
-
end
|
178
|
-
end
|
138
|
+
handler = proc do |raw_response|
|
139
|
+
if raw_response.checkpoint
|
140
|
+
handle_checkpoint(raw_response.checkpoint)
|
179
141
|
else
|
180
|
-
|
142
|
+
event = EventStoreClient::GRPC::Shared::Streams::ProcessResponse.new(config: EventStoreClient.config).call(
|
143
|
+
raw_response,
|
144
|
+
false,
|
145
|
+
false
|
146
|
+
)
|
147
|
+
handle_event(event) if event
|
181
148
|
end
|
182
149
|
end
|
183
150
|
|
@@ -191,7 +158,7 @@ The user creating a subscription must have read access to the stream it's subscr
|
|
191
158
|
The code below shows how you can provide user credentials for a subscription. When you specify subscription credentials explicitly, it will override the default credentials set for the client. If you don't specify any credentials, the client will use the credentials specified for the client, if you specified those.
|
192
159
|
|
193
160
|
```ruby
|
194
|
-
EventStoreClient.client.subscribe_to_stream('some-stream', handler: proc { |
|
161
|
+
EventStoreClient.client.subscribe_to_stream('some-stream', handler: proc { |event| }, credentials: { username: 'admin', password: 'changeit' })
|
195
162
|
```
|
196
163
|
|
197
164
|
## Server-side filtering
|
@@ -203,7 +170,7 @@ You can filter by event type or stream name using either a regular expression or
|
|
203
170
|
A simple stream prefix filter looks like this:
|
204
171
|
|
205
172
|
```ruby
|
206
|
-
EventStoreClient.client.subscribe_to_all(handler: proc { |
|
173
|
+
EventStoreClient.client.subscribe_to_all(handler: proc { |event| }, options: { filter: { stream_identifier: { prefix: ['test-', 'other-'] } } })
|
207
174
|
```
|
208
175
|
|
209
176
|
### Filtering out system events
|
@@ -211,7 +178,7 @@ EventStoreClient.client.subscribe_to_all(handler: proc { |res| }, options: { fil
|
|
211
178
|
There are a number of events in EventStoreDB called system events. These are prefixed with a `$` and under most circumstances you won't care about these. They can be filtered out by event type.
|
212
179
|
|
213
180
|
```ruby
|
214
|
-
EventStoreClient.client.subscribe_to_all(handler: proc { |
|
181
|
+
EventStoreClient.client.subscribe_to_all(handler: proc { |event| }, options: { filter: { event_type: { regex: /^[^\$].*/.to_s } } })
|
215
182
|
```
|
216
183
|
|
217
184
|
### Filtering by event type
|
@@ -223,7 +190,7 @@ If you only want to subscribe to events of a given type there are two options. Y
|
|
223
190
|
This will only subscribe to events with a type that begin with `customer-`:
|
224
191
|
|
225
192
|
```ruby
|
226
|
-
EventStoreClient.client.subscribe_to_all(handler: proc { |
|
193
|
+
EventStoreClient.client.subscribe_to_all(handler: proc { |event| }, options: { filter: { event_type: { prefix: ['customer-'] } } })
|
227
194
|
```
|
228
195
|
|
229
196
|
#### Filtering by regular expression
|
@@ -231,7 +198,7 @@ EventStoreClient.client.subscribe_to_all(handler: proc { |res| }, options: { fil
|
|
231
198
|
If you want to subscribe to multiple event types then it might be better to provide a regular expression. This will subscribe to any event that begins with `user` or `company`:
|
232
199
|
|
233
200
|
```ruby
|
234
|
-
EventStoreClient.client.subscribe_to_all(handler: proc { |
|
201
|
+
EventStoreClient.client.subscribe_to_all(handler: proc { |event| }, options: { filter: { event_type: { regex: '^user|^company' } } })
|
235
202
|
```
|
236
203
|
|
237
204
|
### Filtering by stream name
|
@@ -243,7 +210,7 @@ If you only want to subscribe to a stream with a given name there are two option
|
|
243
210
|
This will only subscribe to all streams with a name that begins with `user-`:
|
244
211
|
|
245
212
|
```ruby
|
246
|
-
EventStoreClient.client.subscribe_to_all(handler: proc { |
|
213
|
+
EventStoreClient.client.subscribe_to_all(handler: proc { |event| }, options: { filter: { stream_identifier: { prefix: ['user-'] } } })
|
247
214
|
```
|
248
215
|
|
249
216
|
#### Filtering by regular expression
|
@@ -251,5 +218,5 @@ EventStoreClient.client.subscribe_to_all(handler: proc { |res| }, options: { fil
|
|
251
218
|
If you want to subscribe to multiple streams then it might be better to provide a regular expression.
|
252
219
|
|
253
220
|
```ruby
|
254
|
-
EventStoreClient.client.subscribe_to_all(handler: proc { |
|
221
|
+
EventStoreClient.client.subscribe_to_all(handler: proc { |event| }, options: { filter: { stream_identifier: { regex: '^account|^savings' } } })
|
255
222
|
```
|
data/docs/configuration.md
CHANGED
data/docs/deleting_streams.md
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
|
5
5
|
## Soft deleting streams
|
6
6
|
|
7
|
-
When you read a soft deleted stream, the read
|
7
|
+
When you read a soft deleted stream, the read raises `EventStoreClient::StreamNotFoundError` error. After deleting the stream, you are able to append to it again, continuing from where it left off.
|
8
8
|
|
9
9
|
```ruby
|
10
10
|
EventStoreClient.client.delete_stream('some-stream')
|
@@ -25,3 +25,15 @@ You can provide user credentials to be used to delete the stream as follows. Thi
|
|
25
25
|
```ruby
|
26
26
|
EventStoreClient.client.delete_stream('some-stream', credentials: { username: 'admin', password: 'changeit' })
|
27
27
|
```
|
28
|
+
|
29
|
+
## Possible errors during stream deletion
|
30
|
+
|
31
|
+
If you try to delete non-existing stream, or if you provided `:expected_revision` option with a value which doesn't match current stream's state - `EventStoreClient::StreamDeletionError` error will be raised:
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
begin
|
35
|
+
EventStoreClient.client.delete_stream('non-existing-stream')
|
36
|
+
rescue => e
|
37
|
+
puts e.message
|
38
|
+
end
|
39
|
+
```
|
data/docs/encrypting_events.md
CHANGED
@@ -6,10 +6,8 @@ To encrypt/decrypt events payload, you can use an encrypted mapper.
|
|
6
6
|
|
7
7
|
|
8
8
|
```ruby
|
9
|
-
mapper = EventStoreClient::Mapper::Encrypted.new(key_repository)
|
10
|
-
|
11
9
|
EventStoreClient.configure do |config|
|
12
|
-
config.mapper =
|
10
|
+
config.mapper = EventStoreClient::Mapper::Encrypted.new(key_repository, config: config)
|
13
11
|
end
|
14
12
|
```
|
15
13
|
|
data/docs/linking_events.md
CHANGED
@@ -18,18 +18,16 @@ stream_name_1 = 'some-stream-1'
|
|
18
18
|
stream_name_2 = 'some-stream-2'
|
19
19
|
EventStoreClient.client.append_to_stream(stream_name_1, event)
|
20
20
|
# Get persisted event
|
21
|
-
event = EventStoreClient.client.read(stream_name_1).
|
21
|
+
event = EventStoreClient.client.read(stream_name_1).first
|
22
22
|
# Link event from first stream into second stream
|
23
|
-
|
24
|
-
|
25
|
-
else # event was not linked, result.failure? => true
|
26
|
-
end
|
23
|
+
EventStoreClient.client.link_to(stream_name_2, event)
|
24
|
+
# => EventStore::Client::Streams::AppendResp
|
27
25
|
```
|
28
26
|
|
29
27
|
The linked event can later be fetched by providing the `:resolve_link_tos` option when reading from the stream:
|
30
28
|
|
31
29
|
```ruby
|
32
|
-
EventStoreClient.client.read('some-stream-2', options: { resolve_link_tos: true })
|
30
|
+
EventStoreClient.client.read('some-stream-2', options: { resolve_link_tos: true })
|
33
31
|
```
|
34
32
|
|
35
33
|
If you don't provide the `:resolve_link_tos` option, the "linked" event will be returned instead of the original one.
|
@@ -55,14 +53,10 @@ events.each do |event|
|
|
55
53
|
EventStoreClient.client.append_to_stream(stream_name_1, event)
|
56
54
|
end
|
57
55
|
# Get persisted events
|
58
|
-
events = EventStoreClient.client.read(stream_name_1)
|
56
|
+
events = EventStoreClient.client.read(stream_name_1)
|
59
57
|
# Link events from first stream into second stream one by one
|
60
|
-
|
61
|
-
|
62
|
-
if result.success? # Event was successfully linked
|
63
|
-
else # event was not linked, result.failure? => true
|
64
|
-
end
|
65
|
-
end
|
58
|
+
EventStoreClient.client.link_to(stream_name_2, events)
|
59
|
+
# => Array<EventStore::Client::Streams::AppendResp>
|
66
60
|
```
|
67
61
|
|
68
62
|
## Handling concurrency
|
@@ -87,11 +81,13 @@ stream_name_1 = "some-stream-1$#{SecureRandom.uuid}"
|
|
87
81
|
stream_name_2 = "some-stream-2$#{SecureRandom.uuid}"
|
88
82
|
|
89
83
|
EventStoreClient.client.append_to_stream(stream_name_1, [event1, event2])
|
90
|
-
events = EventStoreClient.client.read(stream_name_1)
|
84
|
+
events = EventStoreClient.client.read(stream_name_1)
|
91
85
|
|
92
|
-
|
93
|
-
|
94
|
-
|
86
|
+
begin
|
87
|
+
EventStoreClient.client.link_to(stream_name_2, events, options: { expected_revision: :no_stream })
|
88
|
+
rescue EventStoreClient::WrongExpectedVersionError => e
|
89
|
+
puts e.message
|
90
|
+
end
|
95
91
|
```
|
96
92
|
|
97
93
|
There are three available stream states:
|
@@ -119,13 +115,13 @@ event2 = SomethingHappened.new(
|
|
119
115
|
EventStoreClient.client.append_to_stream(stream_name_1, event1)
|
120
116
|
EventStoreClient.client.append_to_stream(stream_name_2, event2)
|
121
117
|
# Load events from DB
|
122
|
-
event1 = EventStoreClient.client.read(stream_name_1).
|
123
|
-
event2 = EventStoreClient.client.read(stream_name_2).
|
118
|
+
event1 = EventStoreClient.client.read(stream_name_1).first
|
119
|
+
event2 = EventStoreClient.client.read(stream_name_2).first
|
124
120
|
# Get the revision number of latest event
|
125
|
-
revision = EventStoreClient.client.read(stream_name_2).
|
121
|
+
revision = EventStoreClient.client.read(stream_name_2).last.stream_revision
|
126
122
|
# Expected revision matches => will succeed
|
127
123
|
EventStoreClient.client.link_to(stream_name_2, event1, options: { expected_revision: revision })
|
128
|
-
# Will fail with revisions mismatch
|
124
|
+
# Will fail with EventStoreClient::WrongExpectedVersionError error due to revisions mismatch
|
129
125
|
EventStoreClient.client.link_to(stream_name_2, event2, options: { expected_revision: revision })
|
130
126
|
```
|
131
127
|
|
@@ -145,7 +141,7 @@ stream_name_1 = 'some-stream-1'
|
|
145
141
|
stream_name_2 = 'some-stream-2'
|
146
142
|
EventStoreClient.client.append_to_stream(stream_name_1, event)
|
147
143
|
# Get persisted event
|
148
|
-
event = EventStoreClient.client.read(stream_name_1).
|
144
|
+
event = EventStoreClient.client.read(stream_name_1).first
|
149
145
|
# Link event from first stream into second stream
|
150
|
-
|
146
|
+
EventStoreClient.client.link_to(stream_name_2, event, credentials: { username: 'admin', password: 'changeit' })
|
151
147
|
```
|
data/docs/reading_events.md
CHANGED
@@ -8,18 +8,7 @@ The simplest way to read a stream forwards is to supply a stream name.
|
|
8
8
|
|
9
9
|
```ruby
|
10
10
|
EventStoreClient.client.read('some-stream')
|
11
|
-
# =>
|
12
|
-
```
|
13
|
-
|
14
|
-
This will return either `Dry::Monads::Success` with the list of events attached or `Dry::Monads::Failure` with an error. You can handle the result like this:
|
15
|
-
|
16
|
-
```ruby
|
17
|
-
result = EventStoreClient.client.read('some-stream')
|
18
|
-
if result.success?
|
19
|
-
result.success.each do |event|
|
20
|
-
# do something with an event
|
21
|
-
end
|
22
|
-
end
|
11
|
+
# => [#<EventStoreClient::DeserializedEvent 0x1>, #<EventStoreClient::DeserializedEvent 0x1>]
|
23
12
|
```
|
24
13
|
|
25
14
|
### Request options customization
|
@@ -68,17 +57,17 @@ As well as being able to read a stream forwards you can also go backwards. This
|
|
68
57
|
EventStoreClient.client.read('some-stream', options: { direction: 'Backwards', from_revision: :end })
|
69
58
|
```
|
70
59
|
|
71
|
-
## Checking if
|
60
|
+
## Checking if stream exists
|
72
61
|
|
73
|
-
In case a stream with given name does not exist
|
62
|
+
In case a stream with given name does not exist - `EventStoreClient::StreamNotFoundError` error will be raised:
|
74
63
|
|
75
64
|
```ruby
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
# =>
|
80
|
-
|
81
|
-
|
65
|
+
begin
|
66
|
+
EventStoreClient.client.read('non-existing-stream')
|
67
|
+
rescue EventStoreClient::StreamNotFoundError => e
|
68
|
+
puts e.message # => Stream "non-existing-stream" does not exist.
|
69
|
+
puts e.stream_name # => "non-existing-stream"
|
70
|
+
end
|
82
71
|
```
|
83
72
|
|
84
73
|
## Reading from the $all stream
|
@@ -103,46 +92,40 @@ If you would like to skip deserialization of the `#read` result, you should use
|
|
103
92
|
|
104
93
|
```ruby
|
105
94
|
EventStoreClient.client.read('some-stream', skip_deserialization: true)
|
106
|
-
# =>
|
95
|
+
# => [<EventStore::Client::Streams::ReadResp ...>]
|
107
96
|
```
|
108
97
|
|
109
98
|
## Filtering
|
110
99
|
|
111
|
-
The filtering feature is only available for the`$all` stream.
|
100
|
+
The filtering feature is only available for the `$all` stream.
|
112
101
|
|
113
102
|
Retrieve events from streams with name starting with `some-stream`:
|
114
103
|
|
115
104
|
```ruby
|
116
|
-
|
105
|
+
events =
|
117
106
|
EventStoreClient.client.read('$all', options: { filter: { stream_identifier: { prefix: ['some-stream'] } } })
|
118
|
-
|
119
|
-
|
120
|
-
# iterate through events
|
121
|
-
end
|
107
|
+
events.each do |event|
|
108
|
+
# iterate through events
|
122
109
|
end
|
123
110
|
```
|
124
111
|
|
125
112
|
Retrieve events with name starting with `some-event`:
|
126
113
|
|
127
114
|
```ruby
|
128
|
-
|
115
|
+
events =
|
129
116
|
EventStoreClient.client.read('$all', options: { event_type: { prefix: ['some-event'] } })
|
130
|
-
|
131
|
-
|
132
|
-
# iterate through events
|
133
|
-
end
|
117
|
+
events.each do |event|
|
118
|
+
# iterate through events
|
134
119
|
end
|
135
120
|
```
|
136
121
|
|
137
122
|
Retrieving events from stream `some-stream-1` and `some-stream-2`:
|
138
123
|
|
139
124
|
```ruby
|
140
|
-
|
125
|
+
events =
|
141
126
|
EventStoreClient.client.read('$all', options: { filter: { stream_identifier: { prefix: ['some-stream-1', 'some-stream-2'] } } })
|
142
|
-
|
143
|
-
|
144
|
-
# iterate through events
|
145
|
-
end
|
127
|
+
events.each do |event|
|
128
|
+
# iterate through events
|
146
129
|
end
|
147
130
|
```
|
148
131
|
|
@@ -151,43 +134,33 @@ end
|
|
151
134
|
You can use `#read_paginated`, the ready-to-go implementation of pagination which returns an array of result pages:
|
152
135
|
|
153
136
|
```ruby
|
154
|
-
EventStoreClient.client.read_paginated('some-stream').each do |
|
155
|
-
|
156
|
-
|
157
|
-
# do something with event
|
158
|
-
end
|
137
|
+
EventStoreClient.client.read_paginated('some-stream').each do |events|
|
138
|
+
events.each do |event|
|
139
|
+
# iterate through events
|
159
140
|
end
|
160
141
|
end
|
161
142
|
|
162
|
-
EventStoreClient.client.read_paginated('$all').each do |
|
163
|
-
|
164
|
-
|
165
|
-
# do something with event
|
166
|
-
end
|
143
|
+
EventStoreClient.client.read_paginated('$all').each do |events|
|
144
|
+
events.each do |event|
|
145
|
+
# iterate through events
|
167
146
|
end
|
168
147
|
end
|
169
148
|
```
|
170
149
|
|
171
|
-
|
172
|
-
|
173
150
|
### Paginating backward reads
|
174
151
|
|
175
152
|
Just supply a call with `:direction` option and with `:from_position`/`:from_revision` option(depending on what stream you read from):
|
176
153
|
|
177
154
|
```ruby
|
178
|
-
EventStoreClient.client.read_paginated('some-stream', options: { direction: 'Backwards', from_revision: :end }).each do |
|
179
|
-
|
180
|
-
|
181
|
-
# do something with event
|
182
|
-
end
|
155
|
+
EventStoreClient.client.read_paginated('some-stream', options: { direction: 'Backwards', from_revision: :end }).each do |events|
|
156
|
+
events.each do |event|
|
157
|
+
# iterate through events
|
183
158
|
end
|
184
159
|
end
|
185
160
|
|
186
|
-
EventStoreClient.client.read_paginated('$all', options: { direction: 'Backwards', from_position: :end }).each do |
|
187
|
-
|
188
|
-
|
189
|
-
# do something with event
|
190
|
-
end
|
161
|
+
EventStoreClient.client.read_paginated('$all', options: { direction: 'Backwards', from_position: :end }).each do |events|
|
162
|
+
events.each do |event|
|
163
|
+
# iterate through events
|
191
164
|
end
|
192
165
|
end
|
193
166
|
```
|
@@ -31,8 +31,8 @@ module EventStoreClient
|
|
31
31
|
# puts proposed_msg_opts.proposed_message
|
32
32
|
# end
|
33
33
|
# ```
|
34
|
-
# @return [
|
35
|
-
#
|
34
|
+
# @return [EventStore::Client::Streams::AppendResp, Array<EventStore::Client::Streams::AppendResp>]
|
35
|
+
# @raise [EventStoreClient::WrongExpectedVersionError]
|
36
36
|
def append_to_stream(stream_name, events_or_event, options: {}, credentials: {}, &blk)
|
37
37
|
if events_or_event.is_a?(Array)
|
38
38
|
Commands::Streams::AppendMultiple.new(config: config, **credentials).call(
|
@@ -93,7 +93,8 @@ module EventStoreClient
|
|
93
93
|
# )
|
94
94
|
# end
|
95
95
|
# ```
|
96
|
-
# @return [
|
96
|
+
# @return [Array<EventStoreClient::DeserializedEvent>, Array<EventStore::Client::Streams::ReadResp>]
|
97
|
+
# @raise [EventStoreClient::StreamNotFoundError]
|
97
98
|
def read(stream_name, options: {}, skip_deserialization: config.skip_deserialization,
|
98
99
|
skip_decryption: config.skip_decryption, credentials: {}, &blk)
|
99
100
|
Commands::Streams::Read.new(config: config, **credentials).call(
|
@@ -106,8 +107,9 @@ module EventStoreClient
|
|
106
107
|
end
|
107
108
|
|
108
109
|
# @see {#read} for available params
|
109
|
-
# @return [Enumerator] enumerator will yield
|
110
|
-
#
|
110
|
+
# @return [Enumerator] enumerator will yield EventStoreClient::DeserializedEvent or
|
111
|
+
# EventStore::Client::Streams::ReadResp on each iteration depending on `:skip_deserialization`
|
112
|
+
# argument value
|
111
113
|
def read_paginated(stream_name, options: {}, credentials: {},
|
112
114
|
skip_deserialization: config.skip_deserialization,
|
113
115
|
skip_decryption: config.skip_decryption, &blk)
|
@@ -136,7 +138,8 @@ module EventStoreClient
|
|
136
138
|
# opts.stream_identifier.stream_name = 'overridden-stream-name'
|
137
139
|
# end
|
138
140
|
# ```
|
139
|
-
# @return [
|
141
|
+
# @return [EventStore::Client::Streams::DeleteResp]
|
142
|
+
# @raise [EventStoreClient::StreamDeletionError]
|
140
143
|
def hard_delete_stream(stream_name, options: {}, credentials: {}, &blk)
|
141
144
|
Commands::Streams::HardDelete.
|
142
145
|
new(config: config, **credentials).
|
@@ -159,7 +162,8 @@ module EventStoreClient
|
|
159
162
|
# opts.stream_identifier.stream_name = 'overridden-stream-name'
|
160
163
|
# end
|
161
164
|
# ```
|
162
|
-
# @return [
|
165
|
+
# @return [EventStore::Client::Streams::DeleteResp]
|
166
|
+
# @raise [EventStoreClient::StreamDeletionError]
|
163
167
|
def delete_stream(stream_name, options: {}, credentials: {}, &blk)
|
164
168
|
Commands::Streams::Delete.
|
165
169
|
new(config: config, **credentials).
|
@@ -218,7 +222,7 @@ module EventStoreClient
|
|
218
222
|
# )
|
219
223
|
# end
|
220
224
|
# ```
|
221
|
-
# @return [
|
225
|
+
# @return [void] will block current Thread until killed
|
222
226
|
def subscribe_to_stream(stream_name, handler:, options: {}, credentials: {},
|
223
227
|
skip_deserialization: config.skip_deserialization,
|
224
228
|
skip_decryption: config.skip_decryption, &blk)
|
@@ -274,7 +278,7 @@ module EventStoreClient
|
|
274
278
|
# @param credentials [Hash]
|
275
279
|
# @option credentials [String] :username
|
276
280
|
# @option credentials [String] :password
|
277
|
-
# @return [
|
281
|
+
# @return [EventStore::Client::Gossip::ClusterInfo]
|
278
282
|
def cluster_info(credentials: {})
|
279
283
|
Commands::Gossip::ClusterInfo.new(config: config, **credentials).call
|
280
284
|
end
|