Skip to content

Commit a4e0ec0

Browse files
authored
Merge pull request #81 from Gitdeun/dev
Dev
2 parents 21bb2f5 + ce7586b commit a4e0ec0

File tree

2 files changed

+52
-36
lines changed

2 files changed

+52
-36
lines changed

src/main/java/com/teamEWSN/gitdeun/common/fastapi/FastApiClient.java

Lines changed: 37 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.teamEWSN.gitdeun.common.fastapi;
22

3+
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
34
import com.fasterxml.jackson.annotation.JsonProperty;
45
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
56
import com.teamEWSN.gitdeun.common.converter.IsoToLocalDateTimeDeserializer;
@@ -249,7 +250,7 @@ public SuggestionAutoResponse createAutoSuggestions(
249250
}
250251
}
251252

252-
public String getFileRaw(String repoUrl, String filePath, String authHeader) {
253+
/* public String getFileRaw(String repoUrl, String filePath, String authHeader) {
253254
return getFileRaw(repoUrl, filePath, null, null, null, authHeader);
254255
}
255256
@@ -309,52 +310,50 @@ public String getFileRaw(String repoUrl, String filePath, Integer startLine, Int
309310
log.error("FastAPI 파일 내용 조회 실패 - repoId: {}, filePath: {}", repoId, filePath, e);
310311
return ""; // 빈 문자열 반환 (null 대신)
311312
}
312-
}
313+
}*/
313314

314-
public String getFileRawFromNode(String nodeKey, String filePath, String authHeader) {
315+
public String getCodeFromNode(String nodeKey, String filePath, String authHeader) {
316+
String fileName = extractFileName(filePath);
315317
try {
316-
log.debug("FastAPI 파일 내용 조회 시작 - nodeKey: {}, filePath: {}", nodeKey, filePath);
318+
log.debug("FastAPI 노드 기반 코드 조회 시작 - nodeKey: {}, filePath: {}", nodeKey, fileName);
317319

318-
// URI 생성 (쿼리 파라미터 포함)
319320
UriComponentsBuilder uriBuilder = UriComponentsBuilder
320-
.fromPath("/content/file/nodes")
321+
.fromPath("/content/file/by-node") // FastAPI의 해당 엔드포인트
321322
.queryParam("node_key", nodeKey)
322-
.queryParam("file_path", filePath);
323+
.queryParam("file_path", fileName);
324+
// 'prefer' 파라미터는 생략하여 FastAPI의 기본값(auto)을 따르도록 함
323325

324326
String uri = uriBuilder.build().toUriString();
325327

326-
String response = webClient.get()
328+
NodeCodeResponse response = webClient.get()
327329
.uri(uri)
328330
.headers(headers -> {
329331
if (authHeader != null && !authHeader.trim().isEmpty()) {
330332
headers.set("Authorization", authHeader);
331333
}
332-
headers.set("Accept", "text/plain");
333334
})
334335
.retrieve()
335-
.onStatus(HttpStatusCode::is4xxClientError, clientResponse -> {
336-
log.warn("FastAPI 파일 조회 4xx 오류 - nodeKey: {}, filePath: {}, status: {}",
337-
nodeKey, filePath, clientResponse.statusCode());
338-
return clientResponse.bodyToMono(String.class)
339-
.map(errorBody -> new RuntimeException("파일을 찾을 수 없습니다: " + errorBody));
340-
})
341-
.onStatus(HttpStatusCode::is5xxServerError, serverResponse -> {
342-
log.error("FastAPI 파일 조회 5xx 오류 - nodeKey: {}, filePath: {}, status: {}",
343-
nodeKey, filePath, serverResponse.statusCode());
344-
return Mono.error(new RuntimeException("FastAPI 서버 오류"));
345-
})
346-
.bodyToMono(String.class)
336+
.onStatus(HttpStatusCode::is4xxClientError, clientResponse ->
337+
clientResponse.bodyToMono(String.class)
338+
.map(errorBody -> {
339+
log.warn("FastAPI 노드 코드 조회 4xx 오류 - nodeKey: {}, fileName: {}, status: {}, body: {}",
340+
nodeKey, fileName, clientResponse.statusCode(), errorBody);
341+
return new RuntimeException("FastAPI 클라이언트 오류: " + errorBody);
342+
})
343+
)
344+
.bodyToMono(NodeCodeResponse.class)
347345
.timeout(Duration.ofSeconds(30))
348346
.block();
349347

350-
log.debug("FastAPI 파일 내용 조회 완료 - nodeKey: {}, filePath: {}, 길이: {}",
351-
nodeKey, filePath, response != null ? response.length() : 0);
348+
String codeContent = (response != null) ? response.getCode() : "";
349+
log.debug("FastAPI 노드 기반 코드 조회 성공 - nodeKey: {}, fileName: {}, 길이: {}",
350+
nodeKey, fileName, codeContent != null ? codeContent.length() : 0);
352351

353-
return response != null ? response : "";
352+
return codeContent;
354353

355354
} catch (Exception e) {
356-
log.error("FastAPI 파일 내용 조회 실패 - nodeKey: {}, filePath: {}", nodeKey, filePath, e);
357-
return ""; // 빈 문자열 반환 (null 대신)
355+
log.error("FastAPI 노드 기반 코드 조회 실패 - nodeKey: {}, fileName: {}", nodeKey, fileName, e);
356+
return ""; // 예외 발생 시 빈 문자열 반환
358357
}
359358
}
360359

@@ -366,6 +365,11 @@ private String extractMapId(String repoUrl) {
366365
return segments[segments.length - 1].replaceAll("\\.git$", "");
367366
}
368367

368+
// 파일명 추출
369+
public String extractFileName(String filePath) {
370+
return filePath.substring(filePath.lastIndexOf('/') + 1);
371+
}
372+
369373
private AnalysisResultDto buildAnalysisResultDto(
370374
RepoInfoResponse repoInfo
371375
) {
@@ -388,6 +392,13 @@ private AnalysisResultDto buildRefreshResultDto(
388392

389393
// === Response DTOs ===
390394

395+
@Getter
396+
@Setter
397+
@JsonIgnoreProperties(ignoreUnknown = true) // code 필드 외 다른 필드는 무시
398+
private static class NodeCodeResponse {
399+
private String code;
400+
}
401+
391402
@Getter
392403
@Setter
393404
public static class FetchResponse {

src/main/java/com/teamEWSN/gitdeun/mindmap/util/FileContentCache.java

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,14 @@ public class FileContentCache {
2929

3030
@Component
3131
public static class FileContentL1Cache {
32-
@Cacheable(value = "FILE_CONTENT_L1", key = "#key")
32+
@Cacheable(value = "FILE_CONTENT_L1", key = "#key",
33+
unless = "#result == null || #result.isEmpty()")
3334
public String getFromL1Cache(String key) {
34-
return null;
35+
return null; // 미스면 null
3536
}
3637

37-
@CachePut(value = "FILE_CONTENT_L1", key = "#key")
38+
@CachePut(value = "FILE_CONTENT_L1", key = "#key",
39+
condition = "#content != null && !#content.isBlank()")
3840
public String cacheToL1(String key, String content) {
3941
return content;
4042
}
@@ -46,7 +48,6 @@ public void evictL1Cache() {
4648

4749

4850
public String getFileContentWithCacheFromNode(String repoUrl, String nodeKey, String filePath, LocalDateTime lastCommit, String authHeader) {
49-
// 캐시 키에 repoUrl을 포함시켜 어떤 리포지토리의 캐시인지 명확히 합니다.
5051
String cacheKey = "file-content:" + repoUrl + ":node:" + nodeKey + ":" + filePath + ":" + lastCommit.toString();
5152

5253
// 1. L1 캐시 확인
@@ -59,23 +60,27 @@ public String getFileContentWithCacheFromNode(String repoUrl, String nodeKey, St
5960
// 2. L2 캐시 확인
6061
try {
6162
content = (String) redisTemplate.opsForValue().get(cacheKey);
62-
if (content != null) {
63+
if (content != null && !content.isBlank()) {
6364
log.debug("파일 내용 L2 캐시 히트 - key: {}", cacheKey);
6465
l1Cache.cacheToL1(cacheKey, content); // L1에 저장
6566
return content;
67+
} else if (content != null && content.isBlank()) {
68+
log.warn("L2 캐시에서 빈 문자열 발견 - key: {} (전파/재적재 하지 않음)", cacheKey);
69+
// 캐시에 남겨두지 말고 즉시 삭제
70+
try { redisTemplate.delete(cacheKey); } catch (Exception ignore) {}
6671
}
6772
} catch (Exception e) {
6873
log.warn("Redis 조회 실패, API 직접 호출 - key: {}", cacheKey, e);
6974
}
7075

71-
// 3. FastAPI 실시간 조회
72-
content = fastApiClient.getFileRawFromNode(nodeKey, filePath, authHeader);
76+
// 3. FastAPI 실시간 조회 (새로 만든 메서드를 호출하도록 변경)
77+
content = fastApiClient.getCodeFromNode(nodeKey, filePath, authHeader);
7378

7479
// 4. L1, L2 캐시에 저장
75-
if (content != null) {
80+
if (content != null && !content.isBlank()) {
7681
l1Cache.cacheToL1(cacheKey, content);
7782
try {
78-
redisTemplate.opsForValue().set(cacheKey, content, Duration.ofHours(2)); // L2: 2시간
83+
redisTemplate.opsForValue().set(cacheKey, content, Duration.ofHours(2));
7984
} catch (Exception e) {
8085
log.warn("Redis 저장 실패 - key: {}", cacheKey, e);
8186
}
@@ -88,7 +93,7 @@ public String getFileContentWithCacheFromNode(String repoUrl, String nodeKey, St
8893
public void evictFileCacheForRepo(String repoUrl) {
8994
// L1 캐시는 전체 삭제
9095
l1Cache.evictL1Cache();
91-
deleteRedisKeysByPattern("file-content:repo:" + repoUrl + ":*");
96+
deleteRedisKeysByPattern("file-content:" + repoUrl + ":*");
9297
}
9398

9499
private void deleteRedisKeysByPattern(String pattern) {

0 commit comments

Comments
 (0)