Skip to content

Commit

Permalink
fix: Run full update for cont analytics table job if first time [DHIS…
Browse files Browse the repository at this point in the history
…2-16986] (#18505)
  • Loading branch information
maikelarabori authored Sep 3, 2024
1 parent e699c4e commit 4f5e58d
Show file tree
Hide file tree
Showing 3 changed files with 132 additions and 20 deletions.
24 changes: 24 additions & 0 deletions dhis-2/dhis-api/src/main/java/org/hisp/dhis/util/DateUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,16 @@ public static String toLongDateWithMillis(Date date) {
return date != null ? LONG_DATE_FORMAT_WITH_MILLIS.print(new DateTime(date)) : null;
}

/**
* Formats a Date to the format yyyy-MM-dd HH:mm:ss.
*
* @param date the Date to parse.
* @return A formatted date string.
*/
public static String toLongDate(Date date) {
return date != null ? LONG_DATE_FORMAT.print(new DateTime(date)) : null;
}

/**
* Formats a Date to the format yyyy-MM-dd HH:mm:ss.
*
Expand Down Expand Up @@ -258,6 +268,20 @@ public static Date minusOneDay(Date date) {
return new Date(date.getTime() - MS_PER_DAY);
}

/**
* Creates a {@link Date} representing the given year, month and day.
*
* @param year the year.
* @param month the month, from 1.
* @param dayOfMonth the day of the month, from 1.
* @param hourOfDay the hour of day, from 0.
* @param minuteOfHour the minute of hour, from 0.
* @return a {@link Date}.
*/
public static Date getDate(int year, int month, int dayOfMonth, int hourOfDay, int minuteOfHour) {
return new DateTime(year, month, dayOfMonth, hourOfDay, minuteOfHour).toDate();
}

/**
* Formats a Date according to the HTTP specification standard date format.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,14 @@
*/
package org.hisp.dhis.analytics.table.scheduling;

import static com.google.common.base.MoreObjects.firstNonNull;
import static org.hisp.dhis.util.DateUtils.getLongDateString;
import static org.hisp.dhis.util.DateUtils.toLongDate;

import com.google.common.base.Preconditions;
import java.util.Date;
import java.util.Objects;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.hisp.dhis.analytics.AnalyticsTableGenerator;
import org.hisp.dhis.analytics.AnalyticsTableUpdateParams;
import org.hisp.dhis.scheduling.Job;
Expand Down Expand Up @@ -79,24 +80,14 @@ public void execute(JobConfiguration jobConfiguration, JobProgress progress) {
ContinuousAnalyticsJobParameters parameters =
(ContinuousAnalyticsJobParameters) jobConfiguration.getJobParameters();

Integer fullUpdateHourOfDay =
ObjectUtils.firstNonNull(parameters.getFullUpdateHourOfDay(), DEFAULT_HOUR_OF_DAY);

Date now = new Date();
Date defaultNextFullUpdate = DateUtils.getNextDate(fullUpdateHourOfDay, now);
Date nextFullUpdate =
systemSettingManager.getSystemSetting(
SettingKey.NEXT_ANALYTICS_TABLE_UPDATE, defaultNextFullUpdate);
final int fullUpdateHourOfDay =
firstNonNull(parameters.getFullUpdateHourOfDay(), DEFAULT_HOUR_OF_DAY);
final Date startTime = new Date();

log.info(
"Starting continuous analytics table update, current time: '{}', default next full update: '{}', next full update: '{}'",
getLongDateString(now),
getLongDateString(defaultNextFullUpdate),
getLongDateString(nextFullUpdate));
"Starting continuous analytics table update, current time: '{}'", toLongDate(startTime));

Preconditions.checkNotNull(nextFullUpdate);

if (now.after(nextFullUpdate)) {
if (runFullUpdate(startTime)) {
log.info("Performing full analytics table update");

AnalyticsTableUpdateParams params =
Expand All @@ -105,13 +96,13 @@ public void execute(JobConfiguration jobConfiguration, JobProgress progress) {
.withSkipResourceTables(false)
.withSkipTableTypes(parameters.getSkipTableTypes())
.withJobId(jobConfiguration)
.withStartTime(now)
.withStartTime(startTime)
.build();

try {
analyticsTableGenerator.generateTables(params, progress);
} finally {
Date nextUpdate = DateUtils.getNextDate(fullUpdateHourOfDay, now);
Date nextUpdate = DateUtils.getNextDate(fullUpdateHourOfDay, startTime);
systemSettingManager.saveSystemSetting(SettingKey.NEXT_ANALYTICS_TABLE_UPDATE, nextUpdate);
log.info("Next full analytics table update: '{}'", getLongDateString(nextUpdate));
}
Expand All @@ -124,10 +115,28 @@ public void execute(JobConfiguration jobConfiguration, JobProgress progress) {
.withSkipResourceTables(true)
.withSkipTableTypes(parameters.getSkipTableTypes())
.withJobId(jobConfiguration)
.withStartTime(now)
.withStartTime(startTime)
.build();

analyticsTableGenerator.generateTables(params, progress);
}
}

/**
* Indicates whether a full table update should be run. If the next full update time is not set,
* it indicates that a full update has never been run for this job, and a full update should be
* run immediately. Otherwise, a full update is run if the job start time argument is after the
* next full update time.
*
* @param startTime the job start time.
* @return true if a full table update should be run.
*/
boolean runFullUpdate(Date startTime) {
Objects.requireNonNull(startTime);

Date nextFullUpdate =
systemSettingManager.getSystemSetting(SettingKey.NEXT_ANALYTICS_TABLE_UPDATE, Date.class);

return nextFullUpdate == null || startTime.after(nextFullUpdate);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* Copyright (c) 2004-2024, University of Oslo
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* Neither the name of the HISP project nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.hisp.dhis.analytics.table.scheduling;

import static org.hisp.dhis.setting.SettingKey.NEXT_ANALYTICS_TABLE_UPDATE;
import static org.hisp.dhis.util.DateUtils.getDate;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.when;

import java.util.Date;
import org.hisp.dhis.analytics.AnalyticsTableGenerator;
import org.hisp.dhis.setting.SystemSettingManager;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
class ContinuousAnalyticsTableJobTest {
@Mock private AnalyticsTableGenerator analyticsTableGenerator;

@Mock private SystemSettingManager systemSettingManager;

private ContinuousAnalyticsTableJob job;

private final Date dateA = getDate(2024, 1, 4, 23, 0);
private final Date dateB = getDate(2024, 1, 5, 2, 0);
private final Date dateC = getDate(2024, 1, 5, 8, 0);

@BeforeEach
public void beforeEach() {
job = new ContinuousAnalyticsTableJob(analyticsTableGenerator, systemSettingManager);
}

@Test
void testRunFullUpdate() {
when(systemSettingManager.getSystemSetting(NEXT_ANALYTICS_TABLE_UPDATE, Date.class))
.thenReturn(dateB);

assertFalse(job.runFullUpdate(dateA));
assertTrue(job.runFullUpdate(dateC));
}

@Test
void testRunFullUpdateNullNextUpdate() {
when(systemSettingManager.getSystemSetting(NEXT_ANALYTICS_TABLE_UPDATE, Date.class))
.thenReturn(null);

assertTrue(job.runFullUpdate(dateA));
assertTrue(job.runFullUpdate(dateC));
}
}

0 comments on commit 4f5e58d

Please sign in to comment.