PDGGK opened a new pull request, #39760:
URL: https://github.com/apache/beam/pull/39760

   **Please add a meaningful description for your change here**
   
   Follow-up to #39759, which fixed the identical defect in 
`TFRecordWriteSchemaTransformProvider`. Same bug, different module, so it is a 
separate PR.
   
   `ErrorCounterFn` (and `GenericRecordErrorCounterFn`) are handed `errorSchema 
= ErrorHandling.errorSchema(inputSchema)` and emit 
`ErrorHandling.errorRecord(errorSchema, row, e)`, so every row on `ERROR_TAG` 
carries exactly that schema. The collection was then tagged with the wrapper 
applied a **second** time:
   
   ```java
   Schema errorSchema = ErrorHandling.errorSchema(inputSchema);                 
   // :246
   ...
   new ErrorCounterFn("Kafka-write-error-counter", toBytesFn, errorSchema, 
handleErrors)
   ...
   receiver.get(ERROR_TAG).output(ErrorHandling.errorRecord(errorSchema, row, 
e)); // :161
   ...
   
outputTuple.get(ERROR_TAG).setRowSchema(ErrorHandling.errorSchema(errorSchema));
 // :301
   ```
   
   `errorSchema(x)` is `{failed_row: Row(x), error_message: STRING}`, so the 
declared shape becomes `{failed_row: {failed_row: …, error_message: …}, 
error_message: …}` — which no element this transform produces can match.
   
   `KafkaReadSchemaTransformProvider` gets it right in the same package, and so 
do `JavaFilterTransformProvider`, `JavaMapToFieldsTransformProvider`, 
`PubsubRowToMessage`, `PubsubWriteSchemaTransformProvider` and 
`BigQueryStorageWriteApiSchemaTransformProvider`.
   
   ### Why the existing tests did not catch it
   
   `KafkaWriteSchemaTransformProviderTest` exercises `ErrorCounterFn` by 
applying the `ParDo` directly and then calling `setRowSchema(errorSchema)` 
itself:
   
   ```java
   PCollectionTuple output = input.apply(ParDo.of(new 
ErrorCounterFn(...)).withOutputTags(...));
   output.get(ERROR_TAG).setRowSchema(errorSchema);        // the test's own, 
correct, tagging
   ```
   
   So the four `ErrorFn` tests never reach line 301. The one test that does 
build the whole transform, `testBuildTransformWithManaged`, does not look at 
the output schema.
   
   ### Test
   
   One, and it needs no runner — the schema is fixed while the graph is built, 
so it runs in the ordinary `:sdks:java:io:kafka:test` task. It goes through 
`expand()`, which is the gap above.
   
   Restoring the second wrap fails it and nothing else:
   
   ```
   7 tests completed, 1 failed
   
   KafkaWriteSchemaTransformProviderTest > 
testErrorOutputCarriesTheSchemaErrorCounterFnEmits FAILED
       java.lang.AssertionError:
       expected:<{ failed_row: ROW { bytes: BYTES }, error_message: STRING }>
        but was:<{ failed_row: ROW { failed_row: ROW { bytes: BYTES }, 
error_message: STRING }, error_message: STRING }>
   ```
   
   Note this needs a clean recompile to reproduce — running it incrementally on 
top of a previous build makes `KafkaIO.writeRecords` throw 
`NullPointerException: Null eosTriggerTimeout` in both this test and 
`testBuildTransformWithManaged`, from stale AutoValue output rather than from 
the change. With `--rerun-tasks` only the one test fails.
   
   `spotlessJavaCheck`, `checkstyleMain` and `checkstyleTest` on 
`:sdks:java:io:kafka` are clean.
   
   ### Are there user-facing changes?
   
   Yes, for anyone reading the `errors` output of the Kafka write 
`SchemaTransform`: it is now tagged with the schema its rows actually have. 
Code that hardcoded the doubly-nested shape to work around this would need 
updating, but such code could not have been reading real rows successfully.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to