schema_registry_client 0.0.11.pre.beta1 → 0.0.11
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/.gitignore +1 -0
- data/CHANGELOG.md +4 -0
- data/Gemfile.lock +1 -1
- data/lib/schema_registry_client/cached_confluent_schema_registry.rb +26 -11
- data/lib/schema_registry_client/confluent_schema_registry.rb +0 -4
- data/lib/schema_registry_client/schema/avro.rb +8 -5
- data/lib/schema_registry_client/version.rb +1 -1
- data/lib/schema_registry_client.rb +6 -3
- data/spec/decoding_spec.rb +123 -5
- data/spec/encoding_spec.rb +145 -5
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: '09a16bc0d516a981c823ec6aef2c356cae10f4dca61279870b741741c1f9baa4'
|
|
4
|
+
data.tar.gz: 7bbcbe0b5b6ffeb494c264983e137fc1864387440bc9ecc41b21f2405d15a361
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 88a82ff70e5fdc2a5b5b783630a218a58b02cdc1f2513470ffd31f14e1d75356eff1f1ccef7e684954ce9d72ce07571e71b50900e61e1cf98de998d3513a5718
|
|
7
|
+
data.tar.gz: 9c5a98b3299615b052a8eb2f9f4356cc75dea85b283c5cee8e8759b97c373be17350a7df9d3f9232200cf3d6f406dd64ddff80d4292d5be3982807779f9ae4b9
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## UNRELEASED
|
|
9
9
|
|
|
10
|
+
# 0.0.11 - 2026-02-20
|
|
11
|
+
|
|
12
|
+
* Fixes for caching working correctly and ensuring we don't recalculate / re-parse Avro schemas
|
|
13
|
+
|
|
10
14
|
# 0.0.10 - 2026-02-11
|
|
11
15
|
|
|
12
16
|
* Fix: Do not send `schemaType` or `references` if schema type is `AVRO`, for backwards compatibility with older schema registries.
|
data/Gemfile.lock
CHANGED
|
@@ -8,6 +8,7 @@ module SchemaRegistry
|
|
|
8
8
|
@schemas_by_id = {}
|
|
9
9
|
@ids_by_schema = {}
|
|
10
10
|
@versions_by_subject_and_id = {}
|
|
11
|
+
@mutex = Mutex.new
|
|
11
12
|
end
|
|
12
13
|
|
|
13
14
|
# Delegate the following methods to the upstream
|
|
@@ -20,25 +21,37 @@ module SchemaRegistry
|
|
|
20
21
|
# @param id [Integer] the schema ID to fetch
|
|
21
22
|
# @return [String] the schema string stored in the registry for the given id
|
|
22
23
|
def fetch(id)
|
|
23
|
-
@
|
|
24
|
+
@mutex.synchronize do
|
|
25
|
+
@schemas_by_id[id] ||= @upstream.fetch(id)
|
|
26
|
+
end
|
|
24
27
|
end
|
|
25
28
|
|
|
26
29
|
# @param id [Integer] the schema ID to fetch
|
|
27
30
|
# @param subject [String] the subject to fetch the version for
|
|
28
31
|
# @return [Integer, nil] the version of the schema for the given subject and id, or nil if not found
|
|
29
32
|
def fetch_version(id, subject)
|
|
30
|
-
|
|
31
|
-
|
|
33
|
+
@mutex.synchronize do
|
|
34
|
+
key = [subject, id]
|
|
35
|
+
return @versions_by_subject_and_id[key] if @versions_by_subject_and_id[key]
|
|
32
36
|
|
|
33
|
-
|
|
34
|
-
|
|
37
|
+
results = @upstream.schema_subject_versions(id)
|
|
38
|
+
@versions_by_subject_and_id[key] = results&.find { |r| r["subject"] == subject }&.dig("version")
|
|
39
|
+
end
|
|
35
40
|
end
|
|
36
41
|
|
|
37
42
|
# @param subject [String] the subject to check
|
|
38
43
|
# @param schema [String] the schema text to check
|
|
39
44
|
# @return [Boolean] true if we know the schema has been registered for that subject.
|
|
40
45
|
def registered?(subject, schema)
|
|
41
|
-
@
|
|
46
|
+
@mutex.synchronize do
|
|
47
|
+
@ids_by_schema.key?([subject, schema])
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def fetch_id(subject, schema)
|
|
52
|
+
@mutex.synchronize do
|
|
53
|
+
@ids_by_schema[[subject, schema]]
|
|
54
|
+
end
|
|
42
55
|
end
|
|
43
56
|
|
|
44
57
|
# @param subject [String] the subject to register the schema under
|
|
@@ -46,12 +59,14 @@ module SchemaRegistry
|
|
|
46
59
|
# @param references [Array<Hash>] optional references to other schemas
|
|
47
60
|
# @param schema_type [String]
|
|
48
61
|
def register(subject, schema, references: [], schema_type: "PROTOBUF")
|
|
49
|
-
|
|
62
|
+
@mutex.synchronize do
|
|
63
|
+
key = [subject, schema]
|
|
50
64
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
65
|
+
@ids_by_schema[key] ||= @upstream.register(subject,
|
|
66
|
+
schema,
|
|
67
|
+
references: references,
|
|
68
|
+
schema_type: schema_type)
|
|
69
|
+
end
|
|
55
70
|
end
|
|
56
71
|
end
|
|
57
72
|
end
|
|
@@ -24,9 +24,6 @@ module SchemaRegistry
|
|
|
24
24
|
resolv_resolver: nil,
|
|
25
25
|
retry_limit: nil
|
|
26
26
|
)
|
|
27
|
-
if SchemaRegistry.debug
|
|
28
|
-
logger.info("Creating Confluent Schema Registry client with url: #{url}, schema_context: #{schema_context}, user: #{user}, path_prefix: #{path_prefix}")
|
|
29
|
-
end
|
|
30
27
|
@path_prefix = path_prefix
|
|
31
28
|
@schema_context_prefix = schema_context.nil? ? "" : ":.#{schema_context}:"
|
|
32
29
|
@schema_context_options = schema_context.nil? ? {} : {query: {subject: @schema_context_prefix}}
|
|
@@ -76,7 +73,6 @@ module SchemaRegistry
|
|
|
76
73
|
# @param references [Array<Hash>] optional references to other schemas
|
|
77
74
|
# @return [Integer] the ID of the registered schema
|
|
78
75
|
def register(subject, schema, references: [], schema_type: "PROTOBUF")
|
|
79
|
-
puts("schema_type #{schema_type}")
|
|
80
76
|
body = {schema: schema.to_s}
|
|
81
77
|
# Not all schema registry versions support schemaType
|
|
82
78
|
if schema_type != "AVRO"
|
|
@@ -22,7 +22,10 @@ module SchemaRegistry
|
|
|
22
22
|
@schema_store ||= SchemaRegistry::AvroSchemaStore.new(
|
|
23
23
|
path: SchemaRegistry.avro_schema_path || DEFAULT_SCHEMAS_PATH
|
|
24
24
|
)
|
|
25
|
-
@
|
|
25
|
+
unless @schemas_loaded
|
|
26
|
+
@schema_store.load_schemas!
|
|
27
|
+
@schemas_loaded = true
|
|
28
|
+
end
|
|
26
29
|
@schema_store
|
|
27
30
|
end
|
|
28
31
|
|
|
@@ -44,10 +47,10 @@ module SchemaRegistry
|
|
|
44
47
|
end
|
|
45
48
|
|
|
46
49
|
def decode(stream, schema_text)
|
|
47
|
-
#
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
50
|
+
# Cache parsed writer schemas to avoid re-parsing on every decode
|
|
51
|
+
@parsed_writers_schemas ||= {}
|
|
52
|
+
@parsed_writers_schemas[schema_text] ||= ::Avro::Schema.parse(schema_text)
|
|
53
|
+
writers_schema = @parsed_writers_schemas[schema_text]
|
|
51
54
|
decoder = ::Avro::IO::BinaryDecoder.new(stream)
|
|
52
55
|
|
|
53
56
|
# Try to find the reader schema locally, fall back to writer schema
|
|
@@ -14,8 +14,6 @@ module SchemaRegistry
|
|
|
14
14
|
|
|
15
15
|
class << self
|
|
16
16
|
attr_accessor :avro_schema_path
|
|
17
|
-
|
|
18
|
-
attr_accessor :debug
|
|
19
17
|
end
|
|
20
18
|
|
|
21
19
|
class Client
|
|
@@ -136,7 +134,12 @@ module SchemaRegistry
|
|
|
136
134
|
|
|
137
135
|
def register_schema(message, subject, schema_text: nil, schema_name: nil)
|
|
138
136
|
schema_text ||= @schema.schema_text(message, schema_name: schema_name)
|
|
139
|
-
|
|
137
|
+
|
|
138
|
+
# Fast path: if already registered, return the cached ID without
|
|
139
|
+
# resolving dependencies again.
|
|
140
|
+
if @registry.registered?(subject, schema_text)
|
|
141
|
+
return @registry.fetch_id(subject, schema_text)
|
|
142
|
+
end
|
|
140
143
|
|
|
141
144
|
# register dependencies first
|
|
142
145
|
dependencies = @schema.dependencies(message)
|
data/spec/decoding_spec.rb
CHANGED
|
@@ -60,18 +60,19 @@ RSpec.describe "decoding" do
|
|
|
60
60
|
end
|
|
61
61
|
|
|
62
62
|
describe "with Avro" do
|
|
63
|
-
|
|
63
|
+
around(:each) do |ex|
|
|
64
64
|
SchemaRegistry.avro_schema_path = "#{__dir__}/schemas"
|
|
65
|
+
ex.run
|
|
66
|
+
SchemaRegistry.avro_schema_path = nil
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
let(:schema_registry_client) do
|
|
65
70
|
SchemaRegistry::Client.new(
|
|
66
71
|
registry_url: "http://localhost:8081",
|
|
67
72
|
schema_type: SchemaRegistry::Schema::Avro.new
|
|
68
73
|
)
|
|
69
74
|
end
|
|
70
75
|
|
|
71
|
-
after do
|
|
72
|
-
SchemaRegistry.avro_schema_path = nil
|
|
73
|
-
end
|
|
74
|
-
|
|
75
76
|
it "should decode a simple message" do
|
|
76
77
|
schema = File.read("#{__dir__}/schemas/simple/v1/SimpleMessage.avsc")
|
|
77
78
|
stub = stub_request(:get, "http://localhost:8081/schemas/ids/15")
|
|
@@ -180,4 +181,121 @@ RSpec.describe "decoding" do
|
|
|
180
181
|
end.to raise_error(/Schema|not found/i)
|
|
181
182
|
end
|
|
182
183
|
end
|
|
184
|
+
|
|
185
|
+
describe "caching" do
|
|
186
|
+
it "should not fetch the same schema ID twice (Protobuf)" do
|
|
187
|
+
schema = File.read("#{__dir__}/schemas/simple/simple.proto")
|
|
188
|
+
stub = stub_request(:get, "http://localhost:8081/schemas/ids/15")
|
|
189
|
+
.to_return_json(body: {schema: schema})
|
|
190
|
+
msg = Simple::V1::SimpleMessage.new(name: "my name")
|
|
191
|
+
encoded = "\u0000\u0000\u0000\u0000\u000F\u0000#{msg.to_proto}"
|
|
192
|
+
|
|
193
|
+
3.times { schema_registry_client.decode(encoded) }
|
|
194
|
+
|
|
195
|
+
expect(stub).to have_been_requested.once
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
it "should fetch different schema IDs independently" do
|
|
199
|
+
simple_schema = File.read("#{__dir__}/schemas/simple/simple.proto")
|
|
200
|
+
stub_15 = stub_request(:get, "http://localhost:8081/schemas/ids/15")
|
|
201
|
+
.to_return_json(body: {schema: simple_schema})
|
|
202
|
+
|
|
203
|
+
ref_schema = File.read("#{__dir__}/schemas/referenced/referer.proto")
|
|
204
|
+
stub_20 = stub_request(:get, "http://localhost:8081/schemas/ids/20")
|
|
205
|
+
.to_return_json(body: {schema: ref_schema})
|
|
206
|
+
|
|
207
|
+
msg1 = Simple::V1::SimpleMessage.new(name: "my name")
|
|
208
|
+
encoded1 = "\u0000\u0000\u0000\u0000\u000F\u0000#{msg1.to_proto}"
|
|
209
|
+
|
|
210
|
+
msg2 = Referenced::V1::MessageB::MessageBA.new(
|
|
211
|
+
simple: Simple::V1::SimpleMessage.new(name: "my name")
|
|
212
|
+
)
|
|
213
|
+
encoded2 = "\u0000\u0000\u0000\u0000\u0014\u0004\u0002\u0000#{msg2.to_proto}"
|
|
214
|
+
|
|
215
|
+
# Decode both messages
|
|
216
|
+
schema_registry_client.decode(encoded1)
|
|
217
|
+
schema_registry_client.decode(encoded2)
|
|
218
|
+
|
|
219
|
+
# Each schema fetched exactly once
|
|
220
|
+
expect(stub_15).to have_been_requested.once
|
|
221
|
+
expect(stub_20).to have_been_requested.once
|
|
222
|
+
|
|
223
|
+
# Decode again - no new requests
|
|
224
|
+
schema_registry_client.decode(encoded1)
|
|
225
|
+
schema_registry_client.decode(encoded2)
|
|
226
|
+
|
|
227
|
+
expect(stub_15).to have_been_requested.once
|
|
228
|
+
expect(stub_20).to have_been_requested.once
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
it "should not share cache between different client instances" do
|
|
232
|
+
schema = File.read("#{__dir__}/schemas/simple/simple.proto")
|
|
233
|
+
stub = stub_request(:get, "http://localhost:8081/schemas/ids/15")
|
|
234
|
+
.to_return_json(body: {schema: schema})
|
|
235
|
+
msg = Simple::V1::SimpleMessage.new(name: "my name")
|
|
236
|
+
encoded = "\u0000\u0000\u0000\u0000\u000F\u0000#{msg.to_proto}"
|
|
237
|
+
|
|
238
|
+
schema_registry_client.decode(encoded)
|
|
239
|
+
|
|
240
|
+
# A second client should make its own request
|
|
241
|
+
client2 = SchemaRegistry::Client.new(registry_url: "http://localhost:8081")
|
|
242
|
+
client2.decode(encoded)
|
|
243
|
+
|
|
244
|
+
expect(stub).to have_been_requested.twice
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
describe "with Avro" do
|
|
248
|
+
around(:each) do |ex|
|
|
249
|
+
SchemaRegistry.avro_schema_path = "#{__dir__}/schemas"
|
|
250
|
+
ex.run
|
|
251
|
+
SchemaRegistry.avro_schema_path = nil
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
let(:schema_registry_client) do
|
|
255
|
+
SchemaRegistry::Client.new(
|
|
256
|
+
registry_url: "http://localhost:8081",
|
|
257
|
+
schema_type: SchemaRegistry::Schema::Avro.new
|
|
258
|
+
)
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
it "should not fetch the same schema ID twice" do
|
|
262
|
+
schema = File.read("#{__dir__}/schemas/simple/v1/SimpleMessage.avsc")
|
|
263
|
+
stub = stub_request(:get, "http://localhost:8081/schemas/ids/15")
|
|
264
|
+
.to_return_json(body: {schema: schema})
|
|
265
|
+
|
|
266
|
+
encoded = "\u0000\u0000\u0000\u0000\u000F\u000Emy name"
|
|
267
|
+
|
|
268
|
+
3.times { schema_registry_client.decode(encoded) }
|
|
269
|
+
|
|
270
|
+
expect(stub).to have_been_requested.once
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
it "should fetch different schema IDs independently" do
|
|
274
|
+
simple_schema = File.read("#{__dir__}/schemas/simple/v1/SimpleMessage.avsc")
|
|
275
|
+
stub_15 = stub_request(:get, "http://localhost:8081/schemas/ids/15")
|
|
276
|
+
.to_return_json(body: {schema: simple_schema})
|
|
277
|
+
|
|
278
|
+
nested_schema = File.read("#{__dir__}/schemas/referenced/v1/MessageBA.avsc")
|
|
279
|
+
stub_20 = stub_request(:get, "http://localhost:8081/schemas/ids/20")
|
|
280
|
+
.to_return_json(body: {schema: nested_schema})
|
|
281
|
+
|
|
282
|
+
encoded1 = "\u0000\u0000\u0000\u0000\u000F\u000Emy name"
|
|
283
|
+
encoded2 = "\u0000\u0000\u0000\u0000\u0014\u000Emy name"
|
|
284
|
+
|
|
285
|
+
# Decode both messages
|
|
286
|
+
schema_registry_client.decode(encoded1)
|
|
287
|
+
schema_registry_client.decode(encoded2)
|
|
288
|
+
|
|
289
|
+
expect(stub_15).to have_been_requested.once
|
|
290
|
+
expect(stub_20).to have_been_requested.once
|
|
291
|
+
|
|
292
|
+
# Decode again - no new requests
|
|
293
|
+
schema_registry_client.decode(encoded1)
|
|
294
|
+
schema_registry_client.decode(encoded2)
|
|
295
|
+
|
|
296
|
+
expect(stub_15).to have_been_requested.once
|
|
297
|
+
expect(stub_20).to have_been_requested.once
|
|
298
|
+
end
|
|
299
|
+
end
|
|
300
|
+
end
|
|
183
301
|
end
|
data/spec/encoding_spec.rb
CHANGED
|
@@ -102,18 +102,19 @@ RSpec.describe "encoding" do
|
|
|
102
102
|
end
|
|
103
103
|
|
|
104
104
|
describe "with Avro" do
|
|
105
|
-
|
|
105
|
+
around(:each) do |ex|
|
|
106
106
|
SchemaRegistry.avro_schema_path = "#{__dir__}/schemas"
|
|
107
|
+
ex.run
|
|
108
|
+
SchemaRegistry.avro_schema_path = nil
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
let(:schema_registry_client) do
|
|
107
112
|
SchemaRegistry::Client.new(
|
|
108
113
|
registry_url: "http://localhost:8081",
|
|
109
114
|
schema_type: SchemaRegistry::Schema::Avro.new
|
|
110
115
|
)
|
|
111
116
|
end
|
|
112
117
|
|
|
113
|
-
after do
|
|
114
|
-
SchemaRegistry.avro_schema_path = nil
|
|
115
|
-
end
|
|
116
|
-
|
|
117
118
|
it "should encode a simple message" do
|
|
118
119
|
schema = File.read("#{__dir__}/schemas/simple/v1/SimpleMessage.avsc")
|
|
119
120
|
stub = stub_request(:post, "http://localhost:8081/subjects/simple/versions")
|
|
@@ -196,4 +197,143 @@ RSpec.describe "encoding" do
|
|
|
196
197
|
end.to raise_error(Avro::SchemaValidator::ValidationError)
|
|
197
198
|
end
|
|
198
199
|
end
|
|
200
|
+
|
|
201
|
+
describe "caching" do
|
|
202
|
+
it "should not register the same schema twice (Protobuf)" do
|
|
203
|
+
schema = File.read("#{__dir__}/schemas/simple/simple.proto")
|
|
204
|
+
stub = stub_request(:post, "http://localhost:8081/subjects/simple/versions")
|
|
205
|
+
.with(body: {"schemaType" => "PROTOBUF",
|
|
206
|
+
"references" => [],
|
|
207
|
+
"schema" => schema}).to_return_json(body: {id: 15})
|
|
208
|
+
msg = Simple::V1::SimpleMessage.new(name: "my name")
|
|
209
|
+
|
|
210
|
+
3.times { schema_registry_client.encode(msg, subject: "simple") }
|
|
211
|
+
|
|
212
|
+
expect(stub).to have_been_requested.once
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
it "should register schemas for different subjects separately" do
|
|
216
|
+
schema = File.read("#{__dir__}/schemas/simple/simple.proto")
|
|
217
|
+
stub_a = stub_request(:post, "http://localhost:8081/subjects/subject-a/versions")
|
|
218
|
+
.with(body: {"schemaType" => "PROTOBUF",
|
|
219
|
+
"references" => [],
|
|
220
|
+
"schema" => schema}).to_return_json(body: {id: 15})
|
|
221
|
+
stub_b = stub_request(:post, "http://localhost:8081/subjects/subject-b/versions")
|
|
222
|
+
.with(body: {"schemaType" => "PROTOBUF",
|
|
223
|
+
"references" => [],
|
|
224
|
+
"schema" => schema}).to_return_json(body: {id: 16})
|
|
225
|
+
|
|
226
|
+
msg = Simple::V1::SimpleMessage.new(name: "my name")
|
|
227
|
+
|
|
228
|
+
schema_registry_client.encode(msg, subject: "subject-a")
|
|
229
|
+
schema_registry_client.encode(msg, subject: "subject-b")
|
|
230
|
+
|
|
231
|
+
# Both subjects should get their own registration
|
|
232
|
+
expect(stub_a).to have_been_requested.once
|
|
233
|
+
expect(stub_b).to have_been_requested.once
|
|
234
|
+
|
|
235
|
+
# Encoding again for either subject should not re-register
|
|
236
|
+
schema_registry_client.encode(msg, subject: "subject-a")
|
|
237
|
+
schema_registry_client.encode(msg, subject: "subject-b")
|
|
238
|
+
|
|
239
|
+
expect(stub_a).to have_been_requested.once
|
|
240
|
+
expect(stub_b).to have_been_requested.once
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
it "should not re-register dependencies on subsequent encodes (Protobuf)" do
|
|
244
|
+
schema = File.read("#{__dir__}/schemas/referenced/referer.proto")
|
|
245
|
+
dep_schema = File.read("#{__dir__}/schemas/simple/simple.proto")
|
|
246
|
+
dep_stub = stub_request(:post, "http://localhost:8081/subjects/simple%2Fsimple.proto/versions")
|
|
247
|
+
.with(body: {"schemaType" => "PROTOBUF",
|
|
248
|
+
"references" => [],
|
|
249
|
+
"schema" => dep_schema}).to_return_json(body: {id: 15})
|
|
250
|
+
version_stub = stub_request(:get, "http://localhost:8081/schemas/ids/15/versions")
|
|
251
|
+
.to_return_json(body: [{version: 1, subject: "simple/simple.proto"}])
|
|
252
|
+
stub = stub_request(:post, "http://localhost:8081/subjects/referenced/versions")
|
|
253
|
+
.with(body: {"schemaType" => "PROTOBUF",
|
|
254
|
+
"references" => [
|
|
255
|
+
{
|
|
256
|
+
name: "simple/simple.proto",
|
|
257
|
+
subject: "simple/simple.proto",
|
|
258
|
+
version: 1
|
|
259
|
+
}
|
|
260
|
+
],
|
|
261
|
+
"schema" => schema}).to_return_json(body: {id: 20})
|
|
262
|
+
msg = Referenced::V1::MessageB::MessageBA.new(
|
|
263
|
+
simple: Simple::V1::SimpleMessage.new(name: "my name")
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
3.times { schema_registry_client.encode(msg, subject: "referenced") }
|
|
267
|
+
|
|
268
|
+
expect(stub).to have_been_requested.once
|
|
269
|
+
expect(dep_stub).to have_been_requested.once
|
|
270
|
+
expect(version_stub).to have_been_requested.once
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
it "should not share cache between different client instances" do
|
|
274
|
+
schema = File.read("#{__dir__}/schemas/simple/simple.proto")
|
|
275
|
+
stub = stub_request(:post, "http://localhost:8081/subjects/simple/versions")
|
|
276
|
+
.with(body: {"schemaType" => "PROTOBUF",
|
|
277
|
+
"references" => [],
|
|
278
|
+
"schema" => schema}).to_return_json(body: {id: 15})
|
|
279
|
+
msg = Simple::V1::SimpleMessage.new(name: "my name")
|
|
280
|
+
|
|
281
|
+
schema_registry_client.encode(msg, subject: "simple")
|
|
282
|
+
|
|
283
|
+
# A second client should make its own registration request
|
|
284
|
+
client2 = SchemaRegistry::Client.new(registry_url: "http://localhost:8081")
|
|
285
|
+
client2.encode(msg, subject: "simple")
|
|
286
|
+
|
|
287
|
+
expect(stub).to have_been_requested.twice
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
describe "with Avro" do
|
|
291
|
+
around(:each) do |ex|
|
|
292
|
+
SchemaRegistry.avro_schema_path = "#{__dir__}/schemas"
|
|
293
|
+
ex.run
|
|
294
|
+
SchemaRegistry.avro_schema_path = nil
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
let(:schema_registry_client) do
|
|
298
|
+
SchemaRegistry::Client.new(
|
|
299
|
+
registry_url: "http://localhost:8081",
|
|
300
|
+
schema_type: SchemaRegistry::Schema::Avro.new
|
|
301
|
+
)
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
it "should not register the same schema twice" do
|
|
305
|
+
schema = File.read("#{__dir__}/schemas/simple/v1/SimpleMessage.avsc")
|
|
306
|
+
stub = stub_request(:post, "http://localhost:8081/subjects/simple/versions")
|
|
307
|
+
.with(body: {"schema" => schema}).to_return_json(body: {id: 15})
|
|
308
|
+
msg = {"name" => "my name"}
|
|
309
|
+
|
|
310
|
+
3.times { schema_registry_client.encode(msg, subject: "simple", schema_name: "simple.v1.SimpleMessage") }
|
|
311
|
+
|
|
312
|
+
expect(stub).to have_been_requested.once
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
it "should register schemas for different subjects separately" do
|
|
316
|
+
schema = File.read("#{__dir__}/schemas/simple/v1/SimpleMessage.avsc")
|
|
317
|
+
stub_a = stub_request(:post, "http://localhost:8081/subjects/subject-a/versions")
|
|
318
|
+
.with(body: {"schema" => schema}).to_return_json(body: {id: 15})
|
|
319
|
+
stub_b = stub_request(:post, "http://localhost:8081/subjects/subject-b/versions")
|
|
320
|
+
.with(body: {"schema" => schema}).to_return_json(body: {id: 16})
|
|
321
|
+
|
|
322
|
+
msg = {"name" => "my name"}
|
|
323
|
+
|
|
324
|
+
schema_registry_client.encode(msg, subject: "subject-a", schema_name: "simple.v1.SimpleMessage")
|
|
325
|
+
schema_registry_client.encode(msg, subject: "subject-b", schema_name: "simple.v1.SimpleMessage")
|
|
326
|
+
|
|
327
|
+
expect(stub_a).to have_been_requested.once
|
|
328
|
+
expect(stub_b).to have_been_requested.once
|
|
329
|
+
|
|
330
|
+
# Encoding again should not re-register
|
|
331
|
+
schema_registry_client.encode(msg, subject: "subject-a", schema_name: "simple.v1.SimpleMessage")
|
|
332
|
+
schema_registry_client.encode(msg, subject: "subject-b", schema_name: "simple.v1.SimpleMessage")
|
|
333
|
+
|
|
334
|
+
expect(stub_a).to have_been_requested.once
|
|
335
|
+
expect(stub_b).to have_been_requested.once
|
|
336
|
+
end
|
|
337
|
+
end
|
|
338
|
+
end
|
|
199
339
|
end
|