avro_turf 1.19.0 → 1.20.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.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +20 -11
  3. data/CHANGELOG.md +6 -0
  4. data/Gemfile +5 -2
  5. data/Rakefile +2 -1
  6. data/avro_turf.gemspec +16 -16
  7. data/lib/avro_turf/cached_confluent_schema_registry.rb +9 -8
  8. data/lib/avro_turf/cached_schema_registry.rb +3 -1
  9. data/lib/avro_turf/confluent_schema_registry.rb +23 -17
  10. data/lib/avro_turf/core_ext/date.rb +2 -0
  11. data/lib/avro_turf/core_ext/enumerable.rb +2 -0
  12. data/lib/avro_turf/core_ext/false_class.rb +2 -0
  13. data/lib/avro_turf/core_ext/hash.rb +4 -2
  14. data/lib/avro_turf/core_ext/nil_class.rb +2 -0
  15. data/lib/avro_turf/core_ext/numeric.rb +2 -0
  16. data/lib/avro_turf/core_ext/string.rb +2 -0
  17. data/lib/avro_turf/core_ext/symbol.rb +2 -0
  18. data/lib/avro_turf/core_ext/time.rb +2 -0
  19. data/lib/avro_turf/core_ext/true_class.rb +2 -0
  20. data/lib/avro_turf/core_ext.rb +12 -10
  21. data/lib/avro_turf/disk_cache.rb +13 -12
  22. data/lib/avro_turf/in_memory_cache.rb +2 -0
  23. data/lib/avro_turf/messaging.rb +22 -14
  24. data/lib/avro_turf/mutable_schema_store.rb +25 -4
  25. data/lib/avro_turf/schema_registry.rb +3 -1
  26. data/lib/avro_turf/schema_store.rb +3 -2
  27. data/lib/avro_turf/schema_to_avro_patch.rb +14 -12
  28. data/lib/avro_turf/test/fake_confluent_schema_registry_server.rb +24 -23
  29. data/lib/avro_turf/test/fake_prefixed_confluent_schema_registry_server.rb +12 -10
  30. data/lib/avro_turf/test/fake_schema_registry_server.rb +3 -1
  31. data/lib/avro_turf/version.rb +3 -1
  32. data/lib/avro_turf.rb +15 -13
  33. data/perf/encoding_size.rb +4 -2
  34. data/perf/encoding_speed.rb +4 -2
  35. data/spec/avro_turf_spec.rb +24 -23
  36. data/spec/cached_confluent_schema_registry_spec.rb +9 -7
  37. data/spec/confluent_schema_registry_spec.rb +31 -10
  38. data/spec/core_ext/date_spec.rb +2 -0
  39. data/spec/core_ext/enumerable_spec.rb +2 -0
  40. data/spec/core_ext/false_class_spec.rb +2 -0
  41. data/spec/core_ext/hash_spec.rb +3 -1
  42. data/spec/core_ext/nil_class_spec.rb +2 -0
  43. data/spec/core_ext/numeric_spec.rb +2 -0
  44. data/spec/core_ext/string_spec.rb +2 -0
  45. data/spec/core_ext/symbol_spec.rb +2 -0
  46. data/spec/core_ext/time_spec.rb +2 -0
  47. data/spec/core_ext/true_class_spec.rb +2 -0
  48. data/spec/disk_cached_confluent_schema_registry_spec.rb +23 -21
  49. data/spec/messaging_spec.rb +124 -99
  50. data/spec/mutable_schema_store_spec.rb +134 -0
  51. data/spec/schema_store_spec.rb +23 -21
  52. data/spec/schema_to_avro_patch_spec.rb +8 -7
  53. data/spec/spec_helper.rb +9 -9
  54. data/spec/support/authorized_fake_confluent_schema_registry_server.rb +4 -2
  55. data/spec/support/authorized_fake_prefixed_confluent_schema_registry_server.rb +4 -2
  56. data/spec/support/confluent_schema_registry_context.rb +32 -30
  57. data/spec/test/fake_confluent_schema_registry_server_spec.rb +97 -94
  58. metadata +5 -26
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fffcc17349a4bbbcaa1204610da74800c9a519d4774af83c7059c47bb75efb1b
4
- data.tar.gz: e5afce0fa557da110a0dd1fe73add073f994a72bb8e3a1e37865a3393f864c2b
3
+ metadata.gz: 0f3d6b25c3e25a9137581fbe4bdb3e45015d371c479f8beeb54fa30ee8a3475e
4
+ data.tar.gz: a59d1634303784ae309a40c45f6abf70acdd5b681abe9a89bac40fa0497c5a63
5
5
  SHA512:
