avro_turf 1.1.0 → 1.2.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/README.md +18 -0
- data/lib/avro_turf/messaging.rb +16 -11
- data/lib/avro_turf/version.rb +1 -1
- data/spec/messaging_spec.rb +102 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8fc2d29f1112e649cc2cd5ec96f2126a0ea5fa8f46ebee01d908cdceeac8da0d
|
4
|
+
data.tar.gz: e1989abd9d9b0e5db24f360e96e7bce7ce18e5f488cc794d25a2b3fae6102e66
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f562a66ba746d2c0e4bee8b8f3a0e7fcf65900f261eca444986c8ff6c68231e67aa9c4dc659213721d0d09c65fd9273e12e158938c0773baa48cf86598d6bef9
|
7
|
+
data.tar.gz: 53e3640900a3b64038fe063f5dadab2049417490be1833bb5f17124307abe628af64ea0c68b5bdc2bd4ef2f6e58bbfac287696eaf5ece9a35ddb7c2ab8e5127e
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,11 @@
|
|
2
2
|
|
3
3
|
## Unreleased
|
4
4
|
|
5
|
+
## v1.2.0
|
6
|
+
|
7
|
+
- Expose `fetch_schema`, `fetch_schema_by_id` and `register_schema` schema in `Messaging` interface (#117, #119)
|
8
|
+
- Add ability to validate message before encoding in `Messaging#encode` interface (#116, #118)
|
9
|
+
|
5
10
|
## v1.1.0
|
6
11
|
|
7
12
|
- Compatibility with Avro v1.10.x.
|
data/README.md
CHANGED
@@ -178,6 +178,10 @@ data = avro.encode({ "title" => "hello, world" }, subject: 'greeting', version:
|
|
178
178
|
# of the same schema version will be served by the cache.
|
179
179
|
data = avro.encode({ "title" => "hello, world" }, schema_id: 2)
|
180
180
|
|
181
|
+
# Message can be validated before encoding to get a description of problem through
|
182
|
+
# Avro::SchemaValidator::ValidationError exception
|
183
|
+
data = avro.encode({ "titl" => "hello, world" }, schema_name: "greeting", validate: true)
|
184
|
+
|
181
185
|
# When decoding, the schema will be fetched from the registry and cached. Subsequent
|
182
186
|
# instances of the same schema id will be served by the cache.
|
183
187
|
avro.decode(data) #=> { "title" => "hello, world" }
|
@@ -189,6 +193,20 @@ result.message #=> { "title" => "hello, world" }
|
|
189
193
|
result.schema_id #=> 3
|
190
194
|
result.writer_schema #=> #<Avro::Schema: ...>
|
191
195
|
result.reader_schema #=> nil
|
196
|
+
|
197
|
+
# You can also work with schema through this interface:
|
198
|
+
# Fetch latest schema for subject from registry
|
199
|
+
schema, schema_id = avro.fetch_schema(subject: 'greeting')
|
200
|
+
# Fetch specific version
|
201
|
+
schema, schema_id = avro.fetch_schema(subject: 'greeting', version: 1)
|
202
|
+
# Fetch schema by id
|
203
|
+
schema, schema_id = avro.fetch_schema_by_id(3)
|
204
|
+
# Register schema fetched from store by name
|
205
|
+
schema, schema_id = avro.register_schema(schema_name: 'greeting')
|
206
|
+
# Specify namespace (same as schema_name: 'somewhere.greeting')
|
207
|
+
schema, schema_id = avro.register_schema(schema_name: 'greeting', namespace: 'somewhere')
|
208
|
+
# Customize subject under which to register schema
|
209
|
+
schema, schema_id = avro.register_schema(schema_name: 'greeting', namespace: 'somewhere', subject: 'test')
|
192
210
|
```
|
193
211
|
|
194
212
|
### Confluent Schema Registry Client
|
data/lib/avro_turf/messaging.rb
CHANGED
@@ -84,19 +84,26 @@ class AvroTurf
|
|
84
84
|
# the data. Must match the schema used when encoding (optional).
|
85
85
|
# schema_id - The integer id of the schema that should be used to encode
|
86
86
|
# the data.
|
87
|
+
# validate - The boolean for performing complete message validation before
|
88
|
+
# encoding it, Avro::SchemaValidator::ValidationError with
|
89
|
+
# a descriptive message will be raised in case of invalid message.
|
87
90
|
#
|
88
91
|
# Returns the encoded data as a String.
|
89
|
-
def encode(message, schema_name: nil, namespace: @namespace, subject: nil, version: nil, schema_id: nil)
|
90
|
-
|
92
|
+
def encode(message, schema_name: nil, namespace: @namespace, subject: nil, version: nil, schema_id: nil, validate: false)
|
93
|
+
schema, schema_id = if schema_id
|
91
94
|
fetch_schema_by_id(schema_id)
|
92
95
|
elsif subject && version
|
93
|
-
fetch_schema(subject, version)
|
96
|
+
fetch_schema(subject: subject, version: version)
|
94
97
|
elsif schema_name
|
95
|
-
register_schema(subject, schema_name, namespace)
|
98
|
+
register_schema(subject: subject, schema_name: schema_name, namespace: namespace)
|
96
99
|
else
|
97
100
|
raise ArgumentError.new('Neither schema_name nor schema_id nor subject + version provided to determine the schema.')
|
98
101
|
end
|
99
102
|
|
103
|
+
if validate
|
104
|
+
Avro::SchemaValidator.validate!(schema, message, recursive: true, encoded: false, fail_on_extra_fields: true)
|
105
|
+
end
|
106
|
+
|
100
107
|
stream = StringIO.new
|
101
108
|
writer = Avro::IO::DatumWriter.new(schema)
|
102
109
|
encoder = Avro::IO::BinaryEncoder.new(stream)
|
@@ -169,31 +176,29 @@ class AvroTurf
|
|
169
176
|
raise SchemaNotFoundError.new("Schema with id: #{schema_id} is not found on registry")
|
170
177
|
end
|
171
178
|
|
172
|
-
private
|
173
|
-
|
174
179
|
# Providing subject and version to determine the schema,
|
175
180
|
# which skips the auto registeration of schema on the schema registry.
|
176
181
|
# Fetch the schema from registry with the provided subject name and version.
|
177
|
-
def fetch_schema(subject
|
182
|
+
def fetch_schema(subject:, version: 'latest')
|
178
183
|
schema_data = @registry.subject_version(subject, version)
|
179
184
|
schema_id = schema_data.fetch('id')
|
180
185
|
schema = Avro::Schema.parse(schema_data.fetch('schema'))
|
181
|
-
[
|
186
|
+
[schema, schema_id]
|
182
187
|
end
|
183
188
|
|
184
189
|
# Fetch the schema from registry with the provided schema_id.
|
185
190
|
def fetch_schema_by_id(schema_id)
|
186
191
|
schema_json = @registry.fetch(schema_id)
|
187
192
|
schema = Avro::Schema.parse(schema_json)
|
188
|
-
[
|
193
|
+
[schema, schema_id]
|
189
194
|
end
|
190
195
|
|
191
196
|
# Schemas are registered under the full name of the top level Avro record
|
192
197
|
# type, or `subject` if it's provided.
|
193
|
-
def register_schema(subject
|
198
|
+
def register_schema(schema_name:, subject: nil, namespace: nil)
|
194
199
|
schema = @schema_store.find(schema_name, namespace)
|
195
200
|
schema_id = @registry.register(subject || schema.fullname, schema)
|
196
|
-
[
|
201
|
+
[schema, schema_id]
|
197
202
|
end
|
198
203
|
end
|
199
204
|
end
|
data/lib/avro_turf/version.rb
CHANGED
data/spec/messaging_spec.rb
CHANGED
@@ -297,4 +297,106 @@ describe AvroTurf::Messaging do
|
|
297
297
|
end
|
298
298
|
end
|
299
299
|
end
|
300
|
+
|
301
|
+
context "validating" do
|
302
|
+
subject(:encode){ avro.encode(message, schema_name: "person", validate: true) }
|
303
|
+
|
304
|
+
context "for correct message" do
|
305
|
+
it { expect { encode }.not_to raise_error }
|
306
|
+
end
|
307
|
+
|
308
|
+
context "when message has wrong type" do
|
309
|
+
let(:message) { { "full_name" => 123 } }
|
310
|
+
|
311
|
+
it { expect { encode }.to raise_error(Avro::SchemaValidator::ValidationError, /\.full_name expected type string, got int/) }
|
312
|
+
end
|
313
|
+
|
314
|
+
context "when message contains extra fields (typo in key)" do
|
315
|
+
let(:message) { { "fulll_name" => "John Doe" } }
|
316
|
+
|
317
|
+
it { expect { encode }.to raise_error(Avro::SchemaValidator::ValidationError, /extra field 'fulll_name'/) }
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
context 'fetching and registering schema' do
|
322
|
+
let(:schema_store) { AvroTurf::SchemaStore.new(path: "spec/schemas") }
|
323
|
+
|
324
|
+
let(:registry) { AvroTurf::ConfluentSchemaRegistry.new(registry_url, logger: logger) }
|
325
|
+
|
326
|
+
let(:avro) do
|
327
|
+
AvroTurf::Messaging.new(
|
328
|
+
registry: registry,
|
329
|
+
schema_store: schema_store,
|
330
|
+
logger: logger
|
331
|
+
)
|
332
|
+
end
|
333
|
+
|
334
|
+
let(:schema_id) { 234 }
|
335
|
+
|
336
|
+
context 'using fetch_schema' do
|
337
|
+
subject { avro.fetch_schema(subject: subj, version: version) }
|
338
|
+
|
339
|
+
let(:subj) { 'subject' }
|
340
|
+
|
341
|
+
let(:version) { 'version' }
|
342
|
+
|
343
|
+
let(:response) { {'id' => schema_id, 'schema' => schema_json} }
|
344
|
+
|
345
|
+
before do
|
346
|
+
allow(registry).to receive(:subject_version).with(subj, version).and_return(response)
|
347
|
+
end
|
348
|
+
|
349
|
+
it 'gets schema from registry' do
|
350
|
+
expect(subject).to eq([schema, schema_id])
|
351
|
+
end
|
352
|
+
end
|
353
|
+
|
354
|
+
context 'using fetch_schema_by_id' do
|
355
|
+
subject { avro.fetch_schema_by_id(schema_id) }
|
356
|
+
|
357
|
+
before do
|
358
|
+
allow(registry).to receive(:fetch).with(schema_id).and_return(schema_json)
|
359
|
+
end
|
360
|
+
|
361
|
+
it 'gets schema from registry' do
|
362
|
+
expect(subject).to eq([schema, schema_id])
|
363
|
+
end
|
364
|
+
end
|
365
|
+
|
366
|
+
context 'using register_schema' do
|
367
|
+
let(:schema_name) { 'schema_name' }
|
368
|
+
|
369
|
+
let(:namespace) { 'namespace' }
|
370
|
+
|
371
|
+
before do
|
372
|
+
allow(schema_store).to receive(:find).with(schema_name, namespace).and_return(schema)
|
373
|
+
end
|
374
|
+
|
375
|
+
context 'when subject is not set' do
|
376
|
+
subject { avro.register_schema(schema_name: schema_name, namespace: namespace) }
|
377
|
+
|
378
|
+
before do
|
379
|
+
allow(registry).to receive(:register).with(schema.fullname, schema).and_return(schema_id)
|
380
|
+
end
|
381
|
+
|
382
|
+
it 'registers schema in registry' do
|
383
|
+
expect(subject).to eq([schema, schema_id])
|
384
|
+
end
|
385
|
+
end
|
386
|
+
|
387
|
+
context 'when subject is set' do
|
388
|
+
subject { avro.register_schema(schema_name: schema_name, namespace: namespace, subject: subj) }
|
389
|
+
|
390
|
+
let(:subj) { 'subject' }
|
391
|
+
|
392
|
+
before do
|
393
|
+
allow(registry).to receive(:register).with(subj, schema).and_return(schema_id)
|
394
|
+
end
|
395
|
+
|
396
|
+
it 'registers schema in registry' do
|
397
|
+
expect(subject).to eq([schema, schema_id])
|
398
|
+
end
|
399
|
+
end
|
400
|
+
end
|
401
|
+
end
|
300
402
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: avro_turf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Schierbeck
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-08-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: avro
|