Skip to content

fix: skip enrollment-notes preheat query for WITHOUT_REGISTRATION synthetic enrollments - #25006

Draft
jason-p-pickering wants to merge 3 commits into
2.41from
fix/2.41-enrollment-notes-preheat
Draft

fix: skip enrollment-notes preheat query for WITHOUT_REGISTRATION synthetic enrollments#25006
jason-p-pickering wants to merge 3 commits into
2.41from
fix/2.41-enrollment-notes-preheat

Conversation

@jason-p-pickering

Copy link
Copy Markdown
Contributor

Summary

  • EnrollmentSupplier preheats a synthetic Enrollment for every WITHOUT_REGISTRATION program an import touches. It used the shared preheat EnrollmentMapper, whose @Mapping(target = "notes") forces Hibernate to lazy-load enrollment_notes/note for every such enrollment — even though this synthetic entity is only ever used as an FK reference for events (event.setEnrollment(...)) and is never converted or persisted, so its notes are never read. On a single-event import this fires one dead query per WITHOUT_REGISTRATION program, every time.
  • Added EnrollmentMapper.mapWithoutNotes(Enrollment) — same mapping as map() minus notes — and switched EnrollmentSupplier to use it.
  • EnrollmentStrategy (which preheats real enrollments referenced by UID in a tracker payload) keeps using the notes-inclusive map(): AbstractTrackerPersister calls entityManager.merge(...) on update, and Enrollment.notes is cascade="all-delete-orphan", so skipping the eager load there would silently delete every existing note on every enrollment update. The fix is scoped to EnrollmentSupplier only.
  • Confirmed the same @Mapping(target = "notes") exists on master too, so this is not a 2.41-only regression, just a 2.41-only fix for now (consistent with prior single-event preheat fixes on this branch).

Found via a Glowroot trace on a production single-event import, live-validated: smoke-tested a built dhis.war against the target instance and confirmed the query disappears from the trace.

Test plan

  • New unit test EnrollmentSupplierTest.verifySupplierDoesNotAccessNotesOfEnrollmentWithoutRegistration spies on a real Enrollment and asserts getNotes() is never called during preheat; confirmed it fails against pre-fix code (Mockito pointed at EnrollmentMapperImpl.map()), passes post-fix.
  • Full preheat/converter/bundle package regression sweep in dhis-service-tracker: 129 tests, 0 failures.
  • Built dhis.war from this branch merged into a downstream integration branch and smoke-tested against a production-like single-event import; confirmed the enrollment_notes JOIN note query no longer appears in the trace.

…thetic enrollments

EnrollmentSupplier preheats a synthetic Enrollment for every WITHOUT_REGISTRATION
program an import touches, using the shared preheat EnrollmentMapper which mapped
`notes`. That mapping forces Hibernate to lazy-load enrollment_notes/note for every
such enrollment, even though this synthetic entity is only ever used as an FK
reference for events and is never converted or persisted, so its notes are never
read. Give it a notes-free mapping variant instead. EnrollmentStrategy (which
preheats real enrollments referenced by UID) keeps using the notes-inclusive
mapping, since merge() there relies on it to avoid orphan-deleting existing notes.
@jason-p-pickering
jason-p-pickering requested a review from a team September 1, 2026 06:25
@jason-p-pickering
jason-p-pickering marked this pull request as draft September 1, 2026 06:26
@sonarqubecloud

sonarqubecloud Bot commented Sep 4, 2026

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
1 New issue
1 New Code Smells (required ≤ 0)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

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.

1 participant