6
- metadata.gz: 06aac90715b06f0fdf04918ba73c2533a0cad0b9dff769e1bfc30a1488e0916fc3b38c8f4bee6efab5d667688bd9d407330c603f209ead30d67cb13b3b46c4a5
7
- data.tar.gz: 1a3c95047a2522914394b181eaf01afaee84547d64a72d1aebe3534252f49168cebec0cf7edda8bc8a62f769dd22294eb3916d317a71a65305cb6c46ffba84ad
6
+ metadata.gz: 85b800371ca6102518333c64732a26af7d103d35453923e1ac332b6c643e1826c00c90b826e9332c23e4de5f995bd40c8411447184289c2834fc45dbeded1664
7
+ data.tar.gz: df05accd07e4876a776a6dffb1850bfecd73d82727fc22ab5d25a4e002c069d50c7d9bb0e5fe9ae23e2f528b189c49d31ad87189d0ec07f5c2dcefb707110719
@@ -4,20 +4,29 @@ on: [push, pull_request]
4
4
 
5
5
  jobs:
6
6
  build:
7
-
8
7
  runs-on: ubuntu-latest
9
8
  strategy:
10
9
  fail-fast: false
11
10
  matrix:
12
- ruby: [3.0, 3.1, 3.2, 3.3]
11
+ ruby: ["3.0", 3.1, 3.2, 3.3, 3.4]
12
+ steps:
13
+ - uses: actions/checkout@v5
14
+ - name: Set up Ruby ${{ matrix.ruby }}
15
+ uses: ruby/setup-ruby@v1
16
+ with:
17
+ ruby-version: ${{ matrix.ruby }}
18
+ bundler-cache: true
19
+ - name: Build and test with RSpec
20
+ env:
21
+ RUBYOPT: '--enable=frozen-string-literal --debug=frozen-string-literal'
22
+ run: bundle exec rspec
13
23
 
24
+ lint:
25
+ runs-on: ubuntu-24.04-arm
14
26
  steps:
