avro_turf 0.9.0 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 01a2bdf42a996a7a89bab1769672adc11888d973e5c0c70df42d07b63e87e2bf
4
- data.tar.gz: c80b96eace3ae4fdb254f046335e7aaf21939cde9da86b671d7450e3d1d2ceb4
3
+ metadata.gz: 622818bec3f2c9af6a801fe428b373c96ad38596bef90e6f24d86c855084a1a9
4
+ data.tar.gz: 386053febb649eb457fd0fca3685556e074bee28994be511944da5d7b75b594b
5
5
  SHA512:
6
- metadata.gz: 978d5323dd68d2a1518dadcaa90c1871b065e184ffd06ca7a9a86ad1402c16a46f557ba5847e0a841a269b38bfdcb0769a66ec961eddd6b40dd4f025c6eb2c9e
7
- data.tar.gz: c2abf819298e5c925f60e7d5e6536aced127e1bee0ef4a66893ea25c16f1e8ea9905de9e142e3f7e0a5989901e7708a9ce000cd85384ef2a703d6e77eb27ce7d
6
+ metadata.gz: 35663cd1404da25e60c03bdfcca2dc20fd1af8fb5eb046bad57fb079f4e50901120e15ae3e6f9d275b068202fd113613b49b9e9237ca2705de3f1fd0e34c304a
7
+ data.tar.gz: a37f52541946c02c4858c73e974f78e3e88702fe31292807dd46760e9e2a4dabad8287b136df0ff95ba6912cbb15760881e9574f2837a3124242a00e9d6fac75
@@ -17,6 +17,7 @@ jobs:
17
17
  - v1-dep-master-
18
18
  # Any branch if there are none on the default branch - this should be unnecessary if you have your default branch configured correctly
19
19
  - v1-dep-
20
+ - run: gem install bundler --no-document
20
21
  - run: 'bundle check --path=vendor/bundle || bundle install --path=vendor/bundle --jobs=4 --retry=3'
21
22
  # Save dependency cache
22
23
  - save_cache:
@@ -26,7 +27,7 @@ jobs:
26
27
  - ~/.bundle
27
28
  - run: mkdir -p $CIRCLE_TEST_REPORTS/rspec
28
29
  - run:
29
- command: bundle exec rspec --color --require spec_helper --format RspecJunitFormatter --out $CIRCLE_TEST_REPORTS/rspec/rspec.xml --format progress spec
30
+ command: bundle exec rspec --color --require spec_helper --format progress
30
31
  - store_test_results:
31
32
  path: /tmp/circleci-test-results
32
33
  - store_artifacts:
