Strech / avrora

A convenient Elixir library to work with Avro messages, schemas and Confluent® Schema Registry
https://hexdocs.pm/avrora
MIT License
97 stars 33 forks source link

hook to skip certain fields. #104

Closed sudeepdino008 closed 1 year ago

sudeepdino008 commented 1 year ago

I'm writing a hook to skip certain fields. Borrowing the structure from erlavro

Here's the code:


defmodule MyClient do
  use Avrora.Client,
    otp_app: :rudder,
    registry_url: "http://localhost:8081",
    registry_auth: {:basic, ["username", "password"]},
    schemas_path: "priv/schemas/",
    registry_schemas_autoreg: false,
    convert_null_values: false,
    convert_map_to_proplist: false,
    names_cache_ttl: :infinity,
    decoder_hook: &MyClient.decoder_hook/4

  def decoder_hook(type, subNameOrIndex, data, decodeFun) do
    IO.puts("\n----------------\n")

    IO.inspect(:avro.get_type_fullname(type), label: "type_fullname")
    IO.inspect(:avro.get_type_name(type), label: "type_name")
    IO.inspect(:avro.get_type_namespace(type), label: "namespace")
    IO.inspect(subNameOrIndex, label: "subNameOrIndex")

    case {:avro.get_type_fullname(type), subNameOrIndex} do
      {"io.Payment2", "amount"} ->
        # decodeFun.(data)
        nil;

      {_, _} ->
        decodeFun.(data)
    end
  end

  def test() do
    #Avrora.AvroSchemaStore.start_link()
    {:ok, oldschema2} =
      MyClient.Schema.Encoder.from_json(
        ~s({ "type": "record", "name": "Payment2", "namespace": "io", "fields": [{  "name": "id",  "type": "string"},{  "name": "amount",  "type": "double"} ]  }  )
      )

    oldschema = %{oldschema2 | id: nil, version: nil}
    payload = %{"id" => "123", "amount" => 123.45}

    {:ok, encoded} = MyClient.Codec.ObjectContainerFile.encode(payload, schema: oldschema)
    IO.inspect(encoded, label: "encoded value")

    {:ok, [decoded]} = MyClient.Codec.ObjectContainerFile.decode(encoded)
    IO.puts("\n----------------\n")

    IO.inspect(decoded, label: "decoded value")
  end
end

However on running:

iex(1)> MyClient.start_link()
{:ok, #PID<0.252.0>}
iex(2)> MyClient.test()
encoded value: <<79, 98, 106, 1, 3, 186, 2, 20, 97, 118, 114, 111, 46, 99, 111, 100, 101, 99,
  8, 110, 117, 108, 108, 22, 97, 118, 114, 111, 46, 115, 99, 104, 101, 109, 97,
  254, 1, 123, 34, 110, 97, 109, 101, 115, 112, 97, 99, 101, 34, 58, ...>>

----------------

type_fullname: "io.Payment2"
type_name: "Payment2"
namespace: "io"
subNameOrIndex: :none

----------------

type_fullname: "io.Payment2"
type_name: "Payment2"
namespace: "io"
subNameOrIndex: "id"

----------------

type_fullname: "string"
type_name: "string"
namespace: ""
subNameOrIndex: []

----------------

type_fullname: "io.Payment2"
type_name: "Payment2"
namespace: "io"
subNameOrIndex: "amount"
** (MatchError) no match of right hand side value: {:error, :schema_mismatch}
    (avrora 0.26.0) lib/avrora/myclient.ex:44: MyClient.test/0
    iex:2: (file)

Can someone advice me on how to think about the hook in general? I want to skip the io.Payment2.amount field

sudeepdino008 commented 1 year ago

hi, any pointers please?

Strech commented 1 year ago

Hi @sudeepdino008 I highly discourage such type of "consumerism" in the OSS world and consider it quite offensive. Please be more respectful to the private time others spend working on this project.

As the last tip here is answer on your question: "There is no way to skip the field because it violates entire idea of schema matching the data". You can only amend/skip fields, i.e don't decode them (is a skip) or manipulate the result (i.e update the value).

P.S: Any subsequent requests with the same tone will be closed without explanation