salsify / avromatic

Generate Ruby models from Avro schemas
MIT License
89 stars 17 forks source link

Create model from remote schema registry #158

Closed dobryakov closed 7 months ago

dobryakov commented 1 year ago

Please provide an example how to configure gem to create models only from remote schema registry.

The provided examples based on local-stored schemas while all my schemas are stored remotely in Confluent Cloud with password-protected access. I have no any schemas locally. Which attributes should I pass to configure method?

jturkel commented 1 year ago

I would definitely recommend caching the schemas locally for a faster and more reliable application startup but you could do something like the following if you wanted to dynamically load them from Confluent Cloud:

# Implement the SchemaStore interface to lookup the schema in the Schema Registry
class MyRegistrySchemaStore
  def initialize(registry)
    @registry = registry
  end

  def find(name, namespace = nil)
    # You might have to customize this based on your algorithm 
    subject = namespace ?  "#{namespace}.#{name}" : name
    schema_json = @registry.subject_version(subject, 'latest')
    Avro::Schema.parse(schema_json)
  end
end

Avromatic.configure do |config|
  config.schema_registry = AvroTurf::ConfluentSchemaRegistry.new("http://my-registry:8081/", user: "foo", password: "bar")
  config.schema_store = MyRegistrySchemaStore.new(config.schema_registry)
  config.build_messaging!
end

# Create your models like normal even though this will make a network request
class MyModel
  include Avromatic::Model.build(schema_name: :my_model)
end

Alternatively if the SchemaStore interface doesn't provide the necessary flexibility for your use case you could do something like the following:

# You shouldn't need to configure a Schema Store since you're always manually building schemas
Avromatic.configure do |config|
  config.schema_registry = AvroTurf::ConfluentSchemaRegistry.new("http://my-registry:8081/", user: "foo", password: "bar")
  config.build_messaging!
end

class MyRegistryClient
  include Singleton

  def initialize
    @registry = AvroTurf::ConfluentSchemaRegistry.new("http://my-registry:8081/", user: "foo", password: "bar")
  end

  def find(namespace:, name:, version:)
    # You might have to customize this based on your algorithm 
    subject = namespace ?  "#{namespace}.#{name}" : name
    schema_json = @registry.subject_version(subject, version)
    Avro::Schema.parse(schema_json)
  end
end

class MyModel
  schema = MyRegistryClient.instance.find(namespace: 'com.salsify', name: 'product', version: 5)
  include Avromatic::Model.build(schema: schema)
end