event_store_client 1.0.6 → 1.0.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +70 -130
- data/lib/event_store_client.rb +3 -2
- data/lib/event_store_client/adapters/grpc/README.md +16 -0
- data/lib/event_store_client/adapters/grpc/commands/streams/append.rb +2 -2
- data/lib/event_store_client/adapters/http/README.md +4 -4
- data/lib/event_store_client/adapters/http/client.rb +1 -3
- data/lib/event_store_client/adapters/http/commands/streams/read.rb +2 -4
- data/lib/event_store_client/configuration.rb +2 -2
- data/lib/event_store_client/deserialized_event.rb +3 -1
- data/lib/event_store_client/error_handler.rb +10 -0
- data/lib/event_store_client/subscription.rb +2 -1
- data/lib/event_store_client/version.rb +1 -1
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7046a3740fb53a00a8c30786e4bf6af390ba8a93be973412514baff7065731d1
|
4
|
+
data.tar.gz: ba04c6804ebfa8d7e876f14766f87f806adff2dee66e2f1e02a6d0644acad357
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3657c4a696a35b85f37995cae37af7fd31d7c287f751a8444e1e63c640d7ec5dd9e874164c5448aa0cee5030029d8b80797308676a528a5ec42af71800ea5677
|
7
|
+
data.tar.gz: d17ed0da65846b1e79caa8bbef2ad9968de9627605c3eb0b7b64eee6558e1768171e087604e9c2563666334da4f148913e82df8d35acd6a74852b548af641cc1
|
data/README.md
CHANGED
@@ -3,19 +3,19 @@
|
|
3
3
|
|
4
4
|
# EventStoreClient
|
5
5
|
|
6
|
-
An easy-to use API client for connecting ruby applications with https://eventstore.
|
6
|
+
An easy-to use API client for connecting ruby applications with [EventStoreDB](https://eventstore.com/)
|
7
7
|
|
8
8
|
## Supported adapters
|
9
9
|
|
10
|
-
- GRPC - default
|
10
|
+
- [GRPC](https://github.com/yousty/event_store_client/tree/master/lib/event_store_client/adapters/grpc/README.md) - default
|
11
11
|
- [HTTP](https://github.com/yousty/event_store_client/tree/master/lib/event_store_client/adapters/http/README.md) - Deprecated
|
12
|
-
-
|
12
|
+
- InMemory - for testing
|
13
13
|
|
14
14
|
## Installation
|
15
15
|
Add this line to your application's Gemfile:
|
16
16
|
|
17
17
|
```ruby
|
18
|
-
gem 'event_store_client'
|
18
|
+
gem 'event_store_client', '~> 1.0'
|
19
19
|
```
|
20
20
|
|
21
21
|
And then execute:
|
@@ -30,19 +30,8 @@ $ gem install event_store_client
|
|
30
30
|
|
31
31
|
## Usage
|
32
32
|
|
33
|
-
Before you start, make sure you
|
34
|
-
|
35
|
-
### EventStore engine setup
|
36
|
-
|
37
|
-
1. Download Event Store From https://eventstore.org/downloads/ or docker
|
38
|
-
|
39
|
-
` docker pull eventstore/eventstore`
|
40
|
-
|
41
|
-
2. Run the Event Store server
|
42
|
-
|
43
|
-
`docker run --env EVENTSTORE_INSECURE=true --name eventstore -it -p 2113:2113 -p 1113:1113 eventstore/eventstore`
|
44
|
-
|
45
|
-
4. Visit the admin panel http://localhost:2113 and enable Projections for Event-Types
|
33
|
+
Before you start, make sure you are connecting to a running EventStoreDB instance. For a detailed guide see:
|
34
|
+
[EventStoreServerSetup](https://github.com/yousty/event_store_client/blob/master/docs/eventstore_server_setup.md)
|
46
35
|
|
47
36
|
### Create Dummy event and dummy Handler
|
48
37
|
|
@@ -76,71 +65,99 @@ class DummyHandler
|
|
76
65
|
end
|
77
66
|
end
|
78
67
|
```
|
79
|
-
|
68
|
+
|
80
69
|
|
81
70
|
```ruby
|
82
|
-
# initialize the client
|
83
|
-
client = EventStoreClient::Client.new
|
84
|
-
```
|
85
71
|
|
86
|
-
|
72
|
+
require 'event_store_client'
|
73
|
+
require "event_store_client/adapters/grpc"
|
87
74
|
|
88
|
-
|
89
|
-
|
90
|
-
|
75
|
+
EventStoreClient.configure do |config|
|
76
|
+
config.eventstore_url = ENV['EVENTSTORE_URL']
|
77
|
+
config.eventstore_user = ENV['EVENTSTORE_USER']
|
78
|
+
config.eventstore_password = ENV['EVENTSTORE_PASSWORD']
|
79
|
+
config.verify_ssl = false # remove this line if your server does have the host verified
|
80
|
+
end
|
91
81
|
|
92
|
-
|
82
|
+
event_store = EventStoreClient::Client.new
|
93
83
|
|
94
|
-
|
95
|
-
|
84
|
+
event_store.subscribe(
|
85
|
+
DummyHandler.new,
|
86
|
+
to: [SomethingHappened]
|
87
|
+
)
|
88
|
+
|
89
|
+
event_store.listen
|
96
90
|
```
|
97
91
|
|
98
|
-
|
92
|
+
## Features
|
99
93
|
|
100
|
-
|
101
|
-
events = client.read('newstream', direction: 'backwards') #default 'forwards'
|
102
|
-
```
|
94
|
+
## Basic Usage
|
103
95
|
|
104
|
-
|
96
|
+
The main interface allows for actions listed below which is enough for basic useage.
|
97
|
+
The actual adapter allows for more actions. Contributions as always welcome!
|
105
98
|
|
106
99
|
```ruby
|
107
|
-
|
108
|
-
|
100
|
+
# Publishing to a stream
|
101
|
+
event_store.publish(stream: 'newstream', events: [event])
|
109
102
|
|
110
|
-
|
103
|
+
# Reading from a stream
|
104
|
+
events = event_store.read('newstream').value!
|
111
105
|
|
112
|
-
|
113
|
-
|
106
|
+
# Reading all events from a stream
|
107
|
+
events = event_store.read('newstream', options: { all: true }).value! #default 'false'
|
114
108
|
|
115
|
-
#
|
116
|
-
|
109
|
+
# Linking existing events to a new stream
|
110
|
+
event_store.link_to(stream_name, events)
|
117
111
|
|
118
|
-
#
|
112
|
+
# Subscribing to events
|
113
|
+
event_store.subscribe(DummyHandler.new, to: [SomethingHappened])
|
119
114
|
|
120
|
-
events
|
121
|
-
|
115
|
+
# Listening to new events for all registered subscriptions
|
116
|
+
event_store.listen
|
122
117
|
|
118
|
+
# In the new terminal session publish some events
|
119
|
+
events = (1..10).map { event }
|
120
|
+
event_store.publish(stream: 'newstream', events: events)
|
123
121
|
# .... wait a little bit ... Your handler should be called for every single event you publish
|
124
122
|
```
|
125
123
|
|
126
|
-
###
|
124
|
+
### Extended usage
|
127
125
|
|
128
|
-
|
129
|
-
|
126
|
+
You can get access to more features by calling the adapter directly, for example:
|
127
|
+
|
128
|
+
```
|
129
|
+
event_store.connection.delete_stream(stream)
|
130
|
+
event_store.connection.tombstone_stream(stream)
|
130
131
|
```
|
131
132
|
|
132
|
-
|
133
|
+
See the adapters method list for the possible usage.
|
133
134
|
|
134
|
-
|
135
|
+
- [HTTP](https://github.com/yousty/event_store_client/blob/master/lib/event_store_client/adapters/http/client.rb)
|
136
|
+
- [GRPC](https://github.com/yousty/event_store_client/blob/master/lib/event_store_client/adapters/grpc/client.rb)
|
135
137
|
|
136
|
-
|
138
|
+
### Configuration
|
139
|
+
|
140
|
+
There are several configuration options you can pass to customize your client's instance.
|
141
|
+
All the config options can be passed the same way:
|
137
142
|
|
138
143
|
```ruby
|
139
144
|
EventStoreClient.configure do |config|
|
140
|
-
config.adapter =
|
145
|
+
config.adapter = :grpc
|
141
146
|
end
|
142
147
|
```
|
143
148
|
|
149
|
+
| name | value | default | description |
|
150
|
+
|:-------------:|:-------------:|:-----:|:-------------:|
|
151
|
+
| adapter | `:grpc`, `:http` or `:in_memory` | `:grpc` | different ways to connect with an event_store_db. The in_memory is a mock server useful for testing |
|
152
|
+
| verify_ssl | Boolean | true | Useful for self-signed certificates (Kubernetes, local development) |
|
153
|
+
| error_handler | Any callable ruby object | EvenStoreClient::ErrorHandler | You can pass a custom error handler for reacting on event_handler errors.|
|
154
|
+
| eventstore_url| String| 'http://localhost:2113'| An url for the server instance|
|
155
|
+
| user| String| 'admin' | a user used to connect the application with the server|
|
156
|
+
| password| String| 'changeit'| a password used to connect the application with the server|
|
157
|
+
| per_page| Integer| 20 | a batch size for events subscriptions |
|
158
|
+
| service_name| String| 'default' | a prefix (namespace) added to the subscriptions names|
|
159
|
+
| mapper| `Mapper::Default` or `Mapper::Encrypted`| `Mapper::Default.new` | an engine used to parse events.
|
160
|
+
|
144
161
|
## Event Mappers
|
145
162
|
|
146
163
|
At the moment we offer two types of mappers:
|
@@ -156,86 +173,7 @@ Event parsable by event_store and the other way around.
|
|
156
173
|
### Encrypted Mapper
|
157
174
|
|
158
175
|
This is implemented to match GDPR requirements. It allows you to encrypt any event using your
|
159
|
-
encryption_key repository.
|
160
|
-
|
161
|
-
```ruby
|
162
|
-
mapper = EventStoreClient::Mapper::Encrypted.new(key_repository)
|
163
|
-
EventStoreClient.configure do |config|
|
164
|
-
config.mapper = mapper
|
165
|
-
end
|
166
|
-
```
|
167
|
-
|
168
|
-
The Encrypted mapper uses the encryption key repository to encrypt data in your events according to the event definition.
|
169
|
-
|
170
|
-
Here is the minimal repository interface for this to work.
|
171
|
-
|
172
|
-
```ruby
|
173
|
-
class DummyRepository
|
174
|
-
class Key
|
175
|
-
attr_accessor :iv, :cipher, :id
|
176
|
-
def initialize(id:, **)
|
177
|
-
@id = id
|
178
|
-
end
|
179
|
-
end
|
180
|
-
|
181
|
-
def find(user_id)
|
182
|
-
Key.new(id: user_id)
|
183
|
-
end
|
184
|
-
|
185
|
-
def encrypt(*)
|
186
|
-
'darthvader'
|
187
|
-
end
|
188
|
-
|
189
|
-
def decrypt(*)
|
190
|
-
{ first_name: 'Anakin', last_name: 'Skylwalker'}
|
191
|
-
end
|
192
|
-
end
|
193
|
-
```
|
194
|
-
|
195
|
-
Now, having that, you only need to define the event encryption schema:
|
196
|
-
|
197
|
-
```ruby
|
198
|
-
class EncryptedEvent < EventStoreClient::DeserializedEvent
|
199
|
-
def schema
|
200
|
-
Dry::Schema.Params do
|
201
|
-
required(:user_id).value(:string)
|
202
|
-
required(:first_name).value(:string)
|
203
|
-
required(:last_name).value(:string)
|
204
|
-
required(:profession).value(:string)
|
205
|
-
end
|
206
|
-
end
|
207
|
-
|
208
|
-
def self.encryption_schema
|
209
|
-
{
|
210
|
-
key: ->(data) { data['user_id'] },
|
211
|
-
attributes: %i[first_name last_name email]
|
212
|
-
}
|
213
|
-
end
|
214
|
-
end
|
215
|
-
|
216
|
-
event = EncryptedEvent.new(
|
217
|
-
user_id: SecureRandom.uuid,
|
218
|
-
first_name: 'Anakin',
|
219
|
-
last_name: 'Skylwalker',
|
220
|
-
profession: 'Jedi'
|
221
|
-
)
|
222
|
-
```
|
223
|
-
|
224
|
-
When you'll publish this event, in the store will be saved:
|
225
|
-
|
226
|
-
```ruby
|
227
|
-
{
|
228
|
-
'data' => {
|
229
|
-
'user_id' => 'dab48d26-e4f8-41fc-a9a8-59657e590716',
|
230
|
-
'first_name' => 'encrypted',
|
231
|
-
'last_name' => 'encrypted',
|
232
|
-
'profession' => 'Jedi',
|
233
|
-
'encrypted' => '2345l423lj1#$!lkj24f1'
|
234
|
-
},
|
235
|
-
type: 'EncryptedEvent'
|
236
|
-
metadata: { ... }
|
237
|
-
}
|
238
|
-
```
|
176
|
+
encryption_key repository. For the detailed guide see the: [Encrypting Events](https://github.com/yousty/event_store_client/blob/master/docs/encrypting_events.md).
|
239
177
|
|
240
178
|
## Contributing
|
241
179
|
|
@@ -245,6 +183,8 @@ Do you want to contribute? Welcome!
|
|
245
183
|
2. Create Issue
|
246
184
|
3. Create PR ;)
|
247
185
|
|
186
|
+
For running the client in the dev mode, see: [Development Guide](https://github.com/yousty/event_store_client/blob/master/docs/eventstore_server_setup.md)
|
187
|
+
|
248
188
|
### Publishing new version
|
249
189
|
|
250
190
|
1. Push commit with updated `version.rb` file to the `release` branch. The new version will be automatically pushed to [rubygems](https://rubygems.org).
|
data/lib/event_store_client.rb
CHANGED
@@ -4,13 +4,14 @@ module EventStoreClient
|
|
4
4
|
end
|
5
5
|
|
6
6
|
require 'event_store_client/types'
|
7
|
-
|
8
|
-
require 'event_store_client/deserialized_event'
|
7
|
+
|
9
8
|
require 'event_store_client/serializer/json'
|
10
9
|
|
11
10
|
require 'event_store_client/mapper'
|
12
11
|
|
13
12
|
require 'event_store_client/configuration'
|
13
|
+
require 'event_store_client/event'
|
14
|
+
require 'event_store_client/deserialized_event'
|
14
15
|
|
15
16
|
require 'event_store_client/subscription'
|
16
17
|
require 'event_store_client/subscriptions'
|
@@ -0,0 +1,16 @@
|
|
1
|
+
### GRPC adapter
|
2
|
+
|
3
|
+
This adapter targets the EventstoreDB version `>= "20.*"
|
4
|
+
|
5
|
+
### Configuration
|
6
|
+
|
7
|
+
As by default EventStoreClient uses GRPC adapter. No need to configure anything if you want to use it,
|
8
|
+
however to set it explicitly, place the snippet below in your initializer or when you boot your application.
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
require 'event_store_client/adapters/grpc'
|
12
|
+
|
13
|
+
EventStoreClient.configure do |config|
|
14
|
+
config.adapter = :grpc
|
15
|
+
end
|
16
|
+
```
|
@@ -1,8 +1,6 @@
|
|
1
1
|
### HTTP adapter
|
2
2
|
|
3
|
-
This adapter targets the EventstoreDB version `>= "
|
4
|
-
|
5
|
-
For detailed docs about the http protocol see [EventStoreDB Http Documentation](https://developers.eventstore.com/server/5.0.8/http-api/)
|
3
|
+
This adapter targets the EventstoreDB version `>= "20.*"
|
6
4
|
|
7
5
|
### Configuration
|
8
6
|
|
@@ -10,7 +8,9 @@ As by default EventStoreClient uses gRPC adapter, to switch to http you need to
|
|
10
8
|
Place the snippet below in your initializer or when you boot your application.
|
11
9
|
|
12
10
|
```ruby
|
11
|
+
require 'event_store_client/adapters/http'
|
12
|
+
|
13
13
|
EventStoreClient.configure do |config|
|
14
|
-
config.adapter = :
|
14
|
+
config.adapter = :http
|
15
15
|
end
|
16
16
|
```
|
@@ -47,9 +47,7 @@ module EventStoreClient
|
|
47
47
|
# @return Dry::Monads::Result::Success with returned events or Dry::Monads::Result::Failure
|
48
48
|
#
|
49
49
|
def read(stream_name, options: {})
|
50
|
-
Commands::Streams::Read.new(connection).call(
|
51
|
-
stream_name, options: options
|
52
|
-
)
|
50
|
+
Commands::Streams::Read.new(connection).call(stream_name, options: options)
|
53
51
|
end
|
54
52
|
|
55
53
|
# Reads all events from the given stream
|
@@ -11,10 +11,8 @@ module EventStoreClient
|
|
11
11
|
count = options[:count] || config.per_page
|
12
12
|
start = options[:start].to_i
|
13
13
|
direction = options[:direction] || 'forward'
|
14
|
-
headers = {
|
15
|
-
|
16
|
-
'Accept' => 'application/vnd.eventstore.atom+json'
|
17
|
-
}
|
14
|
+
headers = { 'Accept' => 'application/vnd.eventstore.atom+json' }
|
15
|
+
headers['ES-ResolveLinkTos'] = true if options.key?(:resolve_links)
|
18
16
|
|
19
17
|
response =
|
20
18
|
connection.call(
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'dry-configurable'
|
4
|
-
|
4
|
+
require 'event_store_client/error_handler'
|
5
5
|
module EventStoreClient
|
6
6
|
extend Dry::Configurable
|
7
7
|
|
@@ -10,7 +10,7 @@ module EventStoreClient
|
|
10
10
|
setting :adapter, :grpc
|
11
11
|
setting :verify_ssl, true
|
12
12
|
|
13
|
-
setting :error_handler
|
13
|
+
setting :error_handler, ErrorHandler.new
|
14
14
|
setting :eventstore_url, 'http://localhost:2113' do |value|
|
15
15
|
value.is_a?(URI) ? value : URI(value)
|
16
16
|
end
|
@@ -19,7 +19,9 @@ module EventStoreClient
|
|
19
19
|
|
20
20
|
def initialize(**args)
|
21
21
|
validation = schema.call(args[:data] || {})
|
22
|
-
|
22
|
+
if validation.errors.any?
|
23
|
+
raise InvalidDataError.new(message: "#{schema.class.name} #{validation.errors.to_h}")
|
24
|
+
end
|
23
25
|
|
24
26
|
@data = args.fetch(:data) { {} }
|
25
27
|
@metadata = args.fetch(:metadata) { {} }.merge(
|
@@ -13,7 +13,8 @@ module EventStoreClient
|
|
13
13
|
else
|
14
14
|
subscriber.class.name
|
15
15
|
end
|
16
|
-
@name =
|
16
|
+
@name = subscriber_class.to_s
|
17
|
+
@name = "#{service}-" + @name if service != ''
|
17
18
|
@subscriber = subscriber
|
18
19
|
@stream = name
|
19
20
|
@observed_streams = event_types.reduce([]) { |r, type| r << "$et-#{type}" }
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: event_store_client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.11
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sebastian Wilgosz
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-05-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dry-configurable
|
@@ -156,6 +156,7 @@ files:
|
|
156
156
|
- lib/event_store_client/adapters/grpc/Protos/shared.proto
|
157
157
|
- lib/event_store_client/adapters/grpc/Protos/streams.proto
|
158
158
|
- lib/event_store_client/adapters/grpc/Protos/users.proto
|
159
|
+
- lib/event_store_client/adapters/grpc/README.md
|
159
160
|
- lib/event_store_client/adapters/grpc/client.rb
|
160
161
|
- lib/event_store_client/adapters/grpc/command_registrar.rb
|
161
162
|
- lib/event_store_client/adapters/grpc/commands/command.rb
|
@@ -212,6 +213,7 @@ files:
|
|
212
213
|
- lib/event_store_client/data_encryptor.rb
|
213
214
|
- lib/event_store_client/deserialized_event.rb
|
214
215
|
- lib/event_store_client/encryption_metadata.rb
|
216
|
+
- lib/event_store_client/error_handler.rb
|
215
217
|
- lib/event_store_client/event.rb
|
216
218
|
- lib/event_store_client/mapper.rb
|
217
219
|
- lib/event_store_client/mapper/default.rb
|
@@ -242,7 +244,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
242
244
|
- !ruby/object:Gem::Version
|
243
245
|
version: '0'
|
244
246
|
requirements: []
|
245
|
-
rubygems_version: 3.
|
247
|
+
rubygems_version: 3.0.6
|
246
248
|
signing_key:
|
247
249
|
specification_version: 4
|
248
250
|
summary: Ruby integration for https://eventstore.org
|