Skip to content

Fixes #31568: read logical-suite revisions back through the DAO that wrote them - #31569

Merged
harshach merged 2 commits into
mainfrom
harshach/fix-logical-suite-revision-race
Aug 15, 2026
Merged

Fixes #31568: read logical-suite revisions back through the DAO that wrote them#31569
harshach merged 2 commits into
mainfrom
harshach/fix-logical-suite-revision-race

Conversation

@harshach

Copy link
Copy Markdown
Collaborator

Describe your changes:

Fixes #31568

TestCaseRepository.prepareLogicalSuiteRelationshipChange writes the test case and test suite revision rows through the repository's own daoCollection, then reads them back through the static helpers, which resolve Entity.getCollectionDAO() instead.

That global is mutable: OpenMetadataApplication.run() and the integration-test TestSuiteBootstrap each set it to an on-demand DAO over their own Jdbi, while a repository captures daoCollection once at construction (EntityRepository.java:666). The two can therefore name different instances, and the write lands on one connection while the read-back runs on another. MySQL pins a REPEATABLE READ snapshot at the transaction's first read, so it cannot see the other connection's later commit at all and the rows just written come back missing. Postgres re-snapshots per statement — which is precisely why only the MySQL lanes ever failed.

I gave both helpers an overload that takes the caller's DAO and used it from the write path, so a read-back always shares the writer's connection. The four call sites that read outside a transaction — ReindexingUtil, SearchIndexRetryWorker, TestCaseIndex and TestSuiteIndex — keep resolving the global, which is correct for them.

I also put the counts and the suite id into the two messages. As written they asserted a cause that was never checked ("failed to persist"), which points an investigation at the persistence layer rather than at which connection is being read.

Type of change:

  • Bug fix

High-level design:

N/A — small change.

Tests:

Use cases covered

  • Adding test cases to a logical test suite succeeds on MySQL when the mutable Entity.getCollectionDAO() global does not match the repository's captured daoCollection
  • Reindexing and search-index builders, which read revisions outside any transaction, keep resolving the global DAO

Unit tests

  • Added readsRevisionsThroughTheCallersDaoRatherThanTheGlobalOne to both TestCaseRepositoryTest and TestSuiteRepositoryTest. Each points the global at a different DAO and asserts the revisions still come from the caller's DAO and that the global is never touched — so a revert to the global fails both the value assertion and verifyNoInteractions.

Local run — mvn -pl openmetadata-service test -Dtest='*TestCase*Test,*TestSuite*Test,*DataQuality*Test':

Tests run: 47, Failures: 0, Errors: 0, Skipped: 0
BUILD SUCCESS

That set includes TestCaseIndexTest and TestSuiteIndexTest, which exercise the unchanged single-argument overload.

Integration tests

The existing TestCaseResourceIT and TestSuiteResourceIT logical-suite tests are the real regression coverage — they are the ones failing today on the MySQL lanes. No new IT is added, because reproducing the divergence deterministically needs a second Jdbi mid-startup, which the unit tests model directly.

UI Screen Recording:

N/A — no UI change.

prepareLogicalSuiteRelationshipChange writes the test case and test suite
revision rows through the repository's own daoCollection, then reads them back
through the static helpers, which resolve Entity.getCollectionDAO() instead.

That global is mutable: OpenMetadataApplication and the integration-test
bootstrap each set it to an on-demand DAO over their own Jdbi, while a
repository captures daoCollection once at construction. The two can therefore
name different instances, and the write lands on one connection while the
read-back runs on another. MySQL pins a REPEATABLE READ snapshot at the
transaction's first read, so it cannot see the other connection's later commit
at all and the rows just written come back missing -- reported as
"Failed to persist every test suite relationship revision" and
"Failed to persist the test suite tests revision". Postgres re-snapshots per
statement, which is why only the MySQL lanes ever failed.

Give both helpers an overload that takes the caller's DAO and use it from the
write path, so the read-back always shares the writer's connection. The four
call sites that read outside a transaction -- reindexing, the retry worker and
the two index builders -- keep resolving the global.

Also report the counts and the suite id in the two messages: as written they
named a cause that was never checked, which sent the investigation at the
persistence layer rather than at which connection was being read.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings August 15, 2026 04:51
@harshach
harshach requested a review from a team as a code owner August 15, 2026 04:51
@github-actions

github-actions Bot commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

✅ PR checks passed

The linked issue has a description and all required Shipping project fields set. Thanks!

@github-actions github-actions Bot added backend safe to test Add this label to run secure Github workflows on PRs labels Aug 15, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes intermittent MySQL failures when adding test cases to a logical test suite by ensuring “write then read-back” of revision rows happens through the same CollectionDAO (and therefore the same Jdbi/connection scope) that performed the write, rather than via the mutable global Entity.getCollectionDAO().

Changes:

  • Added CollectionDAO-accepting overloads for revision read helpers in TestCaseRepository and TestSuiteRepository, and updated the transactional write-path to use them.
  • Improved failure messages to report what was actually observed (counts + suite id) instead of asserting an unverified “failed to persist” cause.
  • Added unit tests that pin Entity.getCollectionDAO() to a different DAO and assert the caller DAO is used (and the global DAO is never touched).

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.

