avro_turf 0.8.1 → 0.11.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.
@@ -3,6 +3,7 @@ class AvroTurf::SchemaStore
3
3
  def initialize(path: nil)
4
4
  @path = path or raise "Please specify a schema path"
5
5
  @schemas = Hash.new
6
+ @mutex = Mutex.new
6
7
  end
7
8
 
8
9
  # Resolves and returns a schema.
@@ -12,9 +13,40 @@ class AvroTurf::SchemaStore
12
13
  # Returns an Avro::Schema.
13
14
  def find(name, namespace = nil)
14
15
  fullname = Avro::Name.make_fullname(name, namespace)
15
-
16
+ # Optimistic non-blocking read from @schemas
17
+ # No sense to lock the resource when all the schemas already loaded
16
18
  return @schemas[fullname] if @schemas.key?(fullname)
17
19
 
20
+ # Pessimistic blocking write to @schemas
21
+ @mutex.synchronize do
22
+ # Still need to check is the schema already loaded
23
+ return @schemas[fullname] if @schemas.key?(fullname)
24
+
25
+ load_schema!(fullname, namespace)
26
+ end
27
+ end
28
+
29
+ # Loads all schema definition files in the `schemas_dir`.
30
+ def load_schemas!
31
+ pattern = [@path, "**", "*.avsc"].join("/")
32
+
33
+ Dir.glob(pattern) do |schema_path|
34
+ # Remove the path prefix.
35
+ schema_path.sub!(/^\/?#{@path}\//, "")
36
+
37
+ # Replace `/` with `.` and chop off the file extension.
38
+ schema_name = File.basename(schema_path.tr("/", "."), ".avsc")
39
+
40
+ # Load and cache the schema.
41
+ find(schema_name)
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ # Loads single schema
48
+ # Such method is not thread-safe, do not call it of from mutex synchronization routine
49
+ def load_schema!(fullname, namespace = nil)
18
50
  *namespace, schema_name = fullname.split(".")
19
51
  schema_path = File.join(@path, *namespace, schema_name + ".avsc")
20
52
  schema_json = JSON.parse(File.read(schema_path))
@@ -29,32 +61,15 @@ class AvroTurf::SchemaStore
29
61
  # This is a hack in order to figure out exactly which type was missing. The
30
62
  # Avro gem ought to provide this data directly.
31
63
  if e.to_s =~ /"([\w\.]+)" is not a schema we know about/
32
- find($1)
64
+ load_schema!($1)
33
65
 
34
66
  # Re-resolve the original schema now that the dependency has been resolved.
35
67
  @schemas.delete(fullname)
36
- find(fullname)
68
+ load_schema!(fullname)
37
69
  else
38
70
  raise
39
71
  end
40
72
  rescue Errno::ENOENT, Errno::ENAMETOOLONG
41
73
  raise AvroTurf::SchemaNotFoundError, "could not find Avro schema at `#{schema_path}'"
42
74
  end
43
-
44
- # Loads all schema definition files in the `schemas_dir`.
45
- def load_schemas!
46
- pattern = [@path, "**", "*.avsc"].join("/")
47
-
48
- Dir.glob(pattern) do |schema_path|
49
- # Remove the path prefix.
50
- schema_path.sub!(/^\/?#{@path}\//, "")
51
-
52
- # Replace `/` with `.` and chop off the file extension.
53
- schema_name = File.basename(schema_path.tr("/", "."), ".avsc")
54
-
55
- # Load and cache the schema.
56
- find(schema_name)
57
- end
58
- end
59
-
60
75
  end
@@ -34,10 +34,21 @@ class FakeConfluentSchemaRegistryServer < Sinatra::Base
34
34
  end
35
35
 
36
36
  post "/subjects/:subject/versions" do
37
- SCHEMAS << parse_schema
37
+ schema = parse_schema
38
+ ids_for_subject = SUBJECTS[params[:subject]]
39
+
40
+ schemas_for_subject =
41
+ SCHEMAS.select
42
+ .with_index { |_, i| ids_for_subject.include?(i) }
43
+
44
+ if schemas_for_subject.include?(schema)
45
+ schema_id = SCHEMAS.index(schema)
46
+ else
47
+ SCHEMAS << schema
48
+ schema_id = SCHEMAS.size - 1
49
+ SUBJECTS[params[:subject]] = SUBJECTS[params[:subject]] << schema_id
50
+ end
38
51
 
39
- schema_id = SCHEMAS.size - 1
40
- SUBJECTS[params[:subject]] = SUBJECTS[params[:subject]] << schema_id
41
52
  { id: schema_id }.to_json
42
53
  end
43
54
 
@@ -73,6 +84,7 @@ class FakeConfluentSchemaRegistryServer < Sinatra::Base
73
84
  {
74
85
  name: params[:subject],
75
86
  version: schema_ids.index(schema_id) + 1,
87
+ id: schema_id,
76
88
  schema: schema
77
89
  }.to_json
78
90
  end
@@ -1,3 +1,3 @@
1
1
  class AvroTurf
2
- VERSION = "0.8.1"
2
+ VERSION = "0.11.0"
3
3
  end
@@ -16,8 +16,9 @@ describe AvroTurf::CachedConfluentSchemaRegistry do
16
16
 
17
17
  describe "#fetch" do
18
18
  it "caches the result of fetch" do
19
+ # multiple calls return same result, with only one upstream call
19
20
  allow(upstream).to receive(:fetch).with(id).and_return(schema)
20
- registry.fetch(id)
21
+ expect(registry.fetch(id)).to eq(schema)
21
22
  expect(registry.fetch(id)).to eq(schema)
22
23
  expect(upstream).to have_received(:fetch).exactly(1).times
23
24
  end
@@ -27,13 +28,34 @@ describe AvroTurf::CachedConfluentSchemaRegistry do
27
28
  let(:subject_name) { "a_subject" }
28
29
 
29
30
  it "caches the result of register" do
31
+ # multiple calls return same result, with only one upstream call
30
32
  allow(upstream).to receive(:register).with(subject_name, schema).and_return(id)
31
- registry.register(subject_name, schema)
33
+ expect(registry.register(subject_name, schema)).to eq(id)
32
34
  expect(registry.register(subject_name, schema)).to eq(id)
33
35
  expect(upstream).to have_received(:register).exactly(1).times
34
36
  end
35
37
  end
36
38
 
39
+ describe '#subject_version' do
40
+ let(:subject_name) { 'a_subject' }
41
+ let(:version) { 1 }
42
+ let(:schema_with_meta) do
43
+ {
44
+ subject: subject_name,
45
+ id: 1,
46
+ version: 1,
47
+ schema: schema
48
+ }
49
+ end
50
+
51
+ it 'caches the result of subject_version' do
52
+ allow(upstream).to receive(:subject_version).with(subject_name, version).and_return(schema_with_meta)
53
+ registry.subject_version(subject_name, version)
54
+ registry.subject_version(subject_name, version)
55
+ expect(upstream).to have_received(:subject_version).exactly(1).times
56
+ end
57
+ end
58
+
37
59
  it_behaves_like "a confluent schema registry client" do
38
60
  let(:upstream) { AvroTurf::ConfluentSchemaRegistry.new(registry_url, logger: logger) }
39
61
  let(:registry) { described_class.new(upstream) }
@@ -3,7 +3,19 @@ require 'avro_turf/confluent_schema_registry'
3
3
  require 'avro_turf/test/fake_confluent_schema_registry_server'
4
4
 
5
5
  describe AvroTurf::ConfluentSchemaRegistry do
6
+ let(:client_cert) { "test client cert" }
7
+ let(:client_key) { "test client key" }
8
+ let(:client_key_pass) { "test client key password" }
9
+
6
10
  it_behaves_like "a confluent schema registry client" do
7
- let(:registry) { described_class.new(registry_url, logger: logger) }
11
+ let(:registry) {
12
+ described_class.new(
13
+ registry_url,
14
+ logger: logger,
15
+ client_cert: client_cert,
16
+ client_key: client_key,
17
+ client_key_pass: client_key_pass
18
+ )
19
+ }
8
20
  end
9
21
  end
@@ -0,0 +1,159 @@
1
+ require 'webmock/rspec'
2
+ require 'avro_turf/cached_confluent_schema_registry'
3
+ require 'avro_turf/test/fake_confluent_schema_registry_server'
4
+
5
+ describe AvroTurf::CachedConfluentSchemaRegistry do
6
+ let(:upstream) { instance_double(AvroTurf::ConfluentSchemaRegistry) }
7
+ let(:cache) { AvroTurf::DiskCache.new("spec/cache")}
8
+ let(:registry) { described_class.new(upstream, cache: cache) }
9
+ let(:id) { rand(999) }
10
+ let(:schema) do
11
+ {
12
+ type: "record",
13
+ name: "person",
14
+ fields: [{ name: "name", type: "string" }]
15
+ }.to_json
16
+ end
17
+
18
+ let(:city_id) { rand(999) }
19
+ let(:city_schema) do
20
+ {
21
+ type: "record",
22
+ name: "city",
23
+ fields: [{ name: "name", type: "string" }]
24
+ }.to_json
25
+ end
26
+
27
+ let(:subject) { 'subject' }
28
+ let(:version) { rand(999) }
29
+ let(:subject_version_schema) do
30
+ {
31
+ subject: subject,
32
+ version: version,
33
+ id: id,
34
+ schema: {
35
+ type: "record",
36
+ name: "city",
37
+ fields: { name: "name", type: "string" }
38
+ }
39
+ }.to_json
40
+ end
41
+
42
+ before do
43
+ FileUtils.mkdir_p("spec/cache")
44
+ end
45
+
46
+ describe "#fetch" do
47
+ let(:cache_before) do
48
+ {
49
+ "#{id}" => "#{schema}"
50
+ }
51
+ end
52
+ let(:cache_after) do
53
+ {
54
+ "#{id}" => "#{schema}",
55
+ "#{city_id}" => "#{city_schema}"
56
+ }
57
+ end
58
+
59
+ # setup the disk cache to avoid performing the upstream fetch
60
+ before do
61
+ store_cache("schemas_by_id.json", cache_before)
62
+ end
63
+
64
+ it "uses preloaded disk cache" do
65
+ # multiple calls return same result, with zero upstream calls
66
+ allow(upstream).to receive(:fetch).with(id).and_return(schema)
67
+ expect(registry.fetch(id)).to eq(schema)
68
+ expect(registry.fetch(id)).to eq(schema)
69
+ expect(upstream).to have_received(:fetch).exactly(0).times
70
+ expect(load_cache("schemas_by_id.json")).to eq cache_before
71
+ end
72
+
73
+ it "writes thru to disk cache" do
74
+ # multiple calls return same result, with only one upstream call
75
+ allow(upstream).to receive(:fetch).with(city_id).and_return(city_schema)
76
+ expect(registry.fetch(city_id)).to eq(city_schema)
77
+ expect(registry.fetch(city_id)).to eq(city_schema)
78
+ expect(upstream).to have_received(:fetch).exactly(1).times
79
+ expect(load_cache("schemas_by_id.json")).to eq cache_after
80
+ end
81
+ end
82
+
83
+ describe "#register" do
84
+ let(:subject_name) { "a_subject" }
85
+ let(:cache_before) do
86
+ {
87
+ "#{subject_name}#{schema}" => id
88
+ }
89
+ end
90
+
91
+ let(:city_name) { "a_city" }
92
+ let(:cache_after) do
93
+ {
94
+ "#{subject_name}#{schema}" => id,
95
+ "#{city_name}#{city_schema}" => city_id
96
+ }
97
+ end
98
+
99
+ # setup the disk cache to avoid performing the upstream register
100
+ before do
101
+ store_cache("ids_by_schema.json", cache_before)
102
+ end
103
+
104
+ it "uses preloaded disk cache" do
105
+ # multiple calls return same result, with zero upstream calls
106
+ allow(upstream).to receive(:register).with(subject_name, schema).and_return(id)
107
+ expect(registry.register(subject_name, schema)).to eq(id)
108
+ expect(registry.register(subject_name, schema)).to eq(id)
109
+ expect(upstream).to have_received(:register).exactly(0).times
110
+ expect(load_cache("ids_by_schema.json")).to eq cache_before
111
+ end
112
+
113
+ it "writes thru to disk cache" do
114
+ # multiple calls return same result, with only one upstream call
115
+ allow(upstream).to receive(:register).with(city_name, city_schema).and_return(city_id)
116
+ expect(registry.register(city_name, city_schema)).to eq(city_id)
117
+ expect(registry.register(city_name, city_schema)).to eq(city_id)
118
+ expect(upstream).to have_received(:register).exactly(1).times
119
+ expect(load_cache("ids_by_schema.json")).to eq cache_after
120
+ end
121
+ end
122
+
123
+ describe "#subject_version" do
124
+ it "writes thru to disk cache" do
125
+ # multiple calls return same result, with zero upstream calls
126
+ allow(upstream).to receive(:subject_version).with(subject, version).and_return(subject_version_schema)
127
+ expect(File).not_to exist("./spec/cache/schemas_by_subject_version.json")
128
+
129
+ expect(registry.subject_version(subject, version)).to eq(subject_version_schema)
130
+
131
+ json = JSON.parse(File.read("./spec/cache/schemas_by_subject_version.json"))["#{subject}#{version}"]
132
+ expect(json).to eq(subject_version_schema)
133
+
134
+ expect(registry.subject_version(subject, version)).to eq(subject_version_schema)
135
+ expect(upstream).to have_received(:subject_version).exactly(1).times
136
+ end
137
+
138
+ it "reads from disk cache and populates mem cache" do
139
+ allow(upstream).to receive(:subject_version).with(subject, version).and_return(subject_version_schema)
140
+ key = "#{subject}#{version}"
141
+ hash = {key => subject_version_schema}
142
+ cache.send(:write_to_disk_cache, "./spec/cache/schemas_by_subject_version.json", hash)
143
+
144
+ cached_schema = cache.instance_variable_get(:@schemas_by_subject_version)
145
+ expect(cached_schema).to eq({})
146
+
147
+ expect(registry.subject_version(subject, version)).to eq(subject_version_schema)
148
+ expect(upstream).to have_received(:subject_version).exactly(0).times
149
+
150
+ cached_schema = cache.instance_variable_get(:@schemas_by_subject_version)
151
+ expect(cached_schema).to eq({key => subject_version_schema})
152
+ end
153
+ end
154
+
155
+ it_behaves_like "a confluent schema registry client" do
156
+ let(:upstream) { AvroTurf::ConfluentSchemaRegistry.new(registry_url, logger: logger) }
157
+ let(:registry) { described_class.new(upstream) }
158
+ end
159
+ end
@@ -4,29 +4,25 @@ require 'avro_turf/test/fake_confluent_schema_registry_server'
4
4
 
5
5
  describe AvroTurf::Messaging do
6
6
  let(:registry_url) { "http://registry.example.com" }
7
+ let(:client_cert) { "test client cert" }
8
+ let(:client_key) { "test client key" }
9
+ let(:client_key_pass) { "test client key password" }
7
10
  let(:logger) { Logger.new(StringIO.new) }
8
11
 
9
12
  let(:avro) {
10
13
  AvroTurf::Messaging.new(
11
14
  registry_url: registry_url,
12
15
  schemas_path: "spec/schemas",
13
- logger: logger
16
+ logger: logger,
17
+ client_cert: client_cert,
18
+ client_key: client_key,
19
+ client_key_pass: client_key_pass
14
20
  )
15
21
  }
16
22
 
17
23
  let(:message) { { "full_name" => "John Doe" } }
18
-
19
- before do
20
- FileUtils.mkdir_p("spec/schemas")
21
- end
22
-
23
- before do
24
- stub_request(:any, /^#{registry_url}/).to_rack(FakeConfluentSchemaRegistryServer)
25
- FakeConfluentSchemaRegistryServer.clear
26
- end
27
-
28
- before do
29
- define_schema "person.avsc", <<-AVSC
24
+ let(:schema_json) do
25
+ <<-AVSC
30
26
  {
31
27
  "name": "person",
32
28
  "type": "record",
@@ -39,8 +35,22 @@ describe AvroTurf::Messaging do
39
35
  }
40
36
  AVSC
41
37
  end
38
+ let(:schema) { Avro::Schema.parse(schema_json) }
42
39
 
43
- shared_examples_for "encoding and decoding" do
40
+ before do
41
+ FileUtils.mkdir_p("spec/schemas")
42
+ end
43
+
44
+ before do
45
+ stub_request(:any, /^#{registry_url}/).to_rack(FakeConfluentSchemaRegistryServer)
46
+ FakeConfluentSchemaRegistryServer.clear
47
+ end
48
+
49
+ before do
50
+ define_schema "person.avsc", schema_json
51
+ end
52
+
53
+ shared_examples_for "encoding and decoding with the schema from schema store" do
44
54
  it "encodes and decodes messages" do
45
55
  data = avro.encode(message, schema_name: "person")
46
56
  expect(avro.decode(data)).to eq message
@@ -60,7 +70,66 @@ describe AvroTurf::Messaging do
60
70
  end
61
71
  end
62
72
 
63
- it_behaves_like "encoding and decoding"
73
+ shared_examples_for 'encoding and decoding with the schema from registry' do
74
+ before do
75
+ registry = AvroTurf::ConfluentSchemaRegistry.new(registry_url, logger: logger)
76
+ registry.register('person', schema)
77
+ registry.register('people', schema)
78
+ end
79
+
80
+ it 'encodes and decodes messages' do
81
+ data = avro.encode(message, subject: 'person', version: 1)
82
+ expect(avro.decode(data)).to eq message
83
+ end
84
+
85
+ it "allows specifying a reader's schema by subject and version" do
86
+ data = avro.encode(message, subject: 'person', version: 1)
87
+ expect(avro.decode(data, schema_name: 'person')).to eq message
88
+ end
89
+
90
+ it 'raises AvroTurf::SchemaNotFoundError when the schema does not exist on registry' do
91
+ expect { avro.encode(message, subject: 'missing', version: 1) }.to raise_error(AvroTurf::SchemaNotFoundError)
92
+ end
93
+
94
+ it 'caches parsed schemas for decoding' do
95
+ data = avro.encode(message, subject: 'person', version: 1)
96
+ avro.decode(data)
97
+ allow(Avro::Schema).to receive(:parse).and_call_original
98
+ expect(avro.decode(data)).to eq message
99
+ expect(Avro::Schema).not_to have_received(:parse)
100
+ end
101
+ end
102
+
103
+ shared_examples_for 'encoding and decoding with the schema_id from registry' do
104
+ before do
105
+ registry = AvroTurf::ConfluentSchemaRegistry.new(registry_url, logger: logger)
106
+ registry.register('person', schema)
107
+ registry.register('people', schema)
108
+ end
109
+
110
+ it 'encodes and decodes messages' do
111
+ data = avro.encode(message, schema_id: 1)
112
+ expect(avro.decode(data)).to eq message
113
+ end
114
+
115
+ it 'raises AvroTurf::SchemaNotFoundError when the schema does not exist on registry' do
116
+ expect { avro.encode(message, schema_id: 5) }.to raise_error(AvroTurf::SchemaNotFoundError)
117
+ end
118
+
119
+ it 'caches parsed schemas for decoding' do
120
+ data = avro.encode(message, schema_id: 1)
121
+ avro.decode(data)
122
+ allow(Avro::Schema).to receive(:parse).and_call_original
123
+ expect(avro.decode(data)).to eq message
124
+ expect(Avro::Schema).not_to have_received(:parse)
125
+ end
126
+ end
127
+
128
+ it_behaves_like "encoding and decoding with the schema from schema store"
129
+
130
+ it_behaves_like 'encoding and decoding with the schema from registry'
131
+
132
+ it_behaves_like 'encoding and decoding with the schema_id from registry'
64
133
 
65
134
  context "with a provided registry" do
66
135
  let(:registry) { AvroTurf::ConfluentSchemaRegistry.new(registry_url, logger: logger) }
@@ -73,7 +142,11 @@ describe AvroTurf::Messaging do
73
142
  )
74
143
  end
75
144
 
76
- it_behaves_like "encoding and decoding"
145
+ it_behaves_like "encoding and decoding with the schema from schema store"
146
+
147
+ it_behaves_like 'encoding and decoding with the schema from registry'
148
+
149
+ it_behaves_like 'encoding and decoding with the schema_id from registry'
77
150
 
78
151
  it "uses the provided registry" do
79
152
  allow(registry).to receive(:register).and_call_original
@@ -101,7 +174,7 @@ describe AvroTurf::Messaging do
101
174
  )
102
175
  end
103
176
 
104
- it_behaves_like "encoding and decoding"
177
+ it_behaves_like "encoding and decoding with the schema from schema store"
105
178
 
106
179
  it "uses the provided schema store" do
107
180
  allow(schema_store).to receive(:find).and_call_original
@@ -109,4 +182,119 @@ describe AvroTurf::Messaging do
109
182
  expect(schema_store).to have_received(:find).with("person", nil)
110
183
  end
111
184
  end
185
+
186
+ describe 'decoding with #decode_message' do
187
+ shared_examples_for "encoding and decoding with the schema from schema store" do
188
+ it "encodes and decodes messages" do
189
+ data = avro.encode(message, schema_name: "person")
190
+ result = avro.decode_message(data)
191
+ expect(result.message).to eq message
192
+ expect(result.schema_id).to eq 0
193
+ expect(result.writer_schema).to eq schema
194
+ expect(result.reader_schema).to eq nil
195
+ end
196
+
197
+ it "allows specifying a reader's schema" do
198
+ data = avro.encode(message, schema_name: "person")
199
+ result = avro.decode_message(data, schema_name: "person")
200
+ expect(result.message).to eq message
201
+ expect(result.writer_schema).to eq schema
202
+ expect(result.reader_schema).to eq schema
203
+ end
204
+
205
+ it "caches parsed schemas for decoding" do
206
+ data = avro.encode(message, schema_name: "person")
207
+ avro.decode_message(data)
208
+ allow(Avro::Schema).to receive(:parse).and_call_original
209
+ expect(avro.decode_message(data).message).to eq message
210
+ expect(Avro::Schema).not_to have_received(:parse)
211
+ end
212
+ end
213
+
214
+ shared_examples_for 'encoding and decoding with the schema from registry' do
215
+ before do
216
+ registry = AvroTurf::ConfluentSchemaRegistry.new(registry_url, logger: logger)
217
+ registry.register('person', schema)
218
+ registry.register('people', schema)
219
+ end
220
+
221
+ it 'encodes and decodes messages' do
222
+ data = avro.encode(message, subject: 'person', version: 1)
223
+ result = avro.decode_message(data)
224
+ expect(result.message).to eq message
225
+ expect(result.schema_id).to eq 0
226
+ end
227
+
228
+ it "allows specifying a reader's schema by subject and version" do
229
+ data = avro.encode(message, subject: 'person', version: 1)
230
+ expect(avro.decode_message(data, schema_name: 'person').message).to eq message
231
+ end
232
+
233
+ it 'raises AvroTurf::SchemaNotFoundError when the schema does not exist on registry' do
234
+ expect { avro.encode(message, subject: 'missing', version: 1) }.to raise_error(AvroTurf::SchemaNotFoundError)
235
+ end
236
+
237
+ it 'caches parsed schemas for decoding' do
238
+ data = avro.encode(message, subject: 'person', version: 1)
239
+ avro.decode_message(data)
240
+ allow(Avro::Schema).to receive(:parse).and_call_original
241
+ expect(avro.decode_message(data).message).to eq message
242
+ expect(Avro::Schema).not_to have_received(:parse)
243
+ end
244
+ end
245
+
246
+ it_behaves_like "encoding and decoding with the schema from schema store"
247
+
248
+ it_behaves_like 'encoding and decoding with the schema from registry'
249
+
250
+ context "with a provided registry" do
251
+ let(:registry) { AvroTurf::ConfluentSchemaRegistry.new(registry_url, logger: logger) }
252
+
253
+ let(:avro) do
254
+ AvroTurf::Messaging.new(
255
+ registry: registry,
256
+ schemas_path: "spec/schemas",
257
+ logger: logger
258
+ )
259
+ end
260
+
261
+ it_behaves_like "encoding and decoding with the schema from schema store"
262
+
263
+ it_behaves_like 'encoding and decoding with the schema from registry'
264
+
265
+ it "uses the provided registry" do
266
+ allow(registry).to receive(:register).and_call_original
267
+ message = { "full_name" => "John Doe" }
268
+ avro.encode(message, schema_name: "person")
269
+ expect(registry).to have_received(:register).with("person", anything)
270
+ end
271
+
272
+ it "allows specifying a schema registry subject" do
273
+ allow(registry).to receive(:register).and_call_original
274
+ message = { "full_name" => "John Doe" }
275
+ avro.encode(message, schema_name: "person", subject: "people")
276
+ expect(registry).to have_received(:register).with("people", anything)
277
+ end
278
+ end
279
+
280
+ context "with a provided schema store" do
281
+ let(:schema_store) { AvroTurf::SchemaStore.new(path: "spec/schemas") }
282
+
283
+ let(:avro) do
284
+ AvroTurf::Messaging.new(
285
+ registry_url: registry_url,
286
+ schema_store: schema_store,
287
+ logger: logger
288
+ )
289
+ end
290
+
291
+ it_behaves_like "encoding and decoding with the schema from schema store"
292
+
293
+ it "uses the provided schema store" do
294
+ allow(schema_store).to receive(:find).and_call_original
295
+ avro.encode(message, schema_name: "person")
296
+ expect(schema_store).to have_received(:find).with("person", nil)
297
+ end
298
+ end
299
+ end
112
300
  end