Skip to content

fix(dao): use canonical DB-stored URN when emitting MAE events#628

Merged
mridul111998 merged 2 commits into
linkedin:masterfrom
mridul111998:research/fix-canonical-urn-in-mae
Jul 3, 2026
Merged

fix(dao): use canonical DB-stored URN when emitting MAE events#628
mridul111998 merged 2 commits into
linkedin:masterfrom
mridul111998:research/fix-canonical-urn-in-mae

Conversation

@mridul111998

@mridul111998 mridul111998 commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

:octocat: What is this change?

Use the canonical DB-stored URN (from ExtraInfo.getUrn()) when emitting MAE events in BaseLocalDAO, instead of the incoming MCE URN. This fix applies to all entity types and all indexes since it is in the core DAO layer.

👉 Why is this required?

Two HDFS clusters (WAR and Holdem) emit MCEs with different casing for the same dataset path (e.g. LixTrackingArchive vs lixTrackingArchive). Because the Hosted Search document ID is derived from the URN, two different document IDs were created → duplicate browse results in Datahub.

The root cause: addCommon() was emitting MAE with the incoming MCE URN instead of the canonical URN stored in the DB. The DB (MySQL) normalises casing via CI collation, so there is only ever one row — but two different HS documents were being created.

✅ How was this tested?

  • Added testBothCaseVariantsProduceSameCanonicalUrnInMAE in BaseLocalDAOTest using a string-keyed BurgerUrn to simulate two MCEs with different-case URNs arriving for the same entity. Verifies that both MAEs are emitted with the canonical (DB-stored) URN and the upper-case URN never appears.
  • Updated makeAspectEntry() test helper in BaseLocalDAOTest and BaseLocalDAOAspectVersionTest to require an explicit @Nullable Urn parameter, mirroring production behaviour where ExtraInfo always carries the stored URN for existing entities. This eliminated RequiredFieldNotPresentException failures in existing tests.
  • Consolidated duplicate makeAspectEntry helper into a single static method in BaseLocalDAOTest, shared via static import.
  • Full dao-api test suite passes (244 tests).

@mridul111998 mridul111998 force-pushed the research/fix-canonical-urn-in-mae branch 5 times, most recently from f67d963 to 0c75f43 Compare July 3, 2026 07:51
When two MCEs arrive with different-case URNs for the same entity
(e.g. lixTrackingArchive vs LixTrackingArchive), MySQL's CI collation
stores only one row, but the MAE was emitted with the incoming MCE URN.
This caused duplicate Elasticsearch documents (one per case variant)
leading to duplicate browse results in Datahub.

Fix: extract the canonical URN from ExtraInfo.getUrn() (the URN as
stored in the DB row) before shouldUpdateAspect(), so both the no-op
early-return path and the update path carry the canonical URN.
Thread it through AddResult into unwrapAddResult() (dropping the now-
redundant 'urn' param) where it is used for all producer/hook calls.
For new entities with no existing DB row, falls back to incoming URN.

Also fixes the same issue in the batch path (addManyBatchInternal).

Test: testBothCaseVariantsProduceSameCanonicalUrnInMAE uses BurgerUrn
(string-keyed) to simulate two genuinely different-case URN variants
and verifies both MAE calls use the canonical DB-stored URN.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@mridul111998 mridul111998 force-pushed the research/fix-canonical-urn-in-mae branch from d60c573 to d599c9d Compare July 3, 2026 08:23

@jphui jphui 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.

🚢 awesome fix

// newValue can in theory be NULL outside of deletion operations, we need to check for that here.
if (_aspectPostUpdateHooksMap.containsKey(aspectClass) && !isDeletion) {
_aspectPostUpdateHooksMap.get(aspectClass).forEach(hook -> hook.accept(urn, newValue));
_aspectPostUpdateHooksMap.get(aspectClass).forEach(hook -> hook.accept(maeUrn, newValue));

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.

IIUC this is the core change, rather than use the urn from the payload, use the urn from the DB

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

yes correct, and the main this is how we are passing this urn from all the places without adding a new extra DB call

@yangyangv2 yangyangv2 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.

Look good to me, thanks for making the fix!

Please fix the build failure and update the comments, then ship-it

Expand one-liner method bodies to multi-line and remove redundant
same-package imports (AspectWithExtraInfo, ListResult) to satisfy
checkstyle rules.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@mridul111998 mridul111998 merged commit fa00325 into linkedin:master Jul 3, 2026
1 of 2 checks passed
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.

3 participants