File Description
openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TestCaseRepository.java Uses caller daoCollection for revision read-back and improves related error messages; adds DAO overload for revision reads.
openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TestSuiteRepository.java Adds DAO overload for reading tests relationship revisions while keeping the existing global-resolving overload for non-transactional callers.
openmetadata-service/src/test/java/org/openmetadata/service/jdbi3/TestCaseRepositoryTest.java Adds a unit test asserting revision reads use the caller DAO and do not interact with the global DAO.
openmetadata-service/src/test/java/org/openmetadata/service/jdbi3/TestSuiteRepositoryTest.java Adds a unit test asserting revision reads use the caller DAO and do not interact with the global DAO.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@github-actions

github-actions Bot commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

✅ Playwright Results — workflow succeeded

Validated commit 06845dd9a3e3b54c5963b05a79f1a7c6bbde8bc2 in Playwright run 31868916304, attempt 1.

✅ 771 passed · ❌ 0 failed · 🟡 1 flaky · ⏭️ 0 skipped · 🧰 0 lifecycle flaky

Performance

Blocking targets: ✅ met · Optimization targets: 🟡 in progress

Shard-job maxima below are not the full workflow wall time; the linked run includes build, fixture, planning, and reporting.

🕒 Full workflow signal wall (to summary) 48m 5s

⏱️ Max setup 3m 0s · max shard execution 20m 7s · max shard-job elapsed before upload 23m 53s · reporting 5s

🌐 214.30 requests/attempt · 2.64 app boots/UI scenario · 13.01% common-shard skew

Optimization targets still in progress:

  • Browser traffic was 214.3 requests per attempt (convergence target: fewer than 200).
  • Application boot ratio was 2.64 per UI scenario (2158 boots / 817 scenarios; convergence target: at most 1).
Shard Passed Failed Flaky Skipped Lifecycle failed Lifecycle flaky
🟡 Shard chromium-01 145 0 1 0 0 0
✅ Shard chromium-02 143 0 0 0 0 0
✅ Shard chromium-03 138 0 0 0 0 0
✅ Shard chromium-04 134 0 0 0 0 0
✅ Shard data-asset-rules-01 61 0 0 0 0 0
✅ Shard domain-isolation-01 14 0 0 0 0 0
✅ Shard global-state-01 34 0 0 0 0 0
✅ Shard import-export-01 26 0 0 0 0 0
✅ Shard ingestion-01 32 0 0 0 0 0
✅ Shard reindex-01 5 0 0 0 0 0
✅ Shard search-01 10 0 0 0 0 0
✅ Shard search-rbac-01 29 0 0 0 0 0
🟡 1 flaky test(s) (passed on retry)
  • Pages/Entity.spec.tsTier Add, Update and Remove (shard chromium-01, 1 retry)

📦 Download artifacts

How to debug locally
# Download playwright-test-results-<shard> artifact and unzip
npx playwright show-trace path/to/trace.zip    # view trace

Copilot AI review requested due to automatic review settings August 15, 2026 06:13

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 4 out of 4 changed files in this pull request and generated no new comments.

@harshach
harshach added this pull request to the merge queue Aug 15, 2026
Merged via the queue into main with commit 3588eb3 Aug 15, 2026
111 checks passed
@harshach
harshach deleted the harshach/fix-logical-suite-revision-race branch August 15, 2026 07:55
@github-actions

Copy link
Copy Markdown
Contributor

Failed to cherry-pick changes to the 1.13 branch.
Please cherry-pick the changes manually.
You can find more details here.

@github-actions

Copy link
Copy Markdown
Contributor

Changes have been cherry-picked to the 2.0 branch.

github-actions Bot pushed a commit that referenced this pull request Aug 15, 2026
…1569)

prepareLogicalSuiteRelationshipChange writes the test case and test suite
revision rows through the repository's own daoCollection, then reads them back
through the static helpers, which resolve Entity.getCollectionDAO() instead.

That global is mutable: OpenMetadataApplication and the integration-test
bootstrap each set it to an on-demand DAO over their own Jdbi, while a
repository captures daoCollection once at construction. The two can therefore
name different instances, and the write lands on one connection while the
read-back runs on another. MySQL pins a REPEATABLE READ snapshot at the
transaction's first read, so it cannot see the other connection's later commit
at all and the rows just written come back missing -- reported as
"Failed to persist every test suite relationship revision" and
"Failed to persist the test suite tests revision". Postgres re-snapshots per
statement, which is why only the MySQL lanes ever failed.

Give both helpers an overload that takes the caller's DAO and use it from the
write path, so the read-back always shares the writer's connection. The four
call sites that read outside a transaction -- reindexing, the retry worker and
the two index builders -- keep resolving the global.

Also report the counts and the suite id in the two messages: as written they
named a cause that was never checked, which sent the investigation at the
persistence layer rather than at which connection was being read.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
(cherry picked from commit 3588eb3)
@gitar-bot

gitar-bot Bot commented Aug 15, 2026

Copy link
Copy Markdown
Code Review ✅ Approved

Updates logical-suite revision read-backs to use the DAO that wrote them instead of the global collection DAO, preventing transaction snapshot visibility issues on MySQL. No issues found.

Options

Display: compact → Showing less information.

Comment with these commands to change the behavior for this request:

Compact
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Powered by Gitar — free for open source

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

Labels

backend safe to test Add this label to run secure Github workflows on PRs To release Will cherry-pick this PR into the release branch

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Logical test-suite adds intermittently 500 on MySQL: revision rows read back on a different connection

3 participants