Skip to content

feat(QTDI-1305): improve error in record #1041

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 22 commits into
base: master
Choose a base branch
from

Conversation

yyin-talend
Copy link
Collaborator

Requirements

  • Any code change adding any logic MUST be tested through a unit test executed with the default build
  • Any API addition MUST be done with a documentation update if relevant

Why this PR is needed?

What does this PR adds (design/code thoughts)?

@yyin-talend yyin-talend changed the title Yyin/QTDI-1305 improve error in record feat(QTDI-1305): improve error in record May 7, 2025

This comment has been minimized.

@yyin-talend yyin-talend requested a review from undx May 8, 2025 07:39

This comment has been minimized.

This comment has been minimized.

Copy link

sonar-eks bot commented May 9, 2025

Failed

  • 78.80% Coverage on New Code (is less than 80.00%)
  • 4.56% Duplicated Lines (%) on New Code (is greater than 3.00%)

Analysis Details

7 Issues

  • Bug 0 Bugs
  • Vulnerability 0 Vulnerabilities
  • Code Smell 7 Code Smells

Coverage and Duplications

  • Coverage 78.80% Coverage (56.40% Estimated after merge)
  • Duplications 4.56% Duplicated Code (1.40% Estimated after merge)

Project ID: org.talend.sdk.component:component-runtime

View in SonarQube

Copy link
Member

@undx undx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As said in comments, I think that errors should be handled at record level not schema one.
The workflow expects that checking for bad values is done outside the framework.
Maybe, we could handle rather in it?

Another lead may be :

  • define rules for bad data handling in schema
  • use the usual withType in Record. (checking is done here as for null values handling).
    wdyt?

@@ -34,6 +34,8 @@

public interface Record {

String RECORD_ERROR_SUPPORT = "talend.sdk.runtime.record.error.support";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Usage in framework is to use talend.component. as a prefix for system properties.

@@ -311,6 +313,11 @@ default Optional<Record> getOptionalRecord(final String name) {
return ofNullable(get(Record.class, name));
}

default boolean isValid() {
return !getSchema().getAllEntries()
.anyMatch(entry -> !entry.isValid());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See sonar comment, more easy to read that double negation.

/**
* @return true if the value of this entry is valid; false for invalid value.
*/
boolean isValid();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can also add a default behavior as returning true...

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not using schema, but using Entry.

Comment on lines +40 to +46
String ENTRY_IS_ON_ERROR = "entry.on.error";

String ENTRY_ERROR_MESSAGE = "entry.error.message";

String ENTRY_ERROR_FALLBACK_VALUE = "entry.error.fallback.value";

String ERROR_EXCEPTION = "entry.error.exception";
Copy link
Member

@undx undx May 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see my previous comment. Maybe smtg like record.value.

@@ -163,6 +163,10 @@ public String getProp(final String property) {
public Builder toBuilder() {
throw new UnsupportedOperationException("#toBuilder()");
}

@Override
public boolean isValid() { return true; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See previous comments...

assertNotNull(entry2);
Assertions.assertFalse(entry2.isValid());

System.setProperty(Record.RECORD_ERROR_SUPPORT, "false");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use the before and after annotations to handle this...


@Emitter
public SupportErrorInput createSource() {

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

empty line, applied formater?

@GridLayout(value = {
@GridLayout.Row("dataset"),
})
@Version
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indentation

Comment on lines +237 to +254
Schema customerSchema = schemaBuilder.withEntry(nameEntry).withEntry(nmEntry).withEntry(ageEntry).build();
// record 1
Record.Builder recordBuilder = factory.newRecordBuilder(customerSchema);
Record record1 = recordBuilder.withError("name", null, "Stirng is null", null)
.withString("normal", "normal")
.withError("age", "string", "is not an int", null)
.build();
assertFalse(record1.isValid());

final Schema.Entry entry =
record1.getSchema().getEntries().stream().filter(e -> "name".equals(e.getName())).findAny().get();
assertNotNull(entry);
Assertions.assertFalse(entry.isValid());

final Schema.Entry entry2 =
record1.getSchema().getEntries().stream().filter(e -> "age".equals(e.getName())).findAny().get();
assertNotNull(entry2);
Assertions.assertFalse(entry2.isValid());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, we're testing the Record/Schema implementations, not the Avro related.

Comment on lines +524 to +535
// duplicate the schema instance with a modified Entry
final Entry oldEntry = this.findExistingEntry(columnName);
final Entry updateEntry = oldEntry.toBuilder()
.withName(columnName)
.withNullable(true)
.withType(oldEntry.getType())
.withProp(SchemaProperty.ENTRY_IS_ON_ERROR, "true")
.withProp(SchemaProperty.ENTRY_ERROR_MESSAGE, errorMessage)
.withProp(SchemaProperty.ENTRY_ERROR_FALLBACK_VALUE, String.valueOf(value))
.withProp(SchemaProperty.ERROR_EXCEPTION, exception == null ? "" : exception.toString())
.build();
return updateEntryByName(columnName, updateEntry);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This intent expects that value is always in error.

@undx
Copy link
Member

undx commented May 9, 2025

Discussed with Yves and forget my comments on Schema level vs Record Level.
Removing my comments for clarity.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants