flipp-oss / deimos

Framework to work with Kafka, Avro and ActiveRecord
Other
59 stars 22 forks source link

Deimos::Producer#publish unable to consolidate BigDecimal and float types for sub-records #72

Closed JennyFlipp closed 3 years ago

JennyFlipp commented 4 years ago

Deimos::Producer#publish unable to consolidate BigDecimal and float types for sub-records.

Currently: calling publish returns the following error after item was converted into a sub-record: Avro::SchemaValidator::ValidationError: at .item.price expected type float, got BigDecimal with value 0.37999e3 at .item.original_price expected type float, got BigDecimal with value 0.39999e3

      # @param job [Bullwhip::Job] The Bullwhip job object
      # @param item [Item] The item object
      # return [Hash] Returns a ItemScraperResponse payload
      def generate_payload(job, item)
        # Possible defect in Deimos causes SchemaValidator to be unable to
        # consolidate BigData and float types for subtype records

        { external_id: job.external_id,
          merchant_name_identifier: job.parameters[:merchant_name_identifier],
          url: job.parameters[:url],
          language: job.parameters[:language],
          item: item.attributes }
      end

PREVIOUSLY: No errors when item attributes were sent within the payload directly.

      def generate_payload(job, item)
        { external_id: job.external_id,
          merchant_name_identifier: job.parameters[:merchant_name_identifier],
          url: job.parameters[:url],
          language: job.parameters[:language] }.merge(item)
DeeChau commented 3 years ago

Looks like this bug was introduced by SchemaBackends. Here's a description and outline of how the error occurs. For the following payload, test_id and test_float are correctly coerced by Deimos::SchemaBackends::Base.coerce

payload = {
  'test_id' => 'foo',
  'test_float' => BigDecimal('123.456'),
  'nested_record' => {
    'some_int' => 123,
    'some_float' => BigDecimal('456.789'),
    'some_string' => '123',
    'some_optional_int' => nil
  }
}

Once it reaches nested_record, the schema type is a :record and this is an unhandled case in the AvroSchemaCoercer which returns the same value, and not converting the some_float to a float.