@@ -0,0 +1,20 @@
1
+ name: Ruby
2
+
3
+ on: [push]
4
+
5
+ jobs:
6
+ build:
7
+
8
+ runs-on: ubuntu-latest
9
+
10
+ steps:
11
+ - uses: actions/checkout@v1
12
+ - name: Set up Ruby 2.6
13
+ uses: actions/setup-ruby@v1
14
+ with:
15
+ ruby-version: 2.6.x
16
+ - name: Build and test with RSpec
17
+ run: |
18
+ gem install bundler
19
+ bundle install --jobs 4 --retry 3
20
+ bundle exec rspec
@@ -2,6 +2,11 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## v0.10.0
6
+
7
+ - Add more disk caching (#103)
8
+ - Include schema information when decoding (#100, #101, #104)
9
+
5
10
  ## v0.9.0
6
11
 
7
12
  - Compatibility with Avro v1.9.0 (#94)
data/Gemfile CHANGED
@@ -2,6 +2,3 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in avro_turf.gemspec
4
4
  gemspec
5
-
6
- # Used by CircleCI to format RSpec results.
7
- gem 'rspec_junit_formatter', :git => 'git@github.com:circleci/rspec_junit_formatter.git'
data/README.md CHANGED
@@ -126,13 +126,27 @@ data = avro.encode({ "title" => "hello, world" }, schema_name: "greeting")
126
126
 
127
127
  # If you don't want to automatically register new schemas, you can pass explicitly
128
128
  # subject and version to specify which schema should be used for encoding.
129
- # It will fetch that schema from the registry and cache it. Subsequent instances
129
+ # It will fetch that schema from the registry and cache it. Subsequent instances
130
130
  # of the same schema version will be served by the cache.
131
131
  data = avro.encode({ "title" => "hello, world" }, subject: 'greeting', version: 1)
132
132
 
133
+ # You can also pass explicitly schema_id to specify which schema
134
+ # should be used for encoding.
135
+ # It will fetch that schema from the registry and cache it. Subsequent instances
136
+ # of the same schema version will be served by the cache.
137
+ data = avro.encode({ "title" => "hello, world" }, schema_id: 2)
138
+
133
139
  # When decoding, the schema will be fetched from the registry and cached. Subsequent
134
140
  # instances of the same schema id will be served by the cache.
135
141
  avro.decode(data) #=> { "title" => "hello, world" }
142
+
143
+ # If you want to get decoded message as well as the schema used to encode the message,
144
+ # you can use `#decode_message` method.
145
+ result = avro.decode_message(data)
146
+ result.message #=> { "title" => "hello, world" }
147
+ result.schema_id #=> 3
148
+ result.writer_schema #=> #<Avro::Schema: ...>
149
+ result.reader_schema #=> nil
136
150
  ```
137
151
 
138
152
  ### Confluent Schema Registry Client
@@ -20,7 +20,7 @@ Gem::Specification.new do |spec|
20
20
  spec.add_dependency "avro", ">= 1.7.7", "< 1.10"
21
21
  spec.add_dependency "excon", "~> 0.45"
22
22
 
23
- spec.add_development_dependency "bundler", "~> 1.7"
23
+ spec.add_development_dependency "bundler", "~> 2.0"
24
24
  spec.add_development_dependency "rake", "~> 10.0"
25
25
  spec.add_development_dependency "rspec", "~> 3.2.0"
26
26
  spec.add_development_dependency "fakefs", "~> 0.6.7"
@@ -11,6 +11,9 @@ class AvroTurf::DiskCache < AvroTurf::InMemoryCache
11
11
 
12
12
  @ids_by_schema_path = File.join(disk_path, 'ids_by_schema.json')
13
13
  @ids_by_schema = JSON.parse(File.read(@ids_by_schema_path)) if File.exist?(@ids_by_schema_path)
14
+
15
+ @schemas_by_subject_version_path = File.join(disk_path, 'schemas_by_subject_version.json')
16
+ @schemas_by_subject_version = {}
14
17
  end
15
18
 
16
19
  # override
@@ -35,4 +38,46 @@ class AvroTurf::DiskCache < AvroTurf::InMemoryCache
35
38
  File.write(@ids_by_schema_path, JSON.pretty_generate(@ids_by_schema))
36
39
  return value
37
40
  end
41
+
42
+ # checks instance var (in-memory cache) for schema
43
+ # checks disk cache if in-memory cache doesn't exists
44
+ # if file exists but no in-memory cache, read from file and sync in-memory cache
45
+ # finally, if file doesn't exist return nil
46
+ def lookup_by_version(subject, version)
47
+ key = "#{subject}#{version}"
48
+ schema = @schemas_by_subject_version[key]
49
+
50
+ return schema unless schema.nil?
51
+
52
+ hash = JSON.parse(File.read(@schemas_by_subject_version_path)) if File.exist?(@schemas_by_subject_version_path)
53
+ if hash
54
+ @schemas_by_subject_version = hash
55
+ @schemas_by_subject_version[key]
56
+ end
57
+ end
58
+
59
+ # check if file exists and parse json into a hash
60
+ # if file exists take json and overwite/insert schema at key
61
+ # if file doesn't exist create new hash
62
+ # write the new/updated hash to file
63
+ # update instance var (in memory-cache) to match
64
+ def store_by_version(subject, version, schema)
65
+ key = "#{subject}#{version}"
66
+ hash = JSON.parse(File.read(@schemas_by_subject_version_path)) if File.exist?(@schemas_by_subject_version_path)
67
+ hash = if hash
68
+ hash[key] = schema
69
+ hash
70
+ else
71
+ {key => schema}
72
+ end
73
+
74
+ write_to_disk_cache(@schemas_by_subject_version_path, hash)
75
+
76
+ @schemas_by_subject_version = hash
77
+ @schemas_by_subject_version[key]
78
+ end
79
+
80
+ private def write_to_disk_cache(path, hash)
81
+ File.write(path, JSON.pretty_generate(hash))
82
+ end
38
83
  end
@@ -21,6 +21,8 @@ class AvroTurf
21
21
  # 1: https://github.com/confluentinc/schema-registry
22
22
  class Messaging
23
23
  MAGIC_BYTE = [0].pack("C").freeze
24
+ DecodedMessage = Struct.new(:schema_id, :writer_schema, :reader_schema, :message)
25
+ private_constant(:DecodedMessage)
24
26
 
25
27
  # Instantiate a new Messaging instance with the given configuration.
26
28
  #
@@ -50,15 +52,19 @@ class AvroTurf
50
52
  # the schema registry (optional).
51
53
  # version - The integer version of the schema that should be used to decode
52
54
  # the data. Must match the schema used when encoding (optional).
55
+ # schema_id - The integer id of the schema that should be used to encode
56
+ # the data.
53
57
  #
54
58
  # Returns the encoded data as a String.
55
- def encode(message, schema_name: nil, namespace: @namespace, subject: nil, version: nil)
56
- schema_id, schema = if subject && version
59
+ def encode(message, schema_name: nil, namespace: @namespace, subject: nil, version: nil, schema_id: nil)
60
+ schema_id, schema = if schema_id
61
+ fetch_schema_by_id(schema_id)
62
+ elsif subject && version
57
63
  fetch_schema(subject, version)
58
64
  elsif schema_name
59
65
  register_schema(subject, schema_name, namespace)
60
66
  else
61
- raise ArgumentError.new('Neither schema_name nor subject + version provided to determine the schema.')
67
+ raise ArgumentError.new('Neither schema_name nor schema_id nor subject + version provided to determine the schema.')
62
68
  end
63
69
 
64
70
  stream = StringIO.new
@@ -76,7 +82,11 @@ class AvroTurf
76
82
 
77
83
  stream.string
78
84
  rescue Excon::Error::NotFound
79
- raise SchemaNotFoundError.new("Schema with subject: `#{subject}` version: `#{version}` is not found on registry")
85
+ if schema_id
86
+ raise SchemaNotFoundError.new("Schema with id: #{schema_id} is not found on registry")
87
+ else
88
+ raise SchemaNotFoundError.new("Schema with subject: `#{subject}` version: `#{version}` is not found on registry")
89
+ end
80
90
  end
81
91
 
82
92
  # Decodes data into the original message.
@@ -88,6 +98,20 @@ class AvroTurf
88
98
  #
89
99
  # Returns the decoded message.
90
100
  def decode(data, schema_name: nil, namespace: @namespace)
101
+ decode_message(data, schema_name: schema_name, namespace: namespace).message
102
+ end
103
+
104
+ # Decodes data into the original message.
105
+ #
106
+ # data - A String containing encoded data.
107
+ # schema_name - The String name of the schema that should be used to decode
108
+ # the data. Must match the schema used when encoding (optional).
109
+ # namespace - The namespace of the schema (optional).
110
+ #
111
+ # Returns Struct with the next attributes:
112
+ # schema_id - The integer id of schema used to encode the message
113
+ # message - The decoded message
114
+ def decode_message(data, schema_name: nil, namespace: @namespace)
91
115
  readers_schema = schema_name && @schema_store.find(schema_name, namespace)
92
116
  stream = StringIO.new(data)
93
117
  decoder = Avro::IO::BinaryDecoder.new(stream)
@@ -108,7 +132,9 @@ class AvroTurf
108
132
  end
109
133
 
110
134
  reader = Avro::IO::DatumReader.new(writers_schema, readers_schema)
111
- reader.read(decoder)
135
+ message = reader.read(decoder)
136
+
137
+ DecodedMessage.new(schema_id, writers_schema, readers_schema, message)
112
138
  rescue Excon::Error::NotFound
113
139
  raise SchemaNotFoundError.new("Schema with id: #{schema_id} is not found on registry")
114
140
  end
@@ -125,6 +151,13 @@ class AvroTurf
125
151
  [schema_id, schema]
126
152
  end
127
153
 
154
+ # Fetch the schema from registry with the provided schema_id.
155
+ def fetch_schema_by_id(schema_id)
156
+ schema_json = @registry.fetch(schema_id)
157
+ schema = Avro::Schema.parse(schema_json)
158
+ [schema_id, schema]
159
+ end
160
+
128
161
  # Schemas are registered under the full name of the top level Avro record
129
162
  # type, or `subject` if it's provided.
130
163
  def register_schema(subject, schema_name, namespace)
@@ -1,3 +1,3 @@
1
1
  class AvroTurf
2
- VERSION = "0.9.0"
2
+ VERSION = "0.10.0"
3
3
  end
@@ -24,6 +24,21 @@ describe AvroTurf::CachedConfluentSchemaRegistry do
24
24
  }.to_json
25
25
  end
26
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
+
27
42
  before do
28
43
  FileUtils.mkdir_p("spec/cache")
29
44
  end
@@ -105,6 +120,38 @@ describe AvroTurf::CachedConfluentSchemaRegistry do
105
120
  end
106
121
  end
107
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
+
108
155
  it_behaves_like "a confluent schema registry client" do
109
156
  let(:upstream) { AvroTurf::ConfluentSchemaRegistry.new(registry_url, logger: logger) }
110
157
  let(:registry) { described_class.new(upstream) }
@@ -29,6 +29,7 @@ describe AvroTurf::Messaging do
29
29
  }
30
30
  AVSC
31
31
  end
32
+ let(:schema) { Avro::Schema.parse(schema_json) }
32
33
 
33
34
  before do
34
35
  FileUtils.mkdir_p("spec/schemas")
@@ -66,8 +67,8 @@ describe AvroTurf::Messaging do
66
67
  shared_examples_for 'encoding and decoding with the schema from registry' do
67
68
  before do
68
69
  registry = AvroTurf::ConfluentSchemaRegistry.new(registry_url, logger: logger)
69
- registry.register('person', Avro::Schema.parse(schema_json))
70
- registry.register('people', Avro::Schema.parse(schema_json))
70
+ registry.register('person', schema)
71
+ registry.register('people', schema)
71
72
  end
72
73
 
73
74
  it 'encodes and decodes messages' do
@@ -93,10 +94,37 @@ describe AvroTurf::Messaging do
93
94
  end
94
95
  end
95
96
 
97
+ shared_examples_for 'encoding and decoding with the schema_id from registry' do
98
+ before do
99
+ registry = AvroTurf::ConfluentSchemaRegistry.new(registry_url, logger: logger)
100
+ registry.register('person', schema)
101
+ registry.register('people', schema)
102
+ end
103
+
104
+ it 'encodes and decodes messages' do
105
+ data = avro.encode(message, schema_id: 1)
106
+ expect(avro.decode(data)).to eq message
107
+ end
108
+
109
+ it 'raises AvroTurf::SchemaNotFoundError when the schema does not exist on registry' do
110
+ expect { avro.encode(message, schema_id: 5) }.to raise_error(AvroTurf::SchemaNotFoundError)
111
+ end
112
+
113
+ it 'caches parsed schemas for decoding' do
114
+ data = avro.encode(message, schema_id: 1)
115
+ avro.decode(data)
116
+ allow(Avro::Schema).to receive(:parse).and_call_original
117
+ expect(avro.decode(data)).to eq message
118
+ expect(Avro::Schema).not_to have_received(:parse)
119
+ end
120
+ end
121
+
96
122
  it_behaves_like "encoding and decoding with the schema from schema store"
97
123
 
98
124
  it_behaves_like 'encoding and decoding with the schema from registry'
99
125
 
126
+ it_behaves_like 'encoding and decoding with the schema_id from registry'
127
+
100
128
  context "with a provided registry" do
101
129
  let(:registry) { AvroTurf::ConfluentSchemaRegistry.new(registry_url, logger: logger) }
102
130
 
@@ -112,6 +140,8 @@ describe AvroTurf::Messaging do
112
140
 
113
141
  it_behaves_like 'encoding and decoding with the schema from registry'
114
142
 
143
+ it_behaves_like 'encoding and decoding with the schema_id from registry'
144
+
115
145
  it "uses the provided registry" do
116
146
  allow(registry).to receive(:register).and_call_original
117
147
  message = { "full_name" => "John Doe" }
@@ -146,4 +176,119 @@ describe AvroTurf::Messaging do
146
176
  expect(schema_store).to have_received(:find).with("person", nil)
147
177
  end
148
178
  end
179
+
180
+ describe 'decoding with #decode_message' do
181
+ shared_examples_for "encoding and decoding with the schema from schema store" do
182
+ it "encodes and decodes messages" do
183
+ data = avro.encode(message, schema_name: "person")
184
+ result = avro.decode_message(data)
185
+ expect(result.message).to eq message
186
+ expect(result.schema_id).to eq 0
187
+ expect(result.writer_schema).to eq schema
188
+ expect(result.reader_schema).to eq nil
189
+ end
190
+
191
+ it "allows specifying a reader's schema" do
192
+ data = avro.encode(message, schema_name: "person")
193
+ result = avro.decode_message(data, schema_name: "person")
194
+ expect(result.message).to eq message
195
+ expect(result.writer_schema).to eq schema
196
+ expect(result.reader_schema).to eq schema
197
+ end
198
+
199
+ it "caches parsed schemas for decoding" do
200
+ data = avro.encode(message, schema_name: "person")
201
+ avro.decode_message(data)
202
+ allow(Avro::Schema).to receive(:parse).and_call_original
203
+ expect(avro.decode_message(data).message).to eq message
204
+ expect(Avro::Schema).not_to have_received(:parse)
205
+ end
206
+ end
207
+
208
+ shared_examples_for 'encoding and decoding with the schema from registry' do
209
+ before do
210
+ registry = AvroTurf::ConfluentSchemaRegistry.new(registry_url, logger: logger)
211
+ registry.register('person', schema)
212
+ registry.register('people', schema)
213
+ end
214
+
215
+ it 'encodes and decodes messages' do
216
+ data = avro.encode(message, subject: 'person', version: 1)
217
+ result = avro.decode_message(data)
218
+ expect(result.message).to eq message
219
+ expect(result.schema_id).to eq 0
220
+ end
221
+
222
+ it "allows specifying a reader's schema by subject and version" do
223
+ data = avro.encode(message, subject: 'person', version: 1)
224
+ expect(avro.decode_message(data, schema_name: 'person').message).to eq message
225
+ end
226
+
227
+ it 'raises AvroTurf::SchemaNotFoundError when the schema does not exist on registry' do
228
+ expect { avro.encode(message, subject: 'missing', version: 1) }.to raise_error(AvroTurf::SchemaNotFoundError)
229
+ end
230
+
231
+ it 'caches parsed schemas for decoding' do
232
+ data = avro.encode(message, subject: 'person', version: 1)
233
+ avro.decode_message(data)
234
+ allow(Avro::Schema).to receive(:parse).and_call_original
235
+ expect(avro.decode_message(data).message).to eq message
236
+ expect(Avro::Schema).not_to have_received(:parse)
237
+ end
238
+ end
239
+
240
+ it_behaves_like "encoding and decoding with the schema from schema store"
241
+
242
+ it_behaves_like 'encoding and decoding with the schema from registry'
243
+
244
+ context "with a provided registry" do
245
+ let(:registry) { AvroTurf::ConfluentSchemaRegistry.new(registry_url, logger: logger) }
246
+
247
+ let(:avro) do
248
+ AvroTurf::Messaging.new(
249
+ registry: registry,
250
+ schemas_path: "spec/schemas",
251
+ logger: logger
252
+ )
253
+ end
254
+
255
+ it_behaves_like "encoding and decoding with the schema from schema store"
256
+
257
+ it_behaves_like 'encoding and decoding with the schema from registry'
258
+
259
+ it "uses the provided registry" do
260
+ allow(registry).to receive(:register).and_call_original
261
+ message = { "full_name" => "John Doe" }
262
+ avro.encode(message, schema_name: "person")
263
+ expect(registry).to have_received(:register).with("person", anything)
264
+ end
265
+
266
+ it "allows specifying a schema registry subject" do
267
+ allow(registry).to receive(:register).and_call_original
268
+ message = { "full_name" => "John Doe" }
269
+ avro.encode(message, schema_name: "person", subject: "people")
270
+ expect(registry).to have_received(:register).with("people", anything)
271
+ end
272
+ end
273
+
274
+ context "with a provided schema store" do
275
+ let(:schema_store) { AvroTurf::SchemaStore.new(path: "spec/schemas") }
276
+
277
+ let(:avro) do
278
+ AvroTurf::Messaging.new(
279
+ registry_url: registry_url,
280
+ schema_store: schema_store,
281
+ logger: logger
282
+ )
283
+ end
284
+
285
+ it_behaves_like "encoding and decoding with the schema from schema store"
286
+
287
+ it "uses the provided schema store" do
288
+ allow(schema_store).to receive(:find).and_call_original
289
+ avro.encode(message, schema_name: "person")
290
+ expect(schema_store).to have_received(:find).with("person", nil)
291
+ end
292
+ end
293
+ end
149
294
  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: 0.9.0
4
+ version: 0.10.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: 2019-07-15 00:00:00.000000000 Z
11
+ date: 2019-09-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: avro
@@ -50,14 +50,14 @@ dependencies:
50
50
  requirements:
51
51
  - - "~>"
52
52
  - !ruby/object:Gem::Version
53
- version: '1.7'
53
+ version: '2.0'
54
54
  type: :development
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
57
57
  requirements:
58
58
  - - "~>"
59
59
  - !ruby/object:Gem::Version
60
- version: '1.7'
60
+ version: '2.0'
61
61
  - !ruby/object:Gem::Dependency
62
62
  name: rake
63
63
  requirement: !ruby/object:Gem::Requirement
@@ -164,6 +164,7 @@ extensions: []
164
164
  extra_rdoc_files: []
165
165
  files:
166
166
  - ".circleci/config.yml"
167
+ - ".github/workflows/ruby.yml"
167
168
  - ".gitignore"
168
169
  - ".rspec"
169
170
  - CHANGELOG.md
@@ -248,7 +249,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
248
249
  - !ruby/object:Gem::Version
249
250
  version: '0'
250
251
  requirements: []
251
- rubygems_version: 3.0.3
252
+ rubyforge_project:
253
+ rubygems_version: 2.7.6
252
254
  signing_key:
253
255
  specification_version: 4
254
256
  summary: A library that makes it easier to use the Avro serialization format from