schema_registry_client 0.0.8 → 0.0.10
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 +4 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +1 -1
- data/Rakefile +1 -1
- data/lib/schema_registry_client/avro_schema_store.rb +8 -8
- data/lib/schema_registry_client/cached_confluent_schema_registry.rb +5 -5
- data/lib/schema_registry_client/confluent_schema_registry.rb +17 -12
- data/lib/schema_registry_client/output/json_schema.rb +12 -12
- data/lib/schema_registry_client/output/proto_text.rb +45 -45
- data/lib/schema_registry_client/schema/avro.rb +8 -8
- data/lib/schema_registry_client/schema/base.rb +4 -4
- data/lib/schema_registry_client/schema/proto_json_schema.rb +3 -3
- data/lib/schema_registry_client/schema/protobuf.rb +20 -20
- data/lib/schema_registry_client/version.rb +1 -1
- data/lib/schema_registry_client.rb +19 -19
- data/schema_registry_client.gemspec +20 -20
- data/spec/decoding_spec.rb +51 -51
- data/spec/encoding_spec.rb +80 -88
- data/spec/json_schema_spec.rb +2 -2
- data/spec/proto_text_spec.rb +1 -1
- data/spec/spec_helper.rb +5 -5
- metadata +1 -1
data/spec/encoding_spec.rb
CHANGED
|
@@ -1,111 +1,111 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
RSpec.describe
|
|
3
|
+
RSpec.describe "encoding" do
|
|
4
4
|
let(:schema_registry_client) do
|
|
5
5
|
SchemaRegistry::Client.new(
|
|
6
|
-
registry_url:
|
|
6
|
+
registry_url: "http://localhost:8081"
|
|
7
7
|
)
|
|
8
8
|
end
|
|
9
9
|
|
|
10
|
-
it
|
|
10
|
+
it "should encode a simple message" do
|
|
11
11
|
schema = File.read("#{__dir__}/schemas/simple/simple.proto")
|
|
12
|
-
stub = stub_request(:post,
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
msg = Simple::V1::SimpleMessage.new(name:
|
|
17
|
-
encoded = schema_registry_client.encode(msg, subject:
|
|
12
|
+
stub = stub_request(:post, "http://localhost:8081/subjects/simple/versions")
|
|
13
|
+
.with(body: {"schemaType" => "PROTOBUF",
|
|
14
|
+
"references" => [],
|
|
15
|
+
"schema" => schema}).to_return_json(body: {id: 15})
|
|
16
|
+
msg = Simple::V1::SimpleMessage.new(name: "my name")
|
|
17
|
+
encoded = schema_registry_client.encode(msg, subject: "simple")
|
|
18
18
|
expect(encoded).to eq("\u0000\u0000\u0000\u0000\u000F\u0000#{msg.to_proto}")
|
|
19
19
|
|
|
20
20
|
# if we do it again we should not see any more requests
|
|
21
|
-
encoded2 = schema_registry_client.encode(msg, subject:
|
|
21
|
+
encoded2 = schema_registry_client.encode(msg, subject: "simple")
|
|
22
22
|
expect(encoded2).to eq(encoded)
|
|
23
23
|
|
|
24
24
|
expect(stub).to have_been_requested.once
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
-
it
|
|
27
|
+
it "should encode a complex message" do
|
|
28
28
|
schema = File.read("#{__dir__}/schemas/referenced/referer.proto")
|
|
29
29
|
dep_schema = File.read("#{__dir__}/schemas/simple/simple.proto")
|
|
30
|
-
dep_stub = stub_request(:post,
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
version_stub = stub_request(:get,
|
|
35
|
-
|
|
36
|
-
stub = stub_request(:post,
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
30
|
+
dep_stub = stub_request(:post, "http://localhost:8081/subjects/simple%2Fsimple.proto/versions")
|
|
31
|
+
.with(body: {"schemaType" => "PROTOBUF",
|
|
32
|
+
"references" => [],
|
|
33
|
+
"schema" => dep_schema}).to_return_json(body: {id: 15})
|
|
34
|
+
version_stub = stub_request(:get, "http://localhost:8081/schemas/ids/15/versions")
|
|
35
|
+
.to_return_json(body: [{version: 1, subject: "simple/simple.proto"}])
|
|
36
|
+
stub = stub_request(:post, "http://localhost:8081/subjects/referenced/versions")
|
|
37
|
+
.with(body: {"schemaType" => "PROTOBUF",
|
|
38
|
+
"references" => [
|
|
39
|
+
{
|
|
40
|
+
name: "simple/simple.proto",
|
|
41
|
+
subject: "simple/simple.proto",
|
|
42
|
+
version: 1
|
|
43
|
+
}
|
|
44
|
+
],
|
|
45
|
+
"schema" => schema}).to_return_json(body: {id: 20})
|
|
46
46
|
msg = Referenced::V1::MessageB::MessageBA.new(
|
|
47
|
-
simple: Simple::V1::SimpleMessage.new(name:
|
|
47
|
+
simple: Simple::V1::SimpleMessage.new(name: "my name")
|
|
48
48
|
)
|
|
49
|
-
encoded = schema_registry_client.encode(msg, subject:
|
|
49
|
+
encoded = schema_registry_client.encode(msg, subject: "referenced")
|
|
50
50
|
expect(encoded).to eq("\u0000\u0000\u0000\u0000\u0014\u0004\u0002\u0000#{msg.to_proto}")
|
|
51
51
|
|
|
52
52
|
# if we do it again we should not see any more requests
|
|
53
|
-
encoded2 = schema_registry_client.encode(msg, subject:
|
|
53
|
+
encoded2 = schema_registry_client.encode(msg, subject: "referenced")
|
|
54
54
|
expect(encoded2).to eq(encoded)
|
|
55
55
|
expect(stub).to have_been_requested.once
|
|
56
56
|
expect(dep_stub).to have_been_requested.once
|
|
57
57
|
expect(version_stub).to have_been_requested.once
|
|
58
58
|
end
|
|
59
59
|
|
|
60
|
-
describe
|
|
60
|
+
describe "with JSON" do
|
|
61
61
|
let(:schema_registry_client) do
|
|
62
62
|
SchemaRegistry::Client.new(
|
|
63
|
-
registry_url:
|
|
63
|
+
registry_url: "http://localhost:8081",
|
|
64
64
|
schema_type: SchemaRegistry::Schema::ProtoJsonSchema.new
|
|
65
65
|
)
|
|
66
66
|
end
|
|
67
67
|
|
|
68
|
-
it
|
|
68
|
+
it "should encode a simple message" do
|
|
69
69
|
schema = File.read("#{__dir__}/schemas/simple/simple.json").strip
|
|
70
|
-
stub = stub_request(:post,
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
msg = Simple::V1::SimpleMessage.new(name:
|
|
75
|
-
encoded = schema_registry_client.encode(msg, subject:
|
|
70
|
+
stub = stub_request(:post, "http://localhost:8081/subjects/simple/versions")
|
|
71
|
+
.with(body: {"schemaType" => "JSON",
|
|
72
|
+
"references" => [],
|
|
73
|
+
"schema" => schema}).to_return_json(body: {id: 15})
|
|
74
|
+
msg = Simple::V1::SimpleMessage.new(name: "my name")
|
|
75
|
+
encoded = schema_registry_client.encode(msg, subject: "simple")
|
|
76
76
|
expect(encoded).to eq("\u0000\u0000\u0000\u0000\u000F{\"name\":\"my name\"}")
|
|
77
77
|
|
|
78
78
|
# if we do it again we should not see any more requests
|
|
79
|
-
encoded2 = schema_registry_client.encode(msg, subject:
|
|
79
|
+
encoded2 = schema_registry_client.encode(msg, subject: "simple")
|
|
80
80
|
expect(encoded2).to eq(encoded)
|
|
81
81
|
|
|
82
82
|
expect(stub).to have_been_requested.once
|
|
83
83
|
end
|
|
84
84
|
|
|
85
|
-
it
|
|
85
|
+
it "should encode a complex message" do
|
|
86
86
|
schema = File.read("#{__dir__}/schemas/referenced/referenced.json").strip
|
|
87
|
-
stub = stub_request(:post,
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
87
|
+
stub = stub_request(:post, "http://localhost:8081/subjects/referenced/versions")
|
|
88
|
+
.with(body: {"schemaType" => "JSON",
|
|
89
|
+
"references" => [],
|
|
90
|
+
"schema" => schema}).to_return_json(body: {id: 20})
|
|
91
91
|
msg = Referenced::V1::MessageB::MessageBA.new(
|
|
92
|
-
simple: Simple::V1::SimpleMessage.new(name:
|
|
92
|
+
simple: Simple::V1::SimpleMessage.new(name: "my name")
|
|
93
93
|
)
|
|
94
|
-
encoded = schema_registry_client.encode(msg, subject:
|
|
94
|
+
encoded = schema_registry_client.encode(msg, subject: "referenced")
|
|
95
95
|
expect(encoded).to eq("\u0000\u0000\u0000\u0000\u0014{\"simple\":{\"name\":\"my name\"}}")
|
|
96
96
|
|
|
97
97
|
# if we do it again we should not see any more requests
|
|
98
|
-
encoded2 = schema_registry_client.encode(msg, subject:
|
|
98
|
+
encoded2 = schema_registry_client.encode(msg, subject: "referenced")
|
|
99
99
|
expect(encoded2).to eq(encoded)
|
|
100
100
|
expect(stub).to have_been_requested.once
|
|
101
101
|
end
|
|
102
102
|
end
|
|
103
103
|
|
|
104
|
-
describe
|
|
104
|
+
describe "with Avro" do
|
|
105
105
|
let(:schema_registry_client) do
|
|
106
106
|
SchemaRegistry.avro_schema_path = "#{__dir__}/schemas"
|
|
107
107
|
SchemaRegistry::Client.new(
|
|
108
|
-
registry_url:
|
|
108
|
+
registry_url: "http://localhost:8081",
|
|
109
109
|
schema_type: SchemaRegistry::Schema::Avro.new
|
|
110
110
|
)
|
|
111
111
|
end
|
|
@@ -114,74 +114,68 @@ RSpec.describe 'encoding' do
|
|
|
114
114
|
SchemaRegistry.avro_schema_path = nil
|
|
115
115
|
end
|
|
116
116
|
|
|
117
|
-
it
|
|
117
|
+
it "should encode a simple message" do
|
|
118
118
|
schema = File.read("#{__dir__}/schemas/simple/v1/SimpleMessage.avsc")
|
|
119
|
-
stub = stub_request(:post,
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
msg = { 'name' => 'my name' }
|
|
124
|
-
encoded = schema_registry_client.encode(msg, subject: 'simple', schema_name: 'simple.v1.SimpleMessage')
|
|
119
|
+
stub = stub_request(:post, "http://localhost:8081/subjects/simple/versions")
|
|
120
|
+
.with(body: {"schema" => schema}).to_return_json(body: {id: 15})
|
|
121
|
+
msg = {"name" => "my name"}
|
|
122
|
+
encoded = schema_registry_client.encode(msg, subject: "simple", schema_name: "simple.v1.SimpleMessage")
|
|
125
123
|
# Avro encoding: magic byte (0x00) + schema id (4 bytes, big-endian) + Avro binary data
|
|
126
124
|
# "my name" encoded as Avro string: length (0x0E = 14) + "my name" bytes
|
|
127
125
|
expect(encoded).to eq("\u0000\u0000\u0000\u0000\u000F\u000Emy name")
|
|
128
126
|
|
|
129
127
|
# if we do it again we should not see any more requests
|
|
130
|
-
encoded2 = schema_registry_client.encode(msg, subject:
|
|
128
|
+
encoded2 = schema_registry_client.encode(msg, subject: "simple", schema_name: "simple.v1.SimpleMessage")
|
|
131
129
|
expect(encoded2).to eq(encoded)
|
|
132
130
|
|
|
133
131
|
expect(stub).to have_been_requested.once
|
|
134
132
|
end
|
|
135
133
|
|
|
136
|
-
it
|
|
134
|
+
it "should encode a complex message with nested record" do
|
|
137
135
|
schema = File.read("#{__dir__}/schemas/referenced/v1/MessageBA.avsc")
|
|
138
|
-
stub = stub_request(:post,
|
|
139
|
-
|
|
140
|
-
'references' => [],
|
|
141
|
-
'schema' => schema }).to_return_json(body: { id: 20 })
|
|
136
|
+
stub = stub_request(:post, "http://localhost:8081/subjects/referenced/versions")
|
|
137
|
+
.with(body: {"schema" => schema}).to_return_json(body: {id: 20})
|
|
142
138
|
msg = {
|
|
143
|
-
|
|
144
|
-
|
|
139
|
+
"simple" => {
|
|
140
|
+
"name" => "my name"
|
|
145
141
|
}
|
|
146
142
|
}
|
|
147
|
-
encoded = schema_registry_client.encode(msg, subject:
|
|
143
|
+
encoded = schema_registry_client.encode(msg, subject: "referenced", schema_name: "referenced.v1.MessageBA")
|
|
148
144
|
# Avro encoding: magic byte + schema id + Avro binary for nested record
|
|
149
145
|
expect(encoded).to eq("\u0000\u0000\u0000\u0000\u0014\u000Emy name")
|
|
150
146
|
|
|
151
147
|
# if we do it again we should not see any more requests
|
|
152
|
-
encoded2 = schema_registry_client.encode(msg, subject:
|
|
148
|
+
encoded2 = schema_registry_client.encode(msg, subject: "referenced", schema_name: "referenced.v1.MessageBA")
|
|
153
149
|
expect(encoded2).to eq(encoded)
|
|
154
150
|
expect(stub).to have_been_requested.once
|
|
155
151
|
end
|
|
156
152
|
|
|
157
|
-
it
|
|
153
|
+
it "should handle multiple fields" do
|
|
158
154
|
# Create a temporary schema file for testing
|
|
159
155
|
multi_schema_path = "#{__dir__}/schemas/test/v1"
|
|
160
156
|
FileUtils.mkdir_p(multi_schema_path)
|
|
161
157
|
|
|
162
158
|
multi_schema = {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
{
|
|
168
|
-
{
|
|
159
|
+
"type" => "record",
|
|
160
|
+
"name" => "MultiFieldMessage",
|
|
161
|
+
"namespace" => "test.v1",
|
|
162
|
+
"fields" => [
|
|
163
|
+
{"name" => "name", "type" => "string"},
|
|
164
|
+
{"name" => "age", "type" => "int"}
|
|
169
165
|
]
|
|
170
166
|
}
|
|
171
167
|
schema_json = JSON.pretty_generate(multi_schema)
|
|
172
168
|
File.write("#{multi_schema_path}/MultiFieldMessage.avsc", schema_json)
|
|
173
169
|
|
|
174
|
-
stub = stub_request(:post,
|
|
175
|
-
|
|
176
|
-
'references' => [],
|
|
177
|
-
'schema' => schema_json }).to_return_json(body: { id: 25 })
|
|
170
|
+
stub = stub_request(:post, "http://localhost:8081/subjects/multi/versions")
|
|
171
|
+
.with(body: {"schema" => schema_json}).to_return_json(body: {id: 25})
|
|
178
172
|
|
|
179
|
-
msg = {
|
|
180
|
-
encoded = schema_registry_client.encode(msg, subject:
|
|
173
|
+
msg = {"name" => "Alice", "age" => 30}
|
|
174
|
+
encoded = schema_registry_client.encode(msg, subject: "multi", schema_name: "test.v1.MultiFieldMessage")
|
|
181
175
|
|
|
182
176
|
# Verify encoding starts with magic byte and schema id
|
|
183
177
|
expect(encoded[0]).to eq("\u0000")
|
|
184
|
-
expect(encoded[1..4].unpack1(
|
|
178
|
+
expect(encoded[1..4].unpack1("N")).to eq(25)
|
|
185
179
|
|
|
186
180
|
expect(stub).to have_been_requested.once
|
|
187
181
|
|
|
@@ -189,18 +183,16 @@ RSpec.describe 'encoding' do
|
|
|
189
183
|
FileUtils.rm_rf("#{__dir__}/schemas/test")
|
|
190
184
|
end
|
|
191
185
|
|
|
192
|
-
it
|
|
186
|
+
it "should validate schema before encoding" do
|
|
193
187
|
schema = File.read("#{__dir__}/schemas/simple/v1/SimpleMessage.avsc")
|
|
194
|
-
stub_request(:post,
|
|
195
|
-
.with(body: {
|
|
196
|
-
'references' => [],
|
|
197
|
-
'schema' => schema }).to_return_json(body: { id: 15 })
|
|
188
|
+
stub_request(:post, "http://localhost:8081/subjects/simple/versions")
|
|
189
|
+
.with(body: {"schema" => schema}).to_return_json(body: {id: 15})
|
|
198
190
|
|
|
199
191
|
# Invalid message - missing required field
|
|
200
|
-
msg = {
|
|
192
|
+
msg = {"invalid_field" => "value"}
|
|
201
193
|
|
|
202
194
|
expect do
|
|
203
|
-
schema_registry_client.encode(msg, subject:
|
|
195
|
+
schema_registry_client.encode(msg, subject: "simple", schema_name: "simple.v1.SimpleMessage")
|
|
204
196
|
end.to raise_error(Avro::SchemaValidator::ValidationError)
|
|
205
197
|
end
|
|
206
198
|
end
|
data/spec/json_schema_spec.rb
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
3
|
+
require "schema_registry_client/output/json_schema"
|
|
4
4
|
|
|
5
5
|
RSpec.describe SchemaRegistry::Output::JsonSchema do
|
|
6
|
-
it
|
|
6
|
+
it "should output as expected" do
|
|
7
7
|
output = described_class.output(Everything::V1::TestAllTypes.descriptor.to_proto)
|
|
8
8
|
|
|
9
9
|
expected = File.read("#{__dir__}/schemas/everything/everything.json")
|
data/spec/proto_text_spec.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
RSpec.describe SchemaRegistry::Output::ProtoText do
|
|
4
|
-
it
|
|
4
|
+
it "should output as expected" do
|
|
5
5
|
output = described_class.output(Everything::V1::TestAllTypes.descriptor.file_descriptor.to_proto)
|
|
6
6
|
|
|
7
7
|
expected = File.read("#{__dir__}/schemas/everything/everything.proto")
|
data/spec/spec_helper.rb
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
3
|
+
require "simplecov"
|
|
4
4
|
SimpleCov.start
|
|
5
5
|
|
|
6
|
-
$LOAD_PATH.unshift(File.expand_path(
|
|
7
|
-
$LOAD_PATH.unshift(File.expand_path(
|
|
6
|
+
$LOAD_PATH.unshift(File.expand_path("../lib", __dir__))
|
|
7
|
+
$LOAD_PATH.unshift(File.expand_path("gen", __dir__))
|
|
8
8
|
Dir["#{__dir__}/gen/**/*.rb"].each { |file| require file }
|
|
9
|
-
require
|
|
10
|
-
require
|
|
9
|
+
require "schema_registry_client"
|
|
10
|
+
require "webmock/rspec"
|
|
11
11
|
|
|
12
12
|
RSpec.configure do |config|
|
|
13
13
|
config.full_backtrace = true
|