class Avrolution::CompatibilityCheck
Constants
- BACKWARD
- BOTH
- FORWARD
- FULL
- NONE
Attributes
incompatible_schemas[R]
Public Class Methods
new(logger: Avrolution.logger)
click to toggle source
# File lib/avrolution/compatibility_check.rb, line 23 def initialize(logger: Avrolution.logger) @incompatible_schemas = [] @schema_registry = build_schema_registry @compatibility_breaks = Avrolution::CompatibilityBreaksFile.load @logger = logger end
Public Instance Methods
call()
click to toggle source
# File lib/avrolution/compatibility_check.rb, line 30 def call check_schemas(Avrolution.root) self end
success?()
click to toggle source
# File lib/avrolution/compatibility_check.rb, line 35 def success? incompatible_schemas.empty? end
Private Instance Methods
build_schema_registry()
click to toggle source
# File lib/avrolution/compatibility_check.rb, line 123 def build_schema_registry AvroSchemaRegistry::Client.new(Avrolution.compatibility_schema_registry_url, logger: Avrolution.logger) end
check_schema_compatibility(file)
click to toggle source
# File lib/avrolution/compatibility_check.rb, line 50 def check_schema_compatibility(file) json = File.read(file) schema = Avro::Schema.parse(json) return unless schema.type_sym == :record fullname = schema.fullname fingerprint = schema.sha256_resolution_fingerprint.to_s(16) logger.info("Checking compatibility: #{fullname}") return if schema_registered?(fullname, schema) compatible = schema_registry.compatible?(fullname, schema, 'latest') if compatible.nil? # compatible is nil if the subject is not registered logger.info("... New schema: #{fullname}") elsif !compatible && !compatibility_fallback(schema, fullname, fingerprint) incompatible_schemas << file report_incompatibility(json, schema, fullname, fingerprint) end end
check_schemas(path)
click to toggle source
# File lib/avrolution/compatibility_check.rb, line 41 def check_schemas(path) vendor_bundle_path = File.join(path, 'vendor/bundle/') Dir[File.join(path, '**/*.avsc')].reject do |file| file.start_with?(vendor_bundle_path) end.each do |schema_file| check_schema_compatibility(schema_file) end end
compatibility_fallback(schema, fullname, fingerprint)
click to toggle source
For a schema that is incompatible with the latest registered schema, check if there is a compatibility break defined and check compatibility using the level defined by the break.
# File lib/avrolution/compatibility_check.rb, line 81 def compatibility_fallback(schema, fullname, fingerprint) compatibility_break = compatibility_breaks[[fullname, fingerprint]] if compatibility_break logger.info("... Checking compatibility with level set to #{compatibility_break.with_compatibility}") schema_registry.compatible?( fullname, schema, 'latest', with_compatibility: compatibility_break.with_compatibility ) else false end end
report_incompatibility(json, schema, fullname, fingerprint)
click to toggle source
# File lib/avrolution/compatibility_check.rb, line 94 def report_incompatibility(json, schema, fullname, fingerprint) last_json = schema_registry.subject_version(fullname)['schema'] last_schema = Avro::Schema.parse(last_json) backward = schema.read?(last_schema) forward = last_schema.read?(schema) compatibility_with_last = if backward && forward FULL elsif backward BACKWARD elsif forward FORWARD else NONE end logger.info("... Compatibility with last version: #{compatibility_with_last}") logger.info(Diffy::Diff.new(last_json, json, context: 3).to_s) unless compatibility_with_last == FULL compatibility = schema_registry.subject_config(fullname)['compatibility'] || schema_registry.global_config['compatibility'] compatibility = FULL if compatibility == BOTH logger.info("... Current compatibility level: #{compatibility}") logger.info( "\n To allow a compatibility break, run:\n" \ " rake avro:add_compatibility_break name=#{fullname} fingerprint=#{fingerprint} " \ "with_compatibility=#{compatibility_with_last} [after_compatibility=<LEVEL>]\n" ) end
schema_registered?(fullname, schema)
click to toggle source
# File lib/avrolution/compatibility_check.rb, line 72 def schema_registered?(fullname, schema) schema_registry.lookup_subject_schema(fullname, schema) rescue Excon::Errors::NotFound nil end