Skip to content
Merged

prod #376

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
64 changes: 64 additions & 0 deletions .github/ISSUE_TEMPLATE/코드 안정성.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
---
name: 코드 안정성
about: 코드 안정성 대한 요청

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

템플릿 설명에 사소한 오타가 있습니다. '코드 안정성 대한 요청'을 '코드 안정성에 대한 요청'으로 수정하여 문법적으로 더 자연스럽게 만들 수 있습니다.

Suggested change
about: 코드 안정성 대한 요청
about: 코드 안정성에 대한 요청

title: "[🛠 코드 안정성] "
labels: 코드 안정성
assignees: ""
---

## ✨ 문제 요약

현재 발생한 문제나 개선이 필요한 부분에 대해 한 줄로 명확하게 요약해주세요.

----

-

## 🐛 어떤 문제가 발생했나요?

자세한 문제 상황을 설명해주세요. 버그, 성능 저하, 코드의 문제점(Code Smell) 등 어떤 종류의 안정성 문제인지 구체적으로 서술합니다.

----

-

## 🕹️ 어떻게 재현할 수 있나요?

문제를 재현할 수 있는 구체적인 순서를 단계별로 작성해주세요.
만약 재현이 어렵다면, 어떤 상황에서 주로 발생하는지 설명해주세요. (ex. 특정 API에 요청이 몰릴 때)

----

1. `이 단계에서는...`
2. `그 다음에는...`
3. `그러면 문제가 발생합니다.`

## 🤔 기대 결과와 실제 결과는 무엇이었나요?

- **기대 결과**: 원래라면 어떻게 동작해야 했는지 설명해주세요.
- **실제 결과**: 실제로 어떻게 동작했는지, 어떤 오류가 발생했는지 설명해주세요.

----

- **기대 결과**:
- **실제 결과**:

## 📎 근거 자료

문제 상황을 파악하는 데 도움이 되는 모든 자료를 첨부해주세요.

- **에러 로그**: `(에러 로그를 여기에 붙여넣어 주세요)`
- **스크린샷**: `(스크린샷 이미지 첨부)`
- **관련 코드**: 문제가 발생한 코드의 일부 또는 파일 경로

----

-

## 📝 추가 사항

이슈 해결에 도움이 될 만한 추가 정보나 고려해야 할 조건이 있다면 자유롭게 기입해주세요.

----

