Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,7 @@ private void updateDataValue(String event, String dataElementUid, String newValu
TrackerImportParams.builder().build(),
TrackerObjects.builder().events(List.of(e)).build()));
});
manager.clear();
}

private void updateEventDates(UID event, Instant newDate) throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,7 @@ private void updateDataValue(String event, String dataElementUid, String newValu
TrackerImportParams.builder().build(),
TrackerObjects.builder().events(List.of(e)).build()));
});
manager.clear();
}

private void updateEventDates(UID event, Instant newDate) throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;
import org.hisp.dhis.dbms.DbmsManager;
import org.hisp.dhis.feedback.ForbiddenException;
import org.hisp.dhis.feedback.NotFoundException;
import org.hisp.dhis.program.EnrollmentStatus;
Expand Down Expand Up @@ -76,6 +77,7 @@ class EnrollmentImportTest extends PostgresIntegrationTestBase {
@Autowired private NamedParameterJdbcTemplate jdbcTemplate;

private User importUser;
@Autowired private DbmsManager dbmsManager;

@BeforeAll
void setUp() throws IOException {
Expand All @@ -88,13 +90,15 @@ void setUp() throws IOException {
@ParameterizedTest
@MethodSource("statuses")
void shouldCorrectlyPopulateCompletedDataWhenCreatingAnEnrollment(EnrollmentStatus status)
throws IOException, ForbiddenException, NotFoundException {
throws IOException, NotFoundException {
TrackerImportParams params = TrackerImportParams.builder().build();
TrackerObjects trackerObjects = testSetup.fromJson("tracker/te_enrollment_event.json");
trackerObjects.getEnrollments().get(0).setStatus(status);

ImportReport importReport = trackerImportService.importTracker(params, trackerObjects);

dbmsManager.clearSession();

assertNoErrors(importReport);

Enrollment enrollment =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ void testEventDataValueUpdate() throws IOException {
params.setImportStrategy(TrackerImportStrategy.CREATE_AND_UPDATE);
testSetup.importTrackerData("tracker/event_with_updated_data_values.json", params);

manager.clear();

List<TrackerEvent> updatedEvents = manager.getAll(TrackerEvent.class);
assertEquals(1, updatedEvents.size());
TrackerEvent updatedEvent = manager.get(TrackerEvent.class, updatedEvents.get(0).getUid());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ void shouldUpdateTrackedEntityWhenTrackedEntityIsUpdated() throws IOException {
TrackerImportParams params =
TrackerImportParams.builder().importStrategy(TrackerImportStrategy.UPDATE).build();
testSetup.importTrackerData("tracker/one_te.json", params);

clearSession();
Date lastUpdateAfter = getTrackedEntity().getLastUpdated();

assertTrue(
Expand Down Expand Up @@ -753,5 +753,6 @@ private void updateAttributeValue(String attribute, String attributeValue) throw
ImportReport report = trackerImportService.importTracker(params, trackerObjects);

assertNoErrors(report);
dbmsManager.clearSession();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ void testUpdateEnrollment() throws IOException {
params.setImportStrategy(TrackerImportStrategy.CREATE_AND_UPDATE);
ImportReport updatedReport = trackerImportService.importTracker(params, trackerObjects);
manager.flush();
manager.clear();
assertNoErrors(updatedReport);
assertEquals(1, updatedReport.getStats().getUpdated());
enrollments = manager.getAll(Enrollment.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,8 @@ void shouldImportEventAndCorrectlyAssignPreviousEventDataValue(

ImportReport importReport = trackerImportService.importTracker(params, trackerObjects);

manager.clear();

List<String> firstEventDataValues = getValueForAssignedDataElement(firstEventUid);
List<String> secondEventDataValues = getValueForAssignedDataElement(secondEventUid);
List<String> thirdEventDataValues = getValueForAssignedDataElement(thirdEventUid);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,7 @@ void testValidateAndAddNotesToUpdatedEvent() throws IOException {
// When -> Update the event and adds 3 more notes
ImportReport importReport =
createEvent("tracker/validations/events-with-notes-update-data.json");
manager.clear();
// Then
final TrackerEvent event = getEventFromReport(importReport);
assertThat(event.getNotes(), hasSize(6));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -383,23 +383,41 @@ void shouldGetEventChangeLogsWithSimpleFieldsFilter() {
}

private void updateDataValue(String value) {
String body = createDataValueJson(event, value);
startNewRequestSession();
JsonWebMessage importResponse =
POST("/tracker?async=false&importStrategy=UPDATE", createDataValueJson(event, value))
POST("/tracker?async=false&importStrategy=UPDATE", body)
.content(HttpStatus.OK)
.as(JsonWebMessage.class);
assertEquals(HttpStatus.OK.toString(), importResponse.getStatus());
}

private void updateScheduledAtEventField(String value) {
String body = createScheduledAtEventFieldJson(event, value);
startNewRequestSession();
JsonWebMessage importResponse =
POST(
"/tracker?async=false&importStrategy=UPDATE",
createScheduledAtEventFieldJson(event, value))
POST("/tracker?async=false&importStrategy=UPDATE", body)
.content(HttpStatus.OK)
.as(JsonWebMessage.class);
assertEquals(HttpStatus.OK.toString(), importResponse.getStatus());
}

/**
* Simulates a fresh per-request {@code EntityManager}. {@code /api/tracker/**} is excluded from
* the {@code ConditionalOpenEntityManagerInViewFilter} (OSIV is deliberately off for tracker), so
* its Hibernate session is transaction-scoped: it is opened for the import's
* {@code @Transactional} boundary and closed when that transaction completes, so each {@code
* /tracker} request starts with a fresh persistence context. These MockMvc tests otherwise share
* one thread-bound session across imports; since the tracker importer writes via JDBC (bypassing
* Hibernate), a previous import's now-stale managed entity would linger in the L1 cache and be
* returned to the next import's preheat. Flushing then clearing the session between imports
* reproduces the production per-request isolation.
*/
private void startNewRequestSession() {
dbmsManager.flushSession();
dbmsManager.clearSession();
}

private TrackedEntity trackedEntity() {
TrackedEntity te = trackedEntity(orgUnit);
manager.save(te, false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -364,23 +364,38 @@ void shouldGetEventChangeLogsWithSimpleFieldsFilter() {
}

private void updateDataValue(String value) {
String body = createDataValueJson(event, value);
startNewRequestSession();
JsonWebMessage importResponse =
POST("/tracker?async=false&importStrategy=UPDATE", createDataValueJson(event, value))
POST("/tracker?async=false&importStrategy=UPDATE", body)
.content(HttpStatus.OK)
.as(JsonWebMessage.class);
assertEquals(HttpStatus.OK.toString(), importResponse.getStatus());
}

private void updateScheduledAtEventField(String value) {
String body = createScheduledAtEventFieldJson(event, value);
startNewRequestSession();
JsonWebMessage importResponse =
POST(
"/tracker?async=false&importStrategy=UPDATE",
createScheduledAtEventFieldJson(event, value))
POST("/tracker?async=false&importStrategy=UPDATE", body)
.content(HttpStatus.OK)
.as(JsonWebMessage.class);
assertEquals(HttpStatus.OK.toString(), importResponse.getStatus());
}

/**
* Simulates a fresh per-request {@code EntityManager}. Production registers an {@code
* OpenEntityManagerInViewFilter}, so every {@code /tracker} request gets its own Hibernate
* session. These MockMvc tests otherwise share one thread-bound session across imports; since the
* tracker importer writes via JDBC (bypassing Hibernate), a previous import's now-stale managed
* entity would linger in the L1 cache and be returned to the next import's preheat. Flushing then
* clearing the session between imports reproduces the production per-request isolation.
*/
private void startNewRequestSession() {
dbmsManager.flushSession();
dbmsManager.clearSession();
}

private SingleEvent event() {
SingleEvent eventA = new SingleEvent();
eventA.setProgramStage(programStage);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -389,23 +389,41 @@ void shouldGetEventChangeLogsWithSimpleFieldsFilter() {
}

private void updateDataValue(String value) {
String body = createDataValueJson(event, value);
startNewRequestSession();
JsonWebMessage importResponse =
POST("/tracker?async=false&importStrategy=UPDATE", createDataValueJson(event, value))
POST("/tracker?async=false&importStrategy=UPDATE", body)
.content(HttpStatus.OK)
.as(JsonWebMessage.class);
assertEquals(HttpStatus.OK.toString(), importResponse.getStatus());
}

private void updateScheduledAtEventField(String value) {
String body = createScheduledAtEventFieldJson(event, value);
startNewRequestSession();
JsonWebMessage importResponse =
POST(
"/tracker?async=false&importStrategy=UPDATE",
createScheduledAtEventFieldJson(event, value))
POST("/tracker?async=false&importStrategy=UPDATE", body)
.content(HttpStatus.OK)
.as(JsonWebMessage.class);
assertEquals(HttpStatus.OK.toString(), importResponse.getStatus());
}

/**
* Simulates a fresh per-request {@code EntityManager}. {@code /api/tracker/**} is excluded from
* the {@code ConditionalOpenEntityManagerInViewFilter} (OSIV is deliberately off for tracker), so
* its Hibernate session is transaction-scoped: it is opened for the import's
* {@code @Transactional} boundary and closed when that transaction completes, so each {@code
* /tracker} request starts with a fresh persistence context. These MockMvc tests otherwise share
* one thread-bound session across imports; since the tracker importer writes via JDBC (bypassing
* Hibernate), a previous import's now-stale managed entity would linger in the L1 cache and be
* returned to the next import's preheat. Flushing then clearing the session between imports
* reproduces the production per-request isolation.
*/
private void startNewRequestSession() {
dbmsManager.flushSession();
dbmsManager.clearSession();
}

private TrackerEvent event() {
TrackerEvent eventA = new TrackerEvent();
eventA.setProgramStage(programStage);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -866,7 +866,9 @@ private TrackerEvent event(Enrollment enrollment) {
event.setProgramStage(trackerProgramStage);
event.setOrganisationUnit(enrollment.getOrganisationUnit());
event.setAttributeOptionCombo(coc);
event.setOccurredDate(new Date());
// SMS submissions encode dates with second precision, so the occurred date must not carry
// milliseconds or it won't survive the SMS encode/decode round-trip in shouldUpdateEvent().
event.setOccurredDate(DateUtils.getDate(2024, 9, 2, 10, 15));
event.setAutoFields();
manager.save(event);
return event;
Expand Down
Loading
Loading