15
- - uses: actions/checkout@v3
16
- - name: Set up Ruby ${{ matrix.ruby }}
17
- uses: ruby/setup-ruby@v1
18
- with:
19
- ruby-version: ${{ matrix.ruby }}
20
- bundler-cache: true
21
- - name: Build and test with RSpec
22
- run: |
23
- bundle exec rspec
27
+ - uses: actions/checkout@v5
28
+ - uses: ruby/setup-ruby@v1
29
+ with:
30
+ ruby-version: 3
31
+ bundler-cache: true
32
+ - run: bundle exec standardrb
data/CHANGELOG.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## v1.20.0
6
+
7
+ - Add support for client certificate chains via `client_chain` and `client_chain_data` parameters (#233)
8
+ - Ensure the gem works with frozen strings.
9
+ - Stop caching nested sub-schemas in MutableSchemaStore (#232)
10
+
5
11
  ## v1.19.0
6
12
 
7
13
  - Loosen excon dependency to allow 1.x (#220)
data/Gemfile CHANGED
@@ -1,6 +1,9 @@
1
- source 'https://rubygems.org'
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
2
4
 
3
5
  # Specify your gem's dependencies in avro_turf.gemspec
4
6
  gemspec
5
7
 
6
- gem 'gem-release'
8
+ gem "gem-release"
9
+ gem "standard"
data/Rakefile CHANGED
@@ -1,2 +1,3 @@
1
- require "bundler/gem_tasks"
1
+ # frozen_string_literal: true
2
2
 
3
+ require "bundler/gem_tasks"
data/avro_turf.gemspec CHANGED
@@ -1,22 +1,22 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path("../lib", __FILE__)
3
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'avro_turf/version'
5
+ require "avro_turf/version"
5
6
 
6
7
  Gem::Specification.new do |spec|
7
- spec.name = "avro_turf"
8
- spec.version = AvroTurf::VERSION
9
- spec.authors = ["Daniel Schierbeck"]
10
- spec.email = ["dasch@zendesk.com"]
11
- spec.summary = "A library that makes it easier to use the Avro serialization format from Ruby"
12
- spec.homepage = "https://github.com/dasch/avro_turf"
13
- spec.license = "MIT"
8
+ spec.name = "avro_turf"
9
+ spec.version = AvroTurf::VERSION
10
+ spec.authors = ["Daniel Schierbeck"]
11
+ spec.email = ["dasch@zendesk.com"]
12
+ spec.summary = "A library that makes it easier to use the Avro serialization format from Ruby"
13
+ spec.homepage = "https://github.com/dasch/avro_turf"
14
+ spec.license = "MIT"
14
15
 
15
16
  spec.metadata["rubygems_mfa_required"] = "true"
16
17
 
17
- spec.files = `git ls-files -z`.split("\x0")
18
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.files = `git ls-files -z`.split("\x0")
19
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
20
20
  spec.require_paths = ["lib"]
21
21
 
22
22
  spec.add_dependency "avro", ">= 1.11.3", "< 1.13"
@@ -25,14 +25,14 @@ Gem::Specification.new do |spec|
25
25
  spec.add_development_dependency "bundler", "~> 2.0"
26
26
  spec.add_development_dependency "rake", "~> 13.0"
27
27
  spec.add_development_dependency "rspec", "~> 3.2"
28
- spec.add_development_dependency "fakefs", "< 3"
28
+ spec.add_development_dependency "fakefs", "~> 3"
29
29
  spec.add_development_dependency "webmock"
30
30
  spec.add_development_dependency "sinatra"
31
31
  spec.add_development_dependency "json_spec"
32
32
  spec.add_development_dependency "rack-test"
33
33
  spec.add_development_dependency "resolv"
34
34
 
35
- spec.post_install_message = %{
35
+ spec.post_install_message = %(
36
36
  avro_turf v0.8.0 deprecates the names AvroTurf::SchemaRegistry,
37
37
  AvroTurf::CachedSchemaRegistry, and FakeSchemaRegistryServer.
38
38
 
@@ -40,5 +40,5 @@ Use AvroTurf::ConfluentSchemaRegistry, AvroTurf::CachedConfluentSchemaRegistry,
40
40
  and FakeConfluentSchemaRegistryServer instead.
41
41
 
42
42
  See https://github.com/dasch/avro_turf#deprecation-notice
43
- }
43
+ )
44
44
  end
@@ -1,10 +1,11 @@
1
- require 'avro_turf/confluent_schema_registry'
2
- require 'avro_turf/in_memory_cache'
3
- require 'avro_turf/disk_cache'
1
+ # frozen_string_literal: true
2
+
3
+ require "avro_turf/confluent_schema_registry"
4
+ require "avro_turf/in_memory_cache"
5
+ require "avro_turf/disk_cache"
4
6
 
5
7
  # Caches registrations and lookups to the schema registry in memory.
6
8
  class AvroTurf::CachedConfluentSchemaRegistry
7
-
8
9
  # Instantiate a new CachedConfluentSchemaRegistry instance with the given configuration.
9
10
  # By default, uses a provided InMemoryCache to prevent repeated calls to the upstream registry.
10
11
  #
@@ -17,8 +18,8 @@ class AvroTurf::CachedConfluentSchemaRegistry
17
18
  end
18
19
 
19
20
  # Delegate the following methods to the upstream
20
- %i(subjects subject_versions schema_subject_versions compatible?
21
- global_config update_global_config subject_config update_subject_config).each do |name|
21
+ %i[subjects subject_versions schema_subject_versions compatible?
22
+ global_config update_global_config subject_config update_subject_config].each do |name|
22
23
  define_method(name) do |*args|
23
24
  instance_variable_get(:@upstream).send(name, *args)
24
25
  end
@@ -36,8 +37,8 @@ class AvroTurf::CachedConfluentSchemaRegistry
36
37
  @cache.lookup_by_schema(subject, schema) || @cache.store_by_schema(subject, schema, @upstream.register(subject, schema))
37
38
  end
38
39
 
39
- def subject_version(subject, version = 'latest')
40
- return @upstream.subject_version(subject, version) if version == 'latest'
40
+ def subject_version(subject, version = "latest")
41
+ return @upstream.subject_version(subject, version) if version == "latest"
41
42
 
42
43
  @cache.lookup_by_version(subject, version) ||
43
44
  @cache.store_by_version(subject, version, @upstream.subject_version(subject, version))
@@ -1,4 +1,6 @@
1
- require 'avro_turf/cached_confluent_schema_registry'
1
+ # frozen_string_literal: true
2
+
3
+ require "avro_turf/cached_confluent_schema_registry"
2
4
 
3
5
  # AvroTurf::CachedSchemaRegistry is deprecated and will be removed in a future release.
4
6
  # Use AvroTurf::CachedConfluentSchemaRegistry instead.
@@ -1,7 +1,9 @@
1
- require 'excon'
1
+ # frozen_string_literal: true
2
+
3
+ require "excon"
2
4
 
3
5
  class AvroTurf::ConfluentSchemaRegistry
4
- CONTENT_TYPE = "application/vnd.schemaregistry.v1+json".freeze
6
+ CONTENT_TYPE = "application/vnd.schemaregistry.v1+json"
5
7
 
6
8
  def initialize(
7
9
  url,
@@ -12,9 +14,11 @@ class AvroTurf::ConfluentSchemaRegistry
12
14
  password: nil,
13
15
  ssl_ca_file: nil,
14
16
  client_cert: nil,
17
+ client_chain: nil,
15
18
  client_key: nil,
16
19
  client_key_pass: nil,
17
20
  client_cert_data: nil,
21
+ client_chain_data: nil,
18
22
  client_key_data: nil,
19
23
  path_prefix: nil,
20
24
  connect_timeout: nil,
@@ -22,7 +26,7 @@ class AvroTurf::ConfluentSchemaRegistry
22
26
  retry_limit: nil
23
27
  )
24
28
  @path_prefix = path_prefix
25
- @schema_context_prefix = schema_context.nil? ? '' : ":.#{schema_context}:"
29
+ @schema_context_prefix = schema_context.nil? ? "" : ":.#{schema_context}:"
26
30
  @schema_context_options = schema_context.nil? ? {} : {query: {subject: @schema_context_prefix}}
27
31
  @logger = logger
28
32
  headers = Excon.defaults[:headers].merge(
@@ -35,9 +39,11 @@ class AvroTurf::ConfluentSchemaRegistry
35
39
  proxy: proxy,
36
40
  ssl_ca_file: ssl_ca_file,
37
41
  client_cert: client_cert,
42
+ client_chain: client_chain,
38
43
  client_key: client_key,
39
44
  client_key_pass: client_key_pass,
40
45
  client_cert_data: client_cert_data,
46
+ client_chain_data: client_chain_data,
41
47
  client_key_data: client_key_data,
42
48
  resolv_resolver: resolv_resolver,
43
49
  connect_timeout: connect_timeout,
@@ -53,12 +59,12 @@ class AvroTurf::ConfluentSchemaRegistry
53
59
 
54
60
  def fetch(id)
55
61
  @logger.info "Fetching schema with id #{id}"
56
- data = get("/schemas/ids/#{id}", idempotent: true, **@schema_context_options, )
62
+ data = get("/schemas/ids/#{id}", idempotent: true, **@schema_context_options)
57
63
  data.fetch("schema")
58
64
  end
59
65
 
60
66
  def register(subject, schema)
61
- data = post("/subjects/#{@schema_context_prefix}#{subject}/versions", body: { schema: schema.to_s }.to_json)
67
+ data = post("/subjects/#{@schema_context_prefix}#{subject}/versions", body: {schema: schema.to_s}.to_json)
62
68
 
63
69
  id = data.fetch("id")
64
70
 
@@ -69,7 +75,7 @@ class AvroTurf::ConfluentSchemaRegistry
69
75
 
70
76
  # List all subjects
71
77
  def subjects
72
- get('/subjects', idempotent: true)
78
+ get("/subjects", idempotent: true)
73
79
  end
74
80
 
75
81
  # List all versions for a subject
@@ -78,7 +84,7 @@ class AvroTurf::ConfluentSchemaRegistry
78
84
  end
79
85
 
80
86
  # Get a specific version for a subject
81
- def subject_version(subject, version = 'latest')
87
+ def subject_version(subject, version = "latest")
82
88
  get("/subjects/#{@schema_context_prefix}#{subject}/versions/#{version}", idempotent: true)
83
89
  end
84
90
 
@@ -90,9 +96,9 @@ class AvroTurf::ConfluentSchemaRegistry
90
96
  # Check if a schema exists. Returns nil if not found.
91
97
  def check(subject, schema)
92
98
  data = post("/subjects/#{@schema_context_prefix}#{subject}",
93
- expects: [200, 404],
94
- body: { schema: schema.to_s }.to_json,
95
- idempotent: true)
99
+ expects: [200, 404],
100
+ body: {schema: schema.to_s}.to_json,
101
+ idempotent: true)
96
102
  data unless data.has_key?("error_code")
97
103
  end
98
104
 
@@ -102,10 +108,10 @@ class AvroTurf::ConfluentSchemaRegistry
102
108
  # - nil if the subject or version does not exist
103
109
  # - false if incompatible
104
110
  # http://docs.confluent.io/3.1.2/schema-registry/docs/api.html#compatibility
105
- def compatible?(subject, schema, version = 'latest')
111
+ def compatible?(subject, schema, version = "latest")
106
112
  data = post("/compatibility/subjects/#{@schema_context_prefix}#{subject}/versions/#{version}",
107
- expects: [200, 404], body: { schema: schema.to_s }.to_json, idempotent: true)
108
- data.fetch('is_compatible', false) unless data.has_key?('error_code')
113
+ expects: [200, 404], body: {schema: schema.to_s}.to_json, idempotent: true)
114
+ data.fetch("is_compatible", false) unless data.has_key?("error_code")
109
115
  end
110
116
 
111
117
  # Check for specific schema compatibility issues
@@ -113,11 +119,11 @@ class AvroTurf::ConfluentSchemaRegistry
113
119
  # - nil if the subject or version does not exist
114
120
  # - a list of compatibility issues
115
121
  # https://docs.confluent.io/platform/current/schema-registry/develop/api.html#sr-api-compatibility
116
- def compatibility_issues(subject, schema, version = 'latest')
122
+ def compatibility_issues(subject, schema, version = "latest")
117
123
  data = post("/compatibility/subjects/#{@schema_context_prefix}#{subject}/versions/#{version}",
118
- expects: [200, 404], body: { schema: schema.to_s }.to_json, query: { verbose: true }, idempotent: true)
124
+ expects: [200, 404], body: {schema: schema.to_s}.to_json, query: {verbose: true}, idempotent: true)
119
125
 
120
- data.fetch('messages', []) unless data.has_key?('error_code')
126
+ data.fetch("messages", []) unless data.has_key?("error_code")
121
127
  end
122
128
 
123
129
  # Get global config
@@ -155,7 +161,7 @@ class AvroTurf::ConfluentSchemaRegistry
155
161
  end
156
162
 
157
163
  def request(path, **options)
158
- options = { expects: 200 }.merge!(options)
164
+ options = {expects: 200}.merge!(options)
159
165
  path = File.join(@path_prefix, path) unless @path_prefix.nil?
160
166
  response = @connection.request(path: path, **options)
161
167
  JSON.parse(response.body)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Date
2
4
  def as_avro
3
5
  self
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Enumerable
2
4
  def as_avro
3
5
  map(&:as_avro)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class FalseClass
2
4
  def as_avro
3
5
  self
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Hash
2
4
  def as_avro
3
- hsh = Hash.new
4
- each {|k, v| hsh[k.as_avro] = v.as_avro }
5
+ hsh = {}
6
+ each { |k, v| hsh[k.as_avro] = v.as_avro }
5
7
  hsh
6
8
  end
7
9
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class NilClass
2
4
  def as_avro
3
5
  self
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Numeric
2
4
  def as_avro
3
5
  self
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class String
2
4
  def as_avro
3
5
  self
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Symbol
2
4
  def as_avro
3
5
  to_s
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Time
2
4
  def as_avro
3
5
  iso8601
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class TrueClass
2
4
  def as_avro
3
5
  self
@@ -1,10 +1,12 @@
1
- require 'avro_turf/core_ext/string'
2
- require 'avro_turf/core_ext/numeric'
3
- require 'avro_turf/core_ext/enumerable'
4
- require 'avro_turf/core_ext/hash'
5
- require 'avro_turf/core_ext/time'
6
- require 'avro_turf/core_ext/date'
7
- require 'avro_turf/core_ext/symbol'
8
- require 'avro_turf/core_ext/nil_class'
9
- require 'avro_turf/core_ext/true_class'
10
- require 'avro_turf/core_ext/false_class'
1
+ # frozen_string_literal: true
2
+
3
+ require "avro_turf/core_ext/string"
4
+ require "avro_turf/core_ext/numeric"
5
+ require "avro_turf/core_ext/enumerable"
6
+ require "avro_turf/core_ext/hash"
7
+ require "avro_turf/core_ext/time"
8
+ require "avro_turf/core_ext/date"
9
+ require "avro_turf/core_ext/symbol"
10
+ require "avro_turf/core_ext/nil_class"
11
+ require "avro_turf/core_ext/true_class"
12
+ require "avro_turf/core_ext/false_class"
@@ -1,23 +1,24 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # A cache for the CachedConfluentSchemaRegistry.
2
4
  # Extends the InMemoryCache to provide a write-thru to disk for persistent cache.
3
5
  class AvroTurf::DiskCache
4
-
5
6
  def initialize(disk_path, logger: Logger.new($stdout))
6
7
  @logger = logger
7
8
 
8
9
  # load the write-thru cache on startup, if it exists
9
- @schemas_by_id_path = File.join(disk_path, 'schemas_by_id.json')
10
+ @schemas_by_id_path = File.join(disk_path, "schemas_by_id.json")
10
11
  hash = read_from_disk_cache(@schemas_by_id_path)
11
12
  @schemas_by_id = hash || {}
12
13
 
13
- @ids_by_schema_path = File.join(disk_path, 'ids_by_schema.json')
14
+ @ids_by_schema_path = File.join(disk_path, "ids_by_schema.json")
14
15
  hash = read_from_disk_cache(@ids_by_schema_path)
15
16
  @ids_by_schema = hash || {}
16
17
 
17
- @schemas_by_subject_version_path = File.join(disk_path, 'schemas_by_subject_version.json')
18
+ @schemas_by_subject_version_path = File.join(disk_path, "schemas_by_subject_version.json")
18
19
  @schemas_by_subject_version = {}
19
20
 
20
- @data_by_schema_path = File.join(disk_path, 'data_by_schema.json')
21
+ @data_by_schema_path = File.join(disk_path, "data_by_schema.json")
21
22
  hash = read_from_disk_cache(@data_by_schema_path)
22
23
  @data_by_schema = hash || {}
23
24
  end
@@ -94,11 +95,11 @@ class AvroTurf::DiskCache
94
95
  key = "#{subject}#{version}"
95
96
  hash = read_from_disk_cache(@schemas_by_subject_version_path)
96
97
  hash = if hash
97
- hash[key] = schema
98
- hash
99
- else
100
- { key => schema }
101
- end
98
+ hash[key] = schema
99
+ hash
100
+ else
101
+ {key => schema}
102
+ end
102
103
 
103
104
  write_to_disk_cache(@schemas_by_subject_version_path, hash)
104
105
 
@@ -110,7 +111,7 @@ class AvroTurf::DiskCache
110
111
  private def read_from_disk_cache(path)
111
112
  if File.exist?(path)
112
113
  if File.size(path) != 0
113
- json_data = File.open(path, 'r') do |file|
114
+ json_data = File.open(path, "r") do |file|
114
115
  file.flock(File::LOCK_SH)
115
116
  file.read
116
117
  end
@@ -127,7 +128,7 @@ class AvroTurf::DiskCache
127
128
 
128
129
  private def write_to_disk_cache(path, hash)
129
130
  # don't use "w" because it truncates the file before lock
130
- File.open(path, File::RDWR | File::CREAT, 0644) do |file|
131
+ File.open(path, File::RDWR | File::CREAT, 0o644) do |file|
131
132
  file.flock(File::LOCK_EX)
132
133
  file.write(JSON.pretty_generate(hash))
133
134
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # A cache for the CachedConfluentSchemaRegistry.
2
4
  # Simply stores the schemas and ids in in-memory hashes.
3
5
  class AvroTurf::InMemoryCache
@@ -1,13 +1,15 @@
1
- require 'logger'
2
- require 'avro_turf'
3
- require 'avro_turf/schema_store'
4
- require 'avro_turf/confluent_schema_registry'
5
- require 'avro_turf/cached_confluent_schema_registry'
1
+ # frozen_string_literal: true
2
+
3
+ require "logger"
4
+ require "avro_turf"
5
+ require "avro_turf/schema_store"
6
+ require "avro_turf/confluent_schema_registry"
7
+ require "avro_turf/cached_confluent_schema_registry"
6
8
 
7
9
  # For back-compatibility require the aliases along with the Messaging API.
8
10
  # These names are deprecated and will be removed in a future release.
9
- require 'avro_turf/schema_registry'
10
- require 'avro_turf/cached_schema_registry'
11
+ require "avro_turf/schema_registry"
12
+ require "avro_turf/cached_schema_registry"
11
13
 
12
14
  class AvroTurf
13
15
  class IncompatibleSchemaError < StandardError; end
@@ -56,7 +58,9 @@ class AvroTurf
56
58
  # client_key - Name of file containing client private key to go with client_cert (optional).
57
59
  # client_key_pass - Password to go with client_key (optional).
58
60
  # client_cert_data - In-memory client certificate (optional).
61
+ # client_chain - Name of file containing client certificate chain (optional).
59
62
  # client_key_data - In-memory client private key to go with client_cert_data (optional).
63
+ # client_chain_data - In-memory client certificate chain (optional).
60
64
  # connect_timeout - Timeout to use in the connection with the schema registry (optional).
61
65
  # resolv_resolver - Custom domain name resolver (optional).
62
66
  def initialize(
@@ -73,9 +77,11 @@ class AvroTurf
73
77
  password: nil,
74
78
  ssl_ca_file: nil,
75
79
  client_cert: nil,
80
+ client_chain: nil,
76
81
  client_key: nil,
77
82
  client_key_pass: nil,
78
83
  client_cert_data: nil,
84
+ client_chain_data: nil,
79
85
  client_key_data: nil,
80
86
  connect_timeout: nil,
81
87
  resolv_resolver: nil,
@@ -94,9 +100,11 @@ class AvroTurf
94
100
  password: password,
95
101
  ssl_ca_file: ssl_ca_file,
96
102
  client_cert: client_cert,
103
+ client_chain: client_chain,
97
104
  client_key: client_key,
98
105
  client_key_pass: client_key_pass,
99
106
  client_cert_data: client_cert_data,
107
+ client_chain_data: client_chain_data,
100
108
  client_key_data: client_key_data,
101
109
  path_prefix: registry_path_prefix,
102
110
  connect_timeout: connect_timeout,
@@ -129,7 +137,7 @@ class AvroTurf
129
137
  #
130
138
  # Returns the encoded data as a String.
131
139
  def encode(message, schema_name: nil, namespace: @namespace, subject: nil, version: nil, schema_id: nil, validate: false,
132
- register_schemas: true)
140
+ register_schemas: true)
133
141
  schema, schema_id = if schema_id
134
142
  fetch_schema_by_id(schema_id)
135
143
  elsif subject && version
@@ -139,7 +147,7 @@ class AvroTurf
139
147
  elsif schema_name
140
148
  register_schema(subject: subject, schema_name: schema_name, namespace: namespace)
141
149
  else
142
- raise ArgumentError.new('Neither schema_name nor schema_id nor subject + version provided to determine the schema.')
150
+ raise ArgumentError.new("Neither schema_name nor schema_id nor subject + version provided to determine the schema.")
143
151
  end
144
152
 
145
153
  if validate
@@ -203,7 +211,7 @@ class AvroTurf
203
211
  end
204
212
 
205
213
  # The schema id is a 4-byte big-endian integer.
206
- schema_id = decoder.read(4).unpack("N").first
214
+ schema_id = decoder.read(4).unpack1("N")
207
215
 
208
216
  writers_schema = @schemas_by_id.fetch(schema_id) do
209
217
  schema_json = @registry.fetch(schema_id)
@@ -221,14 +229,14 @@ class AvroTurf
221
229
  # Providing subject and version to determine the schema,
222
230
  # which skips the auto registration of schema on the schema registry.
223
231
  # Fetch the schema from registry with the provided subject name and version.
224
- def fetch_schema(subject:, version: 'latest')
232
+ def fetch_schema(subject:, version: "latest")
225
233
  schema_data = @registry.subject_version(subject, version)
226
- schema_id = schema_data.fetch('id')
227
- schema_type = schema_data['schemaType']
234
+ schema_id = schema_data.fetch("id")
235
+ schema_type = schema_data["schemaType"]
228
236
  if schema_type && schema_type != "AVRO"
229
237
  raise IncompatibleSchemaError, "The #{schema_type} schema for #{subject} is incompatible."
230
238
  end
231
- schema = Avro::Schema.parse(schema_data.fetch('schema'))
239
+ schema = Avro::Schema.parse(schema_data.fetch("schema"))
232
240
  [schema, schema_id]
233
241
  end
234
242
 
@@ -1,18 +1,39 @@
1
- require 'avro_turf/schema_store'
1
+ # frozen_string_literal: true
2
+
3
+ require "avro_turf/schema_store"
2
4
 
3
5
  class AvroTurf
4
6
  # A schema store that allows you to add or remove schemas, and to access
5
7
  # them externally.
8
+ #
9
+ # Only the top-level schema is cached. It is important to not register
10
+ # sub-schema as other schemas may define the same sub-schema and
11
+ # the Avro gem will raise an Avro::SchemaParseError when parsing another
12
+ # schema with a subschema with the same name as one encounted previously:
13
+ # <Avro::SchemaParseError: The name "foo.bar" is already in use.>
14
+ #
15
+ # Essentially, the only schemas that should be resolvable in @schemas
16
+ # are those that have their own .avsc files on disk.
17
+ #
18
+ # See https://github.com/dasch/avro_turf/pull/111
19
+ # and the implementation in AvroTurf::SchemaStore#load_schema!
6
20
  class MutableSchemaStore < SchemaStore
7
21
  attr_accessor :schemas
8
22
 
9
23
  # @param schema_hash [Hash]
10
24
  def add_schema(schema_hash)
11
- name = schema_hash['name']
12
- namespace = schema_hash['namespace']
25
+ name = schema_hash["name"]
26
+ namespace = schema_hash["namespace"]
13
27
  full_name = Avro::Name.make_fullname(name, namespace)
14
28
  return if @schemas.key?(full_name)
15
- Avro::Schema.real_parse(schema_hash, @schemas)
29
+
30
+ # We pass in copy of @schemas which Avro can freely modify
31
+ # and register the sub-schema. It doesn't matter because
32
+ # we will discard it.
33
+ schema = Avro::Schema.real_parse(schema_hash, @schemas.dup)
34
+ @schemas[full_name] = schema
35
+
36
+ schema
16
37
  end
17
38
  end
18
39
  end
@@ -1,4 +1,6 @@
1
- require 'avro_turf/confluent_schema_registry'
1
+ # frozen_string_literal: true
2
+
3
+ require "avro_turf/confluent_schema_registry"
2
4
 
3
5
  # AvroTurf::SchemaRegistry is deprecated and will be removed in a future release.
4
6
  # Use AvroTurf::ConfluentSchemaRegistry instead.