Skip to content

MINOR - Data Contracts only execute tests without results#26429

Open
pmbrull wants to merge 75 commits intomainfrom
task/fix-conflicts-and-review-pr-23335-d42f1f3d
Open

MINOR - Data Contracts only execute tests without results#26429
pmbrull wants to merge 75 commits intomainfrom
task/fix-conflicts-and-review-pr-23335-d42f1f3d

Conversation

@pmbrull
Copy link
Copy Markdown
Collaborator

@pmbrull pmbrull commented Mar 12, 2026

Summary

Rebases and resolves conflicts for PR #23335 (dc-dq-execute-summary) against current main.

Core changes from original PR:

  • Split data contract validation into two paths: tests WITH existing results compile data from latest results, tests WITHOUT results execute via the DQ pipeline
  • Add bidirectional dataContract field to testCase.json schema so test cases can reference their parent contracts
  • Add v1130 migration to backfill dataContract references on existing test cases
  • Update ContractQualityCard to use latestContractResults.qualityValidation prop instead of fetching test suite summary separately
  • Add 3 DAO methods in CollectionDAO.java for managing test case references (PostgreSQL jsonb_set vs MySQL JSON_SET)
  • New search filter for dataContractId in TestCaseResultResource

Conflict resolutions:

  • Migration (mysql/postgres v1110): Kept the flyway migration refactor from main (moved to MigrationWorkflow.loadMigrations()) + added the new migrateTestCaseDataContractReferences call
  • TestCaseMapper: Merged withTopDimensions from main with the dataContract conditional set from the PR
  • ContractDetail.tsx: Kept the security section restructure from main + updated the quality section to use !isEmpty(contract?.qualityExpectations) condition and pass latestContractResults prop
  • ContractDetail.test.tsx: Merged PR's qualityExpectations condition with main's additional entityId/entityType props
  • Test files (DataContractResourceTest, TestCaseResourceTest): Kept deleted (removed in Delete Old Integration tests and fix sonar workflow #26204 cleanup)

Additional fix:

  • Fixed invalid JSON in JP elasticsearch test_case_result_index_mapping.json (was broken in the original PR branch due to structural issues)

Test plan

  • Verify data contract validation correctly splits tests into with/without results paths
  • Verify ContractQualityCard renders quality validation data from contract results
  • Verify test case creation with dataContract reference works
  • Verify v1110 migration correctly backfills dataContract references on existing test cases
  • Verify all 4 locale elasticsearch mappings (en, jp, zh, ru) are valid JSON
  • Run mvn spotless:apply to ensure Java formatting
  • Run frontend lint/tests

Summary by Gitar

  • Database & DAO:
    • Added robust DAO methods for entity_extension versioning, field-change tracking, and relationship count queries.
    • Implemented FeedDAO enhancements to support Task, Announcement, and ActivityStream operations.
  • Migrations:
    • Added v200 migrations to handle Task entity migration, legacy activity thread conversion, and announcement relationship backfilling.
  • Test Resilience:
    • Introduced executeWithDeadlockRetry in TestCaseResourceIT to mitigate transient database deadlocks during entity updates.
    • Adjusted Awaitility timeouts from 30s to 90s-180s in integration tests to reduce flakiness.
  • Schema Updates:
    • Added autoCloseIncident boolean field to testCase.json to support automatic incident resolution.

This will update automatically on new commits.

pmbrull and others added 30 commits September 10, 2025 17:58
pmbrull and others added 2 commits April 1, 2026 12:16
The method isSupportedEntityType was renamed to isEntityTypeSupported and
made public, causing NoSuchMethod errors and mock interception failures.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…refs

- Use contract.entity.fullyQualifiedName instead of route FQN for test
  case entityLink query (fixes wrong test cases for non-table contracts)
- Remove invalid FQN fallback using contract route FQN
- Add null-safety in validateDQ for QualityValidation fields
- Call compileResult when only testsWithoutResults exist so
  schema/semantics failures are surfaced while DQ is pending
- Add bulk DAO method to remove dataContract refs by contract ID,
  preventing dangling references on contract deletion

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 26 out of 28 changed files in this pull request and generated 3 comments.

Comment on lines 185 to 193
expect(getListTestCaseBySearch).toHaveBeenCalledWith(
expect.objectContaining({
testSuiteId: MOCK_DATA_CONTRACT.testSuite.id,
entityLink: '<#E::table::fqn>',
include: 'non-deleted',
includeAllTests: true,
limit: 10000,
sortField: 'testCaseResult.timestamp',
sortType: 'desc',
})
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

The expectation for entityLink is hardcoded to <#E::table::fqn>, but the component builds it from contract.entity.fullyQualifiedName via generateEntityLink(entityFqn). With the current MOCK_DATA_CONTRACT (entity FQN redshift prod.dev.dbt_jaffle.customers), this assertion will fail. Update the test to derive the expected entityLink from the mock contract (or mock generateEntityLink to return a stable value) so it matches the component behavior.

Copilot uses AI. Check for mistakes.
Comment on lines +1237 to +1249
return dataContract.getQualityExpectations().stream()
.map(
testRef -> {
try {
return testCaseRepository.get(
null, testRef.getId(), new Fields(Set.of(TEST_CASE_RESULT)));
} catch (EntityNotFoundException e) {
LOG.warn("Test case {} not found: {}", testRef.getId(), e.getMessage());
return null;
}
})
.filter(Objects::nonNull)
.collect(Collectors.toList());
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

getTestsWithResults() fetches each test case individually via testCaseRepository.get(...) for every quality expectation. This introduces an N+1 pattern during contract create/update and validation (and can be called multiple times per request path), which may become a bottleneck for contracts with many test cases. Consider using a bulk DAO/repository fetch (batch by IDs) or reusing an already-fetched list within the same operation to avoid repeated per-test queries.

Suggested change
return dataContract.getQualityExpectations().stream()
.map(
testRef -> {
try {
return testCaseRepository.get(
null, testRef.getId(), new Fields(Set.of(TEST_CASE_RESULT)));
} catch (EntityNotFoundException e) {
LOG.warn("Test case {} not found: {}", testRef.getId(), e.getMessage());
return null;
}
})
.filter(Objects::nonNull)
.collect(Collectors.toList());
// Collect unique, non-null test case IDs from the quality expectations
List<UUID> testCaseIds =
dataContract.getQualityExpectations().stream()
.map(EntityReference::getId)
.filter(Objects::nonNull)
.distinct()
.collect(Collectors.toList());
if (testCaseIds.isEmpty()) {
return Collections.emptyList();
}
// Bulk-fetch all test cases with their latest results
List<TestCase> fetchedTests =
testCaseRepository.getByIds(testCaseIds, new Fields(Set.of(TEST_CASE_RESULT)));
// Index fetched tests by ID for quick lookup
Map<UUID, TestCase> testsById =
fetchedTests.stream()
.filter(Objects::nonNull)
.collect(Collectors.toMap(TestCase::getId, test -> test, (left, right) -> left));
// Preserve original order from quality expectations and log missing tests
List<TestCase> result = new ArrayList<>();
dataContract.getQualityExpectations().forEach(
testRef -> {
if (testRef.getId() == null) {
return;
}
TestCase test = testsById.get(testRef.getId());
if (test == null) {
LOG.warn("Test case {} not found during bulk fetch", testRef.getId());
return;
}
result.add(test);
});
return result;

Copilot uses AI. Check for mistakes.
Comment on lines 153 to 163
it('should render loader when data is loading', async () => {
render(
<MemoryRouter>
<ContractQualityCard contract={MOCK_DATA_CONTRACT} />
</MemoryRouter>
);

await waitFor(() => {
expect(screen.getByTestId('loader')).toBeInTheDocument();
});
});
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

The loader test doesn't set up getListTestCaseBySearch to return a pending promise. Since the mock currently returns undefined, await getListTestCaseBySearch(...) resolves immediately and the destructuring throws, causing the finally to set isTestCaseLoading back to false in the same tick. With React 18 batching this can make the loader render non-deterministic/flaky. Make the mock return a never-resolving promise (or a controllable deferred) for this test so the loading state remains true while asserting the loader.

Copilot uses AI. Check for mistakes.
pmbrull and others added 2 commits April 22, 2026 16:05
… v2.0.0

Conflicts resolved by keeping both sides (independent additions).
Moved migrateTestCaseDataContractReferences from v1130 to v200
since 1.13 is already released.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

✅ TypeScript Types Auto-Updated

The generated TypeScript types have been automatically updated based on JSON schema changes in this PR.

…act/ContractDetailTab/ContractDetail.test.tsx

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review is ineligible. To be eligible to request a review, you need a paid Copilot license, or your organization must enable Copilot code review.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review is ineligible. To be eligible to request a review, you need a paid Copilot license, or your organization must enable Copilot code review.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review is ineligible. To be eligible to request a review, you need a paid Copilot license, or your organization must enable Copilot code review.

pmbrull and others added 2 commits April 28, 2026 10:36
Merge PR #23335 changes onto main with migration moved to v2.0.0.

Changes:
- Data contracts now only execute tests that don't already have results
- Add dataContract reference to test cases for filtering
- Add dataContractId filter to test case result search API
- Move migrateTestCaseDataContractReferences to v2.0.0 migration

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…hub.com:open-metadata/OpenMetadata into task/fix-conflicts-and-review-pr-23335-d42f1f3d
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 26 out of 28 changed files in this pull request and generated 5 comments.


jest.mock('../../../rest/testAPI', () => ({
getTestCaseExecutionSummary: jest.fn(),
getListTestCaseBySearch: jest.fn(),
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

The getListTestCaseBySearch mock has no default resolved value. In tests that render the component without explicitly setting mockResolvedValue (e.g., the loader test), the component will await the mock, destructure { data }, and can throw because the mock returns undefined by default. Consider setting a safe default (e.g., resolving to { data: [] }) and overriding per-test when needed.

Suggested change
getListTestCaseBySearch: jest.fn(),
getListTestCaseBySearch: jest.fn().mockResolvedValue({ data: [] }),

Copilot uses AI. Check for mistakes.
Comment on lines 273 to 289
await waitFor(() => {
const links = screen.getAllByRole('link');

expect(links[0]).toHaveAttribute('href', '/test-case/table.test_case_1');
expect(links[1]).toHaveAttribute('href', '/test-case/table.test_case_2');
expect(links[2]).toHaveAttribute('href', '/test-case/table.test_case_3');
});
});

it('should handle test cases with missing test results', async () => {
const testCasesWithoutResults: TestCase[] = [
{
id: 'test-case-4',
name: 'Test Case 4',
fullyQualifiedName: 'table.test_case_4',
} as TestCase,
];

(getTestCaseExecutionSummary as jest.Mock).mockResolvedValue(
mockTestSummary
);
(getListTestCaseBySearch as jest.Mock).mockResolvedValue({
data: testCasesWithoutResults,
});

render(
<MemoryRouter>
<ContractQualityCard contract={MOCK_DATA_CONTRACT} />
</MemoryRouter>
);

await waitFor(() => {
expect(screen.getByText('Test Case 4')).toBeInTheDocument();
expect(links[0]).toHaveAttribute(
'href',
'/test-case/CLV Must be Positive'
);
expect(links[1]).toHaveAttribute(
'href',
'/test-case/Customer ID To Be Unique'
);
expect(links[2]).toHaveAttribute(
'href',
'/test-case/Table Row Count To Equal'
);
});
});
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

This link assertion expects navigation to use the test case display/name (with spaces). The UI route helper getTestCaseDetailPagePath is designed for the test case FQN (which is derived from the entity FQN + quoted test name). To avoid masking regressions, update the test data so MOCK_DATA_CONTRACT.qualityExpectations and mockTestCases share the same IDs and the component can resolve matchedTestCase.fullyQualifiedName, then assert the href uses that FQN (encoded).

Copilot uses AI. Check for mistakes.
@@ -243,6 +251,8 @@ protected void postDelete(DataContract dataContract, boolean hardDelete) {
if (!nullOrEmpty(dataContract.getQualityExpectations())) {
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

postDelete deletes the test suite whenever qualityExpectations is non-empty, but deleteTestSuite() calls getOrCreateTestSuite(). With the new logic that can clear dataContract.testSuite when no tests are pending, this path can end up creating a new logical test suite during deletion just to delete it. Gate this on contractHasTestSuite(dataContract) (or make deleteTestSuite only delete an existing suite by reference/name without creating one).

Suggested change
if (!nullOrEmpty(dataContract.getQualityExpectations())) {
if (!nullOrEmpty(dataContract.getQualityExpectations())
&& dataContract.getTestSuite() != null) {

Copilot uses AI. Check for mistakes.
Comment on lines +896 to 900
private void updateTestSuiteTests(
DataContract dataContract, TestSuite testSuite, List<TestCase> testsWithoutResults) {
TestCaseRepository testCaseRepository =
(TestCaseRepository) Entity.getEntityRepository(Entity.TEST_CASE);

Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

In updateTestSuiteTests(...), testCaseRefs is still computed from dataContract.getQualityExpectations() but no longer used after switching removal logic to testsToAdd. Please remove the unused local (or use it) to avoid confusion about which source of truth drives add/remove behavior.

Copilot uses AI. Check for mistakes.
Comment on lines +1881 to +1885
daoCollection
.testCaseDAO()
.updateTestCaseDataContract(
testCaseRef.getId().toString(), JsonUtils.pojoToJson(dataContractRef));

Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

updateTestCasesWithDataContract updates test_case.json directly via updateTestCaseDataContract(...) (JSON_SET/jsonb_set). This bypasses the normal TestCaseRepository update flow (versioning/updatedAt+updatedBy tracking, change events, and any search-index update hooks). If the intent is to keep the back-reference in sync for UI/search, consider performing an entity update through the repository/updater (or otherwise ensuring downstream indexing/auditing stays consistent).

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review is ineligible. To be eligible to request a review, you need a paid Copilot license, or your organization must enable Copilot code review.

@github-actions
Copy link
Copy Markdown
Contributor

The Java checkstyle failed.

Please run mvn spotless:apply in the root of your repository and commit the changes to this PR.
You can also use pre-commit to automate the Java code formatting.

You can install the pre-commit hooks with make install_test precommit_install.

@github-actions
Copy link
Copy Markdown
Contributor

The Java checkstyle failed.

Please run mvn spotless:apply in the root of your repository and commit the changes to this PR.
You can also use pre-commit to automate the Java code formatting.

You can install the pre-commit hooks with make install_test precommit_install.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review is ineligible. To be eligible to request a review, you need a paid Copilot license, or your organization must enable Copilot code review.

@github-actions
Copy link
Copy Markdown
Contributor

The Java checkstyle failed.

Please run mvn spotless:apply in the root of your repository and commit the changes to this PR.
You can also use pre-commit to automate the Java code formatting.

You can install the pre-commit hooks with make install_test precommit_install.

@gitar-bot
Copy link
Copy Markdown

gitar-bot Bot commented Apr 28, 2026

Code Review ⚠️ Changes requested 12 resolved / 15 findings

Data contracts test execution adds comprehensive unit test coverage but leaves three open findings unresolved: potential NPE in certification tag filtering when tagFQN is null, MWAA query string construction bypassing query params, and inefficient DB queries on every entity certification check.

⚠️ Bug: MWAA list_dag_runs builds query string in path, bypassing query param

In MWAAClient.list_dag_runs, query parameters (order_by, limit) are appended directly to the URL path string instead of using the query parameter like other methods (list_dags, _paginate). The MWAA invoke_rest_api method accepts a QueryParameters dict, and mixing inline query strings with QueryParameters may cause issues depending on the AWS SDK implementation. This inconsistency could lead to parameters being ignored or double-encoded.

Suggested fix
def list_dag_runs(self, dag_id: str, limit: int = 10) -> Dict:
    query = {"order_by": "-start_date", "limit": str(limit)}
    return self._invoke_rest_api(
        f"/dags/{quote(dag_id, safe='')}/dagRuns",
        query=query,
    )
💡 Edge Case: Potential NPE in certification tag filtering if tagFQN is null

In getTagsForEntity and updateTags, the code calls FullyQualifiedName.getParentFQN(tag.getTagFQN()) without null-checking tag.getTagFQN(). While tagFQN is marked required in the schema, corrupt or legacy database records could have null values, causing getParentFQN to throw a NullPointerException via CharStreams.fromString(null). The same pattern appears in the updateTags method at lines 6761/6763.

Suggested fix
tags.removeIf(
    tag -> tag.getTagFQN() != null
        && certClassification.equals(
            FullyQualifiedName.getParentFQN(tag.getTagFQN())));
💡 Performance: applyCertification queries DB for existing cert on every entity create

The applyCertification method (called from createNewEntity) queries the database via getCertification(entity) to check for existing certification tags before inserting. During entity creation, this existing certification will always be null since the entity was just created and no cert tags exist yet. This is a wasted DB query per entity creation when certification is set. In applyCertificationBatch, the code correctly does a bulk delete + insert without per-entity existence checks.

Suggested fix
For the single-entity create path, consider skipping
the existence check (line 4515-4523) when called from
`createNewEntity` since no certification tag can exist yet.
Alternatively, keep the check for correctness in PUT/update
paths but document the intent.
✅ 12 resolved
Bug: Postgres jsonb_set: create_missing=false and value stored as string

📄 openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/CollectionDAO.java:7028
The Postgres SQL for updateTestCaseDataContract has two bugs:

  1. jsonb_set(json, '{dataContract}', ..., false) — the false (create_missing) means the dataContract key will NOT be created if it doesn't already exist. Since this method is called to add a new dataContract reference to test cases that don't have one yet, this will silently be a no-op for all Postgres deployments.

  2. to_jsonb(:dataContractJson::text) wraps the JSON string as a JSON string scalar ("<escaped-json>") rather than parsing it as a JSON object. The MySQL version correctly uses CAST(:dataContractJson AS JSON). The Postgres equivalent should cast to jsonb directly.

This means the migration and all runtime updates of dataContract references on test cases will silently fail on Postgres.

Bug: Wrong OR in testsToRemove filter removes valid tests

📄 openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/DataContractRepository.java:919
In updateTestSuiteTests, the filter for tests to remove from the test suite uses:

currentTests.stream()
    .filter(testId -> !testCaseRefs.contains(testId) || !testsToAdd.contains(testId))

testsToAdd only contains tests WITHOUT results. So any test that HAS results (and is therefore not in testsToAdd) will satisfy !testsToAdd.contains(testId) == true, causing it to be removed from the test suite even if it's still a valid quality expectation.

The || (OR) should likely just be removal of tests no longer in quality expectations: !testCaseRefs.contains(testId). Or if the intent is to also remove tests that already have results: !testCaseRefs.contains(testId) || testCaseRefs.contains(testId) && !testsToAdd.contains(testId) which simplifies to just !testsToAdd.contains(testId) — but the current double-negative with OR is overly broad.

Bug: addTestCasesToLogicalTestSuite may add duplicates

📄 openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/DataContractRepository.java:912-913
In the old code, newTestCases was filtered to exclude tests already in currentTests before calling addTestCasesToLogicalTestSuite. The new code at line 913 passes testsToAdd directly without checking against currentTests. If a test without results is already in the test suite (e.g., added previously but not yet executed), it will be added again, potentially causing duplicate entries or constraint violations.

Quality: Null check after findEntityById is dead code

📄 openmetadata-service/src/main/java/org/openmetadata/service/migration/utils/v1130/MigrationUtil.java:104-109
At line 106, if (testCase == null) is dead code because findEntityById throws EntityNotFoundException rather than returning null. The migration still works correctly because the exception is caught by the enclosing try/catch(Exception) block at line 132, but this is misleading — the log message at line 107 ("Test case not found") will never execute, and the actual skip reason is silently logged as a generic warning at line 134.

Consider catching EntityNotFoundException explicitly so the "not found" case has clear, intentional handling.

Edge Case: getTestsWithResults only catches EntityNotFoundException

📄 openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/DataContractRepository.java:1236
In getTestsWithResults, the stream's map lambda only catches EntityNotFoundException. Any other exception from testCaseRepository.get() (e.g., a transient DB error or JSON deserialization issue) will propagate and abort the entire stream, causing the whole postCreate/postUpdate to fail. Consider catching a broader exception type and logging it, consistent with how errors are handled in the other new methods.

...and 7 more resolved from earlier reviews

🤖 Prompt for agents
Code Review: Data contracts test execution adds comprehensive unit test coverage but leaves three open findings unresolved: potential NPE in certification tag filtering when tagFQN is null, MWAA query string construction bypassing query params, and inefficient DB queries on every entity certification check.

1. 💡 Edge Case: Potential NPE in certification tag filtering if tagFQN is null

   In `getTagsForEntity` and `updateTags`, the code calls `FullyQualifiedName.getParentFQN(tag.getTagFQN())` without null-checking `tag.getTagFQN()`. While `tagFQN` is marked required in the schema, corrupt or legacy database records could have null values, causing `getParentFQN` to throw a NullPointerException via `CharStreams.fromString(null)`. The same pattern appears in the `updateTags` method at lines 6761/6763.

   Suggested fix:
   tags.removeIf(
       tag -> tag.getTagFQN() != null
           && certClassification.equals(
               FullyQualifiedName.getParentFQN(tag.getTagFQN())));

2. ⚠️ Bug: MWAA list_dag_runs builds query string in path, bypassing query param

   In `MWAAClient.list_dag_runs`, query parameters (`order_by`, `limit`) are appended directly to the URL path string instead of using the `query` parameter like other methods (`list_dags`, `_paginate`). The MWAA `invoke_rest_api` method accepts a `QueryParameters` dict, and mixing inline query strings with `QueryParameters` may cause issues depending on the AWS SDK implementation. This inconsistency could lead to parameters being ignored or double-encoded.

   Suggested fix:
   def list_dag_runs(self, dag_id: str, limit: int = 10) -> Dict:
       query = {"order_by": "-start_date", "limit": str(limit)}
       return self._invoke_rest_api(
           f"/dags/{quote(dag_id, safe='')}/dagRuns",
           query=query,
       )

3. 💡 Performance: applyCertification queries DB for existing cert on every entity create

   The `applyCertification` method (called from `createNewEntity`) queries the database via `getCertification(entity)` to check for existing certification tags before inserting. During entity creation, this existing certification will always be null since the entity was just created and no cert tags exist yet. This is a wasted DB query per entity creation when certification is set. In `applyCertificationBatch`, the code correctly does a bulk delete + insert without per-entity existence checks.

   Suggested fix:
   For the single-entity create path, consider skipping
   the existence check (line 4515-4523) when called from
   `createNewEntity` since no certification tag can exist yet.
   Alternatively, keep the check for correctness in PUT/update
   paths but document the intent.

Options

Display: compact → Showing less information.

Comment with these commands to change:

Compact
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

@github-actions
Copy link
Copy Markdown
Contributor

The Java checkstyle failed.

Please run mvn spotless:apply in the root of your repository and commit the changes to this PR.
You can also use pre-commit to automate the Java code formatting.

You can install the pre-commit hooks with make install_test precommit_install.

@sonarqubecloud
Copy link
Copy Markdown

@sonarqubecloud
Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Ingestion safe to test Add this label to run secure Github workflows on PRs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants