Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
@@ -1,6 +1,5 @@
package com.softeer5.uniro_backend.admin.service;

import static com.softeer5.uniro_backend.common.constant.UniroConst.*;
import static com.softeer5.uniro_backend.common.error.ErrorCode.*;

import com.softeer5.uniro_backend.admin.annotation.DisableAudit;
Expand All @@ -13,7 +12,6 @@
import com.softeer5.uniro_backend.common.exception.custom.AdminException;
import com.softeer5.uniro_backend.common.exception.custom.RouteException;
import com.softeer5.uniro_backend.common.exception.custom.UnivException;
import com.softeer5.uniro_backend.external.redis.RedisService;
import com.softeer5.uniro_backend.map.dto.response.AllRoutesInfo;
import com.softeer5.uniro_backend.map.dto.response.GetChangedRoutesByRevisionResDTO;
import com.softeer5.uniro_backend.map.dto.response.GetRiskRoutesResDTO;
Expand All @@ -22,6 +20,7 @@
import com.softeer5.uniro_backend.map.entity.Route;
import com.softeer5.uniro_backend.map.repository.NodeRepository;
import com.softeer5.uniro_backend.map.repository.RouteRepository;
import com.softeer5.uniro_backend.map.service.RouteCacheService;
import com.softeer5.uniro_backend.map.service.RouteCalculator;
import com.softeer5.uniro_backend.univ.entity.Univ;
import com.softeer5.uniro_backend.univ.repository.UnivRepository;
Expand All @@ -47,7 +46,7 @@ public class AdminService {

private final RouteCalculator routeCalculator;

private final RedisService redisService;
private final RouteCacheService cacheService;

public List<RevInfoDTO> getAllRevInfo(Long univId){

Expand Down Expand Up @@ -114,8 +113,7 @@ public void rollbackRev(Long univId, Long versionId){
}
}

int routeCount = routes.size();
redisService.deleteRoutesData(univId.toString(), routeCount / STREAM_FETCH_SIZE + 1);
cacheService.deleteFetchSizeAndLightRoutesByUnivId(univId);
}

public GetAllRoutesByRevisionResDTO getAllRoutesByRevision(Long univId, Long versionId){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,23 +62,22 @@ public AllRoutesInfo getAllRoutesByStream(Long univId) {
List<CoreRouteResDTO> coreRoutes = new ArrayList<>();
List<BuildingRouteResDTO> buildingRoutes = new ArrayList<>();

String cacheKeyPrefix = univId + ":";
int batchNumber = 1;

if (!processCacheDataByStream(cacheKeyPrefix, batchNumber, nodeInfos, coreRoutes, buildingRoutes)) {
processDatabaseDataByStream(univId, cacheKeyPrefix, batchNumber, nodeInfos, coreRoutes, buildingRoutes);
if (!processCacheDataByStream(univId, batchNumber, nodeInfos, coreRoutes, buildingRoutes)) {
processDatabaseDataByStream(univId, batchNumber, nodeInfos, coreRoutes, buildingRoutes);
}

return AllRoutesInfo.of(nodeInfos, coreRoutes, buildingRoutes);
}

private boolean processCacheDataByStream(String cacheKeyPrefix,
private boolean processCacheDataByStream(Long unvId,
int batchNumber,
List<NodeInfoResDTO> nodeInfos,
List<CoreRouteResDTO> coreRoutes,
List<BuildingRouteResDTO> buildingRoutes){
while (cacheService.hasData(cacheKeyPrefix + batchNumber)) {
LightRoutes lightRoutes = cacheService.getLightRoutes(cacheKeyPrefix + batchNumber);
while (cacheService.hasLightRoutes(unvId, batchNumber)) {
LightRoutes lightRoutes = cacheService.getLightRoutes(unvId, batchNumber);
if (lightRoutes == null) {
break;
}
Expand All @@ -90,7 +89,7 @@ private boolean processCacheDataByStream(String cacheKeyPrefix,
return batchNumber > 1;
}

private void processDatabaseDataByStream(Long univId, String cacheKeyPrefix, int batchNumber,
private void processDatabaseDataByStream(Long univId, int batchNumber,
List<NodeInfoResDTO> nodeInfos,
List<CoreRouteResDTO> coreRoutes,
List<BuildingRouteResDTO> buildingRoutes) {
Expand All @@ -104,27 +103,27 @@ private void processDatabaseDataByStream(Long univId, String cacheKeyPrefix, int
batch.add(route);

if (batch.size() == STREAM_FETCH_SIZE) {
saveAndSendBatchByStream(cacheKeyPrefix, batchNumber++, batch, nodeInfos, coreRoutes, buildingRoutes);
saveAndSendBatchByStream(univId, batchNumber++, batch, nodeInfos, coreRoutes, buildingRoutes);
}
}

// 남은 배치 처리
if (!batch.isEmpty()) {
saveAndSendBatchByStream(cacheKeyPrefix, batchNumber, batch, nodeInfos, coreRoutes, buildingRoutes);
saveAndSendBatchByStream(univId, batchNumber, batch, nodeInfos, coreRoutes, buildingRoutes);
}

cacheService.saveFetchSize(univId.toString() + ":fetch", fetchSize);
cacheService.saveFetchSize(univId, fetchSize);
}

}

private void saveAndSendBatchByStream(String cacheKeyPrefix, int batchNumber, List<LightRoute> batch,
private void saveAndSendBatchByStream(Long univId, int batchNumber, List<LightRoute> batch,
List<NodeInfoResDTO> nodeInfos,
List<CoreRouteResDTO> coreRoutes,
List<BuildingRouteResDTO> buildingRoutes) {
List<LightRoute> copyBatch = new ArrayList<>(batch);
LightRoutes value = new LightRoutes(copyBatch);
cacheService.saveLightRoutes(cacheKeyPrefix + batchNumber, value);
cacheService.saveLightRoutes(univId, batchNumber, value);
processBatchByStream(batch, nodeInfos, coreRoutes, buildingRoutes);
batch.clear();
}
Expand All @@ -143,27 +142,26 @@ private void processBatchByStream(List<LightRoute> batch,

@Async
public void getAllRoutesBySSE(Long univId, SseEmitter emitter) {
String cacheKeyPrefix = univId + ":";
int batchNumber = 1;

try {
if (cacheService.hasData(cacheKeyPrefix + "fetch")) {
processCacheData(cacheKeyPrefix, batchNumber, emitter);
if (cacheService.hasFetchSize(univId)) {
processCacheData(univId, batchNumber, emitter);
return;
}

processDatabaseData(univId, cacheKeyPrefix, batchNumber, emitter);
processDatabaseData(univId, batchNumber, emitter);
} catch (Exception e) {
emitter.completeWithError(e);
log.error("SSE error: {}", e.getMessage(), e);
}
}

private void processCacheData(String cacheKeyPrefix, int batchNumber, SseEmitter emitter) throws Exception {
Integer fetchSize = cacheService.getFetchSize(cacheKeyPrefix + "fetch");
private void processCacheData(Long univId, int batchNumber, SseEmitter emitter) {
Integer fetchSize = cacheService.getFetchSize(univId);

while (cacheService.hasData(cacheKeyPrefix + batchNumber)) {
LightRoutes lightRoutes = cacheService.getLightRoutes(cacheKeyPrefix + batchNumber);
while (cacheService.hasLightRoutes(univId, batchNumber)) {
LightRoutes lightRoutes = cacheService.getLightRoutes(univId, batchNumber);
if (lightRoutes == null) {
break;
}
Expand All @@ -178,7 +176,7 @@ private void processCacheData(String cacheKeyPrefix, int batchNumber, SseEmitter
}
}

private void processDatabaseData(Long univId, String cacheKeyPrefix, int batchNumber, SseEmitter emitter) {
private void processDatabaseData(Long univId, int batchNumber, SseEmitter emitter) {
int fetchSize = routeRepository.countByUnivId(univId);
int remain = fetchSize % STREAM_FETCH_SIZE;
fetchSize = fetchSize / STREAM_FETCH_SIZE + (remain > 0 ? 1 : 0);
Expand All @@ -189,27 +187,27 @@ private void processDatabaseData(Long univId, String cacheKeyPrefix, int batchNu
batch.add(route);

if (batch.size() == STREAM_FETCH_SIZE) {
saveAndSendBatch(cacheKeyPrefix, batchNumber++, batch, emitter, fetchSize);
saveAndSendBatch(univId, batchNumber++, batch, emitter, fetchSize);
}
}

// 남은 배치 처리
if (!batch.isEmpty()) {
saveAndSendBatch(cacheKeyPrefix, batchNumber, batch, emitter, fetchSize);
saveAndSendBatch(univId, batchNumber, batch, emitter, fetchSize);
}

cacheService.saveFetchSize(univId.toString() + ":fetch", fetchSize);
cacheService.saveFetchSize(univId, fetchSize);
emitter.complete();
log.info("[SSE emitter complete] DB data used.");
} catch (Exception e) {
throw new RuntimeException(e);
}
}

private void saveAndSendBatch(String cacheKeyPrefix, int batchNumber, List<LightRoute> batch, SseEmitter emitter, Integer fetchSize) {
private void saveAndSendBatch(Long univId, int batchNumber, List<LightRoute> batch, SseEmitter emitter, Integer fetchSize) {
List<LightRoute> copyBatch = new ArrayList<>(batch);
LightRoutes value = new LightRoutes(copyBatch);
cacheService.saveLightRoutes(cacheKeyPrefix + batchNumber, value);
cacheService.saveLightRoutes(univId, batchNumber, value);
processBatch(batch, emitter, fetchSize);
batch.clear();
}
Expand Down Expand Up @@ -252,8 +250,6 @@ public GetRiskRoutesResDTO getRiskRoutes(Long univId) {
return routeCalculator.mapRisks(riskRoutes);
}



public GetRiskResDTO getRisk(Long univId, Long routeId) {
Route route = routeRepository.findById(routeId)
.orElseThrow(() -> new RouteException("Route not found", ROUTE_NOT_FOUND));
Expand Down Expand Up @@ -336,7 +332,7 @@ public synchronized AllRoutesInfo createRoute(Long univId, CreateRoutesReqDTO re
nodeRepository.saveAll(nodesForSave);
routeRepository.saveAll(routes);

cacheService.deleteLightRoutes(univId.toString());
cacheService.deleteFetchSizeAndLightRoutesByUnivId(univId);

eventPublisher.publishEvent(new RouteCreatedEvent());
return routeCalculator.assembleRoutes(routes);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,40 +7,53 @@

@Component
public class RouteCacheService {
private static final String FETCH_SIZE_POSTFIX = ":fetch";

private final Cache routeCache;

public RouteCacheService(CacheManager cacheManager) {
this.routeCache = cacheManager.getCache("lightRoutes");
}

public LightRoutes getLightRoutes(String key) {
return routeCache.get(key, LightRoutes.class);
public LightRoutes getLightRoutes(Long univId, int batchNumber) {
String lightRoutesKey = univId + ":" + batchNumber;
return routeCache.get(lightRoutesKey, LightRoutes.class);
}

public void saveLightRoutes(String key, LightRoutes value) {
routeCache.put(key, value);
public void saveLightRoutes(Long univId, int batchNumber, LightRoutes value) {
String lightRoutesKey = univId + ":" + batchNumber;
routeCache.put(lightRoutesKey, value);
}

public Integer getFetchSize(String key){
return routeCache.get(key, Integer.class);
public boolean hasLightRoutes(Long univId, int batchNumber){
String lightRoutesKey = univId + ":" + batchNumber;
return routeCache.get(lightRoutesKey) != null;
}

public void saveFetchSize(String key, Integer fetchSize){
routeCache.put(key, fetchSize);
public Integer getFetchSize(Long univId){
String fetchSizeKey = univId + FETCH_SIZE_POSTFIX;
return routeCache.get(fetchSizeKey, Integer.class);
}

public void deleteLightRoutes(String key){
String keyPrefix = key + ":";
public void saveFetchSize(Long univId, Integer fetchSize){
String fetchSizeKey = univId + FETCH_SIZE_POSTFIX;
routeCache.put(fetchSizeKey, fetchSize);
}

public boolean hasFetchSize(Long univId){
String fetchSizeKey = univId + FETCH_SIZE_POSTFIX;
return routeCache.get(fetchSizeKey) != null;
}

public void deleteFetchSizeAndLightRoutesByUnivId(Long univId){
String keyPrefix = univId + ":";

Integer batchNumber = getFetchSize(key);
Integer batchNumber = getFetchSize(univId);

if(batchNumber == null) return;

for(int i=1; i<= batchNumber; i++){
routeCache.evictIfPresent(keyPrefix + i);
}
}

public boolean hasData(String key){
return routeCache.get(key) != null;
}
}