-
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import life.mosu.mosuserver.presentation.application.dto.ApplicationResponse;
import life.mosu.mosuserver.presentation.application.dto.CreateApplicationResponse;
import life.mosu.mosuserver.presentation.application.dto.ExamApplicationRequest;
import life.mosu.mosuserver.presentation.application.dto.SchoolApplicationCountResponse;
import life.mosu.mosuserver.presentation.common.FileRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
Expand Down Expand Up @@ -103,4 +104,9 @@ private CreateApplicationResponse handleApplication(
public List<ApplicationResponse> getApplications(Long userId) {
return getApplicationsStepProcessor.process(userId);
}

@Transactional(readOnly = true)
public List<SchoolApplicationCountResponse> getPaidApplicationCountBySchool() {
return applicationJpaRepository.findPaidApplicationCountBySchool();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
@RequiredArgsConstructor
public class ApplicationFailureLogDomainArchiveExecutor implements DomainArchiveExecutor {

private final static Duration DURATION_HOURS_STANDARD = Duration.ofHours(1);
private final static Duration DURATION_HOURS_STANDARD = Duration.ofHours(48);
private final static int BATCH_SIZE = 500;

private final ApplicationFailureLogFactory applicationFailureLogFactory;
Expand Down Expand Up @@ -63,7 +63,7 @@ public String getName() {
}

private List<ApplicationJpaEntity> findFailedApplications() {
Instant threshold = Instant.now().minus(DURATION_HOURS_STANDARD); // 3 hours ago
Instant threshold = Instant.now().minus(DURATION_HOURS_STANDARD);
LocalDateTime time = LocalDateTime.ofInstant(threshold, ZoneId.systemDefault());
return applicationJpaRepository.findFailedApplications(time);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.time.LocalDateTime;
import java.util.List;
import life.mosu.mosuserver.domain.application.entity.ApplicationJpaEntity;
import life.mosu.mosuserver.presentation.application.dto.SchoolApplicationCountResponse;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
Expand All @@ -29,6 +30,21 @@ AND a.status IN ('PENDING', 'ABORT')
""")
List<ApplicationJpaEntity> findAllByUserId(@Param("userId") Long userId);

@Query("""
SELECT new life.mosu.mosuserver.presentation.application.dto.SchoolApplicationCountResponse(
e.schoolName,
COUNT(a.id)
)
FROM ApplicationJpaEntity a
JOIN ExamApplicationJpaEntity ea ON ea.applicationId = a.id
JOIN ExamJpaEntity e ON e.id = ea.examId
WHERE a.deleted = false
AND a.status = 'APPROVED'
GROUP BY e.schoolName
ORDER BY e.schoolName
""")
List<SchoolApplicationCountResponse> findPaidApplicationCountBySchool();

@Modifying
@Query(value = """
UPDATE application a
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ public enum Whitelist {
//USER find-password
USER_FIND_PASSWORD("/api/v1/user/me/find-password", WhitelistMethod.POST),

APPLICATION_GUEST("/api/v1/applications/guest", WhitelistMethod.ALL);

APPLICATION_GUEST("/api/v1/applications/guest", WhitelistMethod.ALL),
APPLICATION_PAID("/api/v1/applications/schools/paid-count",WhitelistMethod.ALL);
private static final List<ExceptionRule> AUTH_REQUIRED_EXCEPTIONS = List.of(
new ExceptionRule("/api/v1/exam-application", WhitelistMethod.GET)
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
package life.mosu.mosuserver.infra.cron.job;


import java.time.LocalDateTime;
import java.util.List;
import life.mosu.mosuserver.global.support.cron.LogCleanupExecutor;
import life.mosu.mosuserver.infra.cron.annotation.CronJob;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
Expand All @@ -17,22 +13,22 @@
name = "logCleanupJob"
)
@DisallowConcurrentExecution
@RequiredArgsConstructor
//@RequiredArgsConstructor
public class LogCleanupJob implements Job {

private final List<LogCleanupExecutor> cleanups;
// private final List<LogCleanupExecutor> cleanups;

@Override
public void execute(JobExecutionContext context) {
LocalDateTime threshold = LocalDateTime.now().minusMonths(3);
for (LogCleanupExecutor cleanup : cleanups) {
try {
int deleted = cleanup.deleteLogsBefore(threshold);
log.info("[LogCleanupJob] Deleted total {} logs older than {}", deleted, threshold);
} catch (Exception e) {
log.error("[LogCleanupJob] Error during log cleanup: {}",
cleanup.getClass().getSimpleName(), e);
}
}
// LocalDateTime threshold = LocalDateTime.now().minusMonths(3);
// for (LogCleanupExecutor cleanup : cleanups) {
// try {
// int deleted = cleanup.deleteLogsBefore(threshold);
// log.info("[LogCleanupJob] Deleted total {} logs older than {}", deleted, threshold);
// } catch (Exception e) {
// log.error("[LogCleanupJob] Error during log cleanup: {}",
// cleanup.getClass().getSimpleName(), e);
// }
// }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import life.mosu.mosuserver.presentation.application.dto.ApplicationRequest;
import life.mosu.mosuserver.presentation.application.dto.ApplicationResponse;
import life.mosu.mosuserver.presentation.application.dto.CreateApplicationResponse;
import life.mosu.mosuserver.presentation.application.dto.SchoolApplicationCountResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
Expand Down Expand Up @@ -74,4 +75,12 @@ public ResponseEntity<ApiResponseWrapper<List<ApplicationResponse>>> getApplicat
return ResponseEntity.ok(
ApiResponseWrapper.success(HttpStatus.OK, "신청 내역 조회 성공", responses));
}

//학교별 결제된 신청 수 조회
@GetMapping("/schools/paid-count")
public ResponseEntity<ApiResponseWrapper<List<SchoolApplicationCountResponse>>> getPaidApplicationCountBySchool() {
List<SchoolApplicationCountResponse> responses = applicationService.getPaidApplicationCountBySchool();
return ResponseEntity.ok(
ApiResponseWrapper.success(HttpStatus.OK, "학교별 결제된 신청 수 조회 성공", responses));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package life.mosu.mosuserver.presentation.application.dto;

import io.swagger.v3.oas.annotations.media.Schema;

@Schema(description = "학교별 결제된 신청 수 응답")
public record SchoolApplicationCountResponse(
@Schema(description = "학교명", example = "서울고등학교")
String schoolName,

@Schema(description = "결제된 신청 수", example = "25")
Long paidApplicationCount
) {
}

This file was deleted.