Skip to content

Commit

Permalink
Merge branch 'main' into dependabot/npm_and_yarn/frontend/ejs-3.1.10
Browse files Browse the repository at this point in the history
  • Loading branch information
guzhongren authored May 12, 2024
2 parents fc3bea2 + fe9f64c commit 03d6e82
Show file tree
Hide file tree
Showing 27 changed files with 792 additions and 134 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ public class AsyncMetricsDataHandler extends AsyncDataBaseHandler {

private static final String SLASH = "/";

private final Object readWriteLock = new Object();

public void putMetricsDataCompleted(String timeStamp, MetricsDataCompleted metricsDataCompleted) {
try {
acquireLock(METRICS_DATA_COMPLETED, timeStamp);
Expand All @@ -46,12 +48,13 @@ public void deleteExpireMetricsDataCompletedFile(long currentTimeStamp, File dir
deleteExpireFileByType(METRICS_DATA_COMPLETED, currentTimeStamp, directory);
}

@Synchronized
@Synchronized("readWriteLock")
public void updateMetricsDataCompletedInHandler(String metricDataFileId, MetricType metricType,
boolean isCreateCsvSuccess) {
MetricsDataCompleted previousMetricsCompleted = getMetricsDataCompleted(metricDataFileId);
if (previousMetricsCompleted == null) {
log.error(GENERATE_REPORT_ERROR);
String filename = OUTPUT_FILE_PATH + METRICS_DATA_COMPLETED.getPath() + metricDataFileId;
log.error(GENERATE_REPORT_ERROR + "; filename: " + filename);
throw new GenerateReportException(GENERATE_REPORT_ERROR);
}
if (isCreateCsvSuccess) {
Expand All @@ -66,10 +69,12 @@ public void updateMetricsDataCompletedInHandler(String metricDataFileId, MetricT
putMetricsDataCompleted(metricDataFileId, previousMetricsCompleted);
}

@Synchronized("readWriteLock")
public void updateOverallMetricsCompletedInHandler(String metricDataFileId) {
MetricsDataCompleted previousMetricsCompleted = getMetricsDataCompleted(metricDataFileId);
if (previousMetricsCompleted == null) {
log.error(GENERATE_REPORT_ERROR);
String filename = OUTPUT_FILE_PATH + METRICS_DATA_COMPLETED.getPath() + metricDataFileId;
log.error(GENERATE_REPORT_ERROR + "; filename: " + filename);
throw new GenerateReportException(GENERATE_REPORT_ERROR);
}
previousMetricsCompleted.setOverallMetricCompleted(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ private void deleteOldFiles(FIleType fIleType, long currentTimeStamp, File direc
for (File file : files) {
String fileName = file.getName();
String[] splitResult = fileName.split(FILENAME_SPLIT_PATTERN);
String timeStamp = splitResult[1];
String timeStamp = splitResult[3];
if (validateExpire(currentTimeStamp, Long.parseLong(timeStamp)) && !file.delete() && file.exists()) {
log.error("Failed to deleted expired fIleType: {} file, file name: {}", fIleType.getType(),
fileName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ private void deleteOldCSV(long currentTimeStamp, File directory) {
for (File file : files) {
String fileName = file.getName();
String[] splitResult = fileName.split("[-.]");
String timeStamp = splitResult[1];
String timeStamp = splitResult[3];
if (validateExpire(currentTimeStamp, Long.parseLong(timeStamp)) && !file.delete() && file.exists()) {
log.error("Failed to deleted expired CSV file, file name: {}", fileName);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,8 @@ public void generateReport(GenerateReportRequest request) {
threadList.add(metricTypeThread);
}

CompletableFuture.runAsync(() -> {
for (CompletableFuture<Void> thread : threadList) {
thread.join();
}

CompletableFuture<Void> allFutures = CompletableFuture.allOf(threadList.toArray(new CompletableFuture[0]));
allFutures.thenRun(() -> {
ReportResponse reportResponse = generateReporterService.getComposedReportResponse(request.getCsvTimeStamp(),
convertTimeStampToYYYYMMDD(request.getStartTime()),
convertTimeStampToYYYYMMDD(request.getEndTime()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ class AsyncExceptionHandlerTest {

public static final String APP_OUTPUT_ERROR = "./app/output/error";

public static final String START_TIME = "20240417";

public static final String END_TIME = "20240418";

@InjectMocks
AsyncExceptionHandler asyncExceptionHandler;

Expand All @@ -56,8 +60,8 @@ void shouldDeleteAsyncException() {
long fileId = System.currentTimeMillis();
String currentTime = Long.toString(fileId);
String expireTime = Long.toString(fileId - 1900000L);
String unExpireFile = IdUtil.getBoardReportFileId(currentTime);
String expireFile = IdUtil.getBoardReportFileId(expireTime);
String unExpireFile = getBoardReportFileId(currentTime);
String expireFile = getBoardReportFileId(expireTime);
asyncExceptionHandler.put(unExpireFile, new UnauthorizedException(""));
asyncExceptionHandler.put(expireFile, new UnauthorizedException(""));

Expand All @@ -74,8 +78,8 @@ void shouldDeleteAsyncExceptionTmpFile() {
long fileId = System.currentTimeMillis();
String currentTime = Long.toString(fileId);
String expireTime = Long.toString(fileId - 1900000L);
String unExpireFile = IdUtil.getBoardReportFileId(currentTime) + ".tmp";
String expireFile = IdUtil.getBoardReportFileId(expireTime) + ".tmp";
String unExpireFile = getBoardReportFileId(currentTime) + ".tmp";
String expireFile = getBoardReportFileId(expireTime) + ".tmp";
asyncExceptionHandler.put(unExpireFile, new UnauthorizedException(""));
asyncExceptionHandler.put(expireFile, new UnauthorizedException(""));

Expand All @@ -92,8 +96,8 @@ void shouldSafeDeleteAsyncExceptionWhenHaveManyThordToDeleteFile() throws Interr
long fileId = System.currentTimeMillis();
String currentTime = Long.toString(fileId);
String expireTime = Long.toString(fileId - 1900000L);
String unExpireFile = IdUtil.getBoardReportFileId(currentTime);
String expireFile = IdUtil.getBoardReportFileId(expireTime);
String unExpireFile = getBoardReportFileId(currentTime);
String expireFile = getBoardReportFileId(expireTime);
asyncExceptionHandler.put(unExpireFile, new UnauthorizedException(""));
asyncExceptionHandler.put(expireFile, new UnauthorizedException(""));
CyclicBarrier barrier = new CyclicBarrier(3);
Expand Down Expand Up @@ -125,7 +129,7 @@ void shouldSafeDeleteAsyncExceptionWhenHaveManyThordToDeleteFile() throws Interr
void shouldPutAndGetAsyncException() {
long currentTimeMillis = System.currentTimeMillis();
String currentTime = Long.toString(currentTimeMillis);
String boardReportId = IdUtil.getBoardReportFileId(currentTime);
String boardReportId = getBoardReportFileId(currentTime);
asyncExceptionHandler.put(boardReportId, new UnauthorizedException("test"));

var baseException = asyncExceptionHandler.get(boardReportId);
Expand All @@ -147,7 +151,7 @@ void shouldThrowExceptionGivenCantWriteFileWhenPutFile() {
@Test
void shouldThrowExceptionGivenCannotReadFileWhenGetFile() throws IOException {
new File("./app/output/error/").mkdirs();
String boardReportId = IdUtil.getBoardReportFileId(Long.toString(System.currentTimeMillis()));
String boardReportId = getBoardReportFileId(Long.toString(System.currentTimeMillis()));
Path filePath = Paths.get("./app/output/error/" + boardReportId);
Files.createFile(filePath);
Files.write(filePath, "test".getBytes());
Expand All @@ -163,7 +167,7 @@ void shouldCreateTargetDirWhenPutAsyncException() {
boolean mkdirs = new File(APP_OUTPUT_ERROR).mkdirs();
long currentTimeMillis = System.currentTimeMillis();
String currentTime = Long.toString(currentTimeMillis);
String boardReportId = IdUtil.getBoardReportFileId(currentTime);
String boardReportId = getBoardReportFileId(currentTime);

asyncExceptionHandler.put(boardReportId, new UnauthorizedException("test"));

Expand All @@ -177,7 +181,7 @@ void shouldCreateTargetDirWhenPutAsyncException() {
void shouldPutAndRemoveAsyncException() {
long currentTimeMillis = System.currentTimeMillis();
String currentTime = Long.toString(currentTimeMillis);
String boardReportId = IdUtil.getBoardReportFileId(currentTime);
String boardReportId = getBoardReportFileId(currentTime);
asyncExceptionHandler.put(boardReportId, new UnauthorizedException("test"));

AsyncExceptionDTO baseException = asyncExceptionHandler.remove(boardReportId);
Expand All @@ -190,7 +194,7 @@ void shouldPutAndRemoveAsyncException() {
@Test
void shouldReturnExceptionGivenWrongFileWhenReadAndRemoveAsyncException() throws IOException {
new File("./app/output/error/").mkdirs();
String boardReportId = IdUtil.getBoardReportFileId(Long.toString(System.currentTimeMillis()));
String boardReportId = getBoardReportFileId(Long.toString(System.currentTimeMillis()));
Path filePath = Paths.get("./app/output/error/" + boardReportId);
Files.createFile(filePath);
Files.write(filePath, "test".getBytes());
Expand All @@ -204,7 +208,7 @@ void shouldReturnExceptionGivenWrongFileWhenReadAndRemoveAsyncException() throws
@Test
void shouldThrowExceptionWhenDeleteFile() {
File mockFile = mock(File.class);
when(mockFile.getName()).thenReturn("board-1683734399999");
when(mockFile.getName()).thenReturn("board-20240417-20240418-1683734399999");
when(mockFile.delete()).thenThrow(new RuntimeException("test"));
File[] mockFiles = new File[] { mockFile };
File directory = mock(File.class);
Expand All @@ -217,7 +221,7 @@ void shouldThrowExceptionWhenDeleteFile() {
@Test
void shouldDeleteFailWhenDeleteFile() {
File mockFile = mock(File.class);
when(mockFile.getName()).thenReturn("board-1683734399999");
when(mockFile.getName()).thenReturn("board-20240417-20240418-1683734399999");
when(mockFile.delete()).thenReturn(false);
when(mockFile.exists()).thenReturn(true);
File[] mockFiles = new File[] { mockFile };
Expand All @@ -237,4 +241,8 @@ private void deleteTestFile(String reportId) {
asyncExceptionHandler.remove(reportId);
}

private String getBoardReportFileId(String timestamp) {
return "board-" + START_TIME + "-" + END_TIME + "-" + timestamp;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.RepeatedTest;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.junit.jupiter.MockitoExtension;
Expand All @@ -17,9 +18,15 @@
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import static heartbeat.controller.report.dto.request.MetricType.BOARD;
import static heartbeat.controller.report.dto.request.MetricType.DORA;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
Expand Down Expand Up @@ -90,7 +97,7 @@ class DeleteExpireMetricsDataCompletedFile {
@Test
void shouldDeleteMetricsDataReadyWhenMetricsFileIsExpire() throws IOException {
long currentTimeMillis = System.currentTimeMillis();
String prefix = "prefix-";
String prefix = "prefix-20240417-20240418-";
String currentTimeFileId = prefix + currentTimeMillis;
String expireTimeFileId = prefix + (currentTimeMillis - 1900000L);
String expireTimeLockFileId = prefix + (currentTimeMillis - 1900000L) + ".lock";
Expand Down Expand Up @@ -142,8 +149,7 @@ void shouldThrowGenerateReportExceptionWhenPreviousMetricsStatusIsNull() {
String currentTime = Long.toString(currentTimeMillis);

GenerateReportException exception = assertThrows(GenerateReportException.class,
() -> asyncMetricsDataHandler.updateMetricsDataCompletedInHandler(currentTime, MetricType.BOARD,
false));
() -> asyncMetricsDataHandler.updateMetricsDataCompletedInHandler(currentTime, BOARD, false));

assertEquals("Failed to update metrics data completed through this timestamp.", exception.getMessage());
}
Expand All @@ -157,7 +163,7 @@ void shouldUpdateBoardMetricDataWhenPreviousMetricsStatusIsNotNullAndMetricTypeI
.build();
asyncMetricsDataHandler.putMetricsDataCompleted(currentTime, metricsDataCompleted);

asyncMetricsDataHandler.updateMetricsDataCompletedInHandler(currentTime, MetricType.BOARD, true);
asyncMetricsDataHandler.updateMetricsDataCompletedInHandler(currentTime, BOARD, true);

MetricsDataCompleted completed = asyncMetricsDataHandler.getMetricsDataCompleted(currentTime);
assertTrue(completed.boardMetricsCompleted());
Expand Down Expand Up @@ -239,6 +245,67 @@ void shouldUpdateAllMetricDataWhenPreviousMetricsStatusIsNotNull() throws IOExce

}

@Nested
class UpdateAllMetricsCompletedInHandlerAtTheSameTime {

// The test should be moved to integration test next.
@RepeatedTest(100)
@SuppressWarnings("unchecked")
void shouldUpdateAllMetricDataAtTheSameTimeWhenPreviousMetricsStatusIsNotNull() throws IOException {
long currentTimeMillis = System.currentTimeMillis();
String currentTime = Long.toString(currentTimeMillis);
List<Integer> sleepTime = new ArrayList<>();
for (int i = 0; i < 3; i++) {
sleepTime.add(new Random().nextInt(100));
}
MetricsDataCompleted metricsDataCompleted = MetricsDataCompleted.builder()
.boardMetricsCompleted(false)
.doraMetricsCompleted(false)
.overallMetricCompleted(false)
.build();
asyncMetricsDataHandler.putMetricsDataCompleted(currentTime, metricsDataCompleted);

List<CompletableFuture<Void>> threadList = new ArrayList<>();

threadList.add(CompletableFuture.runAsync(() -> {
try {
TimeUnit.MILLISECONDS.sleep(sleepTime.get(0)); // NOSONAR
}
catch (InterruptedException ignored) {
}
asyncMetricsDataHandler.updateMetricsDataCompletedInHandler(currentTime, BOARD, true);
}));
threadList.add(CompletableFuture.runAsync(() -> {
try {
TimeUnit.MILLISECONDS.sleep(sleepTime.get(1)); // NOSONAR
}
catch (InterruptedException ignored) {
}
asyncMetricsDataHandler.updateMetricsDataCompletedInHandler(currentTime, DORA, true);
}));
threadList.add(CompletableFuture.runAsync(() -> {
try {
TimeUnit.MILLISECONDS.sleep(sleepTime.get(2)); // NOSONAR
}
catch (InterruptedException ignored) {
}
asyncMetricsDataHandler.updateOverallMetricsCompletedInHandler(currentTime);
}));

for (CompletableFuture<Void> thread : threadList) {
thread.join();
}

MetricsDataCompleted completed = asyncMetricsDataHandler.getMetricsDataCompleted(currentTime);
assertTrue(completed.boardMetricsCompleted());
assertTrue(completed.doraMetricsCompleted());
assertTrue(completed.allMetricsCompleted());
Files.deleteIfExists(Path.of(APP_OUTPUT_METRICS + "/" + currentTime));
assertNull(asyncMetricsDataHandler.getMetricsDataCompleted(currentTime));
}

}

private void createLockFile(String currentTime) throws IOException {
String fileName = APP_OUTPUT_METRICS + "/" + currentTime + ".lock";
File file = new File(fileName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ class AsyncReportRequestHandlerTest {

public static final String APP_OUTPUT_REPORT = "./app/output/report";

public static final String START_TIME = "20240417";

public static final String END_TIME = "20240418";

@InjectMocks
AsyncReportRequestHandler asyncReportRequestHandler;

Expand All @@ -47,8 +51,8 @@ void shouldDeleteReportWhenReportIsExpire() throws IOException {
long currentTimeMillis = System.currentTimeMillis();
String currentTime = Long.toString(currentTimeMillis);
String expireTime = Long.toString(currentTimeMillis - 1900000L);
String unExpireFile = IdUtil.getBoardReportFileId(currentTime);
String expireFile = IdUtil.getBoardReportFileId(expireTime);
String unExpireFile = getBoardReportFileId(currentTime);
String expireFile = getBoardReportFileId(expireTime);
asyncReportRequestHandler.putReport(unExpireFile, ReportResponse.builder().build());
asyncReportRequestHandler.putReport(expireFile, ReportResponse.builder().build());

Expand Down Expand Up @@ -79,4 +83,8 @@ void shouldThrowGenerateReportExceptionGivenFileNameInvalidWhenHandlerPutData()
() -> asyncReportRequestHandler.putReport("../", ReportResponse.builder().build()));
}

private String getBoardReportFileId(String timestamp) {
return "board-" + START_TIME + "-" + END_TIME + "-" + timestamp;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -957,7 +957,7 @@ void shouldNotDeleteOldCsvWhenExportCsvWithoutOldCsvInsideThirtyMinutes() throws
@Test
void shouldDeleteFailWhenDeleteCSV() {
File mockFile = mock(File.class);
when(mockFile.getName()).thenReturn("file1-1683734399999.CSV");
when(mockFile.getName()).thenReturn("file1-20240417-20240418-1683734399999.CSV");
when(mockFile.delete()).thenReturn(false);
File[] mockFiles = new File[] { mockFile };
File directory = mock(File.class);
Expand Down Expand Up @@ -985,7 +985,7 @@ void shouldThrowExceptionWhenDeleteCSV() {
@Test
void shouldDeleteFailWhenDeleteFile() {
File mockFile = mock(File.class);
when(mockFile.getName()).thenReturn("board-1683734399999");
when(mockFile.getName()).thenReturn("board-20240417-20240418-1683734399999");
when(mockFile.delete()).thenReturn(false);
when(mockFile.exists()).thenReturn(true);
File[] mockFiles = new File[] { mockFile };
Expand All @@ -1000,7 +1000,7 @@ void shouldDeleteFailWhenDeleteFile() {
@Test
void shouldDeleteTempFailWhenDeleteFile() {
File mockFile = mock(File.class);
when(mockFile.getName()).thenReturn("board-1683734399999.tmp");
when(mockFile.getName()).thenReturn("board-20240417-20240418-1683734399999.tmp");
when(mockFile.delete()).thenReturn(true);
when(mockFile.exists()).thenReturn(false);
File[] mockFiles = new File[] { mockFile };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ describe('PipelineMetricSelection', () => {
});

await waitFor(() => {
expect(mockHandleClickRemoveButton).toHaveBeenCalledTimes(2);
expect(mockHandleClickRemoveButton).toHaveBeenCalledTimes(0);
});
});

Expand Down
Loading

0 comments on commit 03d6e82

Please sign in to comment.