Skip to content
Merged
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
2 changes: 2 additions & 0 deletions backend/src/main/java/moadong/MoadongApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@RequiredArgsConstructor
@EnableScheduling
public class MoadongApplication {

public static void main(String[] args) {
Expand Down
5 changes: 5 additions & 0 deletions backend/src/main/java/moadong/club/entity/Club.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import moadong.club.enums.ClubRecruitmentStatus;
import moadong.club.enums.ClubState;
import moadong.club.payload.request.ClubInfoRequest;
import moadong.club.payload.request.ClubRecruitmentInfoUpdateRequest;
Expand Down Expand Up @@ -93,4 +94,8 @@ public void updateLogo(String logo) {
public void updateFeedImages(List<String> feedImages) {
this.clubRecruitmentInformation.updateFeedImages(feedImages);
}

public void updateRecruitmentStatus(ClubRecruitmentStatus clubRecruitmentStatus) {
this.clubRecruitmentInformation.updateRecruitmentStatus(clubRecruitmentStatus);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,17 @@ public boolean hasRecruitmentPeriod() {

public ZonedDateTime getRecruitmentStart() {
ZoneId seoulZone = ZoneId.of("Asia/Seoul");
if (recruitmentStart == null) {
return null;
}
return recruitmentStart.atZone(seoulZone);
}

public ZonedDateTime getRecruitmentEnd() {
ZoneId seoulZone = ZoneId.of("Asia/Seoul");
if (recruitmentEnd == null) {
return null;
}
return recruitmentEnd.atZone(seoulZone);
}

Expand Down
31 changes: 12 additions & 19 deletions backend/src/main/java/moadong/club/service/ClubProfileService.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
import moadong.club.entity.Club;
import moadong.club.payload.dto.ClubDetailedResult;
import moadong.club.payload.request.ClubCreateRequest;
import moadong.club.payload.request.ClubRecruitmentInfoUpdateRequest;
import moadong.club.payload.request.ClubInfoRequest;
import moadong.club.payload.request.ClubRecruitmentInfoUpdateRequest;
import moadong.club.payload.response.ClubDetailedResponse;
import moadong.club.repository.ClubRepository;
import moadong.global.exception.ErrorCode;
Expand All @@ -20,14 +20,13 @@
public class ClubProfileService {

private final ClubRepository clubRepository;
private final RecruitmentScheduler recruitmentScheduler;

public String createClub(ClubCreateRequest request) {
Club club = Club.builder()
.name(request.name())
.category(request.category())
.division(request.division())
.build();
.name(request.name())
.category(request.category())
.division(request.division())
.build();
clubRepository.save(club);

return club.getId();
Expand All @@ -40,34 +39,28 @@ public void updateClubInfo(ClubInfoRequest request, CustomUserDetails user) {
clubRepository.save(club);
}

public void updateClubRecruitmentInfo(ClubRecruitmentInfoUpdateRequest request, CustomUserDetails user) {
public void updateClubRecruitmentInfo(ClubRecruitmentInfoUpdateRequest request,
CustomUserDetails user) {
Club club = validateClubUpdateRequest(request.id(), user);

club.update(request);
clubRepository.save(club);

//모집일정을 동적스케쥴러에 달아둠
if (request.recruitmentStart() != null && request.recruitmentEnd() != null) {
recruitmentScheduler.scheduleRecruitment(club.getId(), request.recruitmentStart(),
request.recruitmentEnd());
}
}

public ClubDetailedResponse getClubDetail(String clubId) {
ObjectId objectId = ObjectIdConverter.convertString(clubId);
Club club = clubRepository.findClubById(objectId)
.orElseThrow(() -> new RestApiException(ErrorCode.CLUB_NOT_FOUND));
.orElseThrow(() -> new RestApiException(ErrorCode.CLUB_NOT_FOUND));

ClubDetailedResult clubDetailedResult = ClubDetailedResult.of(
club
club
);
return new ClubDetailedResponse(clubDetailedResult);
}

private Club validateClubUpdateRequest(String clubId, CustomUserDetails user){
private Club validateClubUpdateRequest(String clubId, CustomUserDetails user) {
Club club = clubRepository.findById(clubId)
.orElseThrow(() -> new RestApiException(ErrorCode.CLUB_NOT_FOUND));
if (!user.getId().equals(club.getUserId())){
.orElseThrow(() -> new RestApiException(ErrorCode.CLUB_NOT_FOUND));
if (!user.getId().equals(club.getUserId())) {
throw new RestApiException(ErrorCode.USER_UNAUTHORIZED);
}
return club;
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package moadong.club.service;

import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import java.util.List;
import lombok.RequiredArgsConstructor;
import moadong.club.entity.Club;
import moadong.club.entity.ClubRecruitmentInformation;
import moadong.club.enums.ClubRecruitmentStatus;
import moadong.club.repository.ClubRepository;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
@RequiredArgsConstructor
public class RecruitmentStateChecker {

private final ClubRepository clubRepository;

@Scheduled(fixedRate = 60 * 60 * 1000) // 5분마다 실행
public void performTask() {
List<Club> clubs = clubRepository.findAll();
for (Club club : clubs) {
ClubRecruitmentInformation recruitInfo = club.getClubRecruitmentInformation();
ZonedDateTime recruitmentStartDate = recruitInfo.getRecruitmentStart();
ZonedDateTime recruitmentEndDate = recruitInfo.getRecruitmentEnd();
if (recruitInfo.getClubRecruitmentStatus() == ClubRecruitmentStatus.ALWAYS) {
continue;
}
Comment on lines +22 to +30
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

스케줄링 태스크 성능 보장을 위한 조치 필요

스케줄링 메서드에 트랜잭션 관리가 없습니다. DB 작업을 포함하는 스케줄링 태스크에서는 트랜잭션 관리가 중요합니다. 또한, 모든 클럽을 한번에 가져오는 방식은 클럽 수가 많아질 경우 성능 이슈가 발생할 수 있습니다.

@Scheduled(fixedRate = 60 * 60 * 1000) // 5분마다 실행
+ @Transactional
public void performTask() {
    List<Club> clubs = clubRepository.findAll();

추가적으로 페이징 처리를 고려해보세요:

public void performTask() {
    int pageSize = 100;
    int pageNumber = 0;
    Page<Club> clubsPage;
    
    do {
        Pageable pageable = PageRequest.of(pageNumber++, pageSize);
        clubsPage = clubRepository.findAll(pageable);
        processClubPage(clubsPage.getContent());
    } while (clubsPage.hasNext());
}

private void processClubPage(List<Club> clubs) {
    for (Club club : clubs) {
        // 현재 로직 구현
    }
}

if (recruitmentStartDate != null && recruitmentEndDate != null) {
ZonedDateTime now = ZonedDateTime.now(ZoneId.of("Asia/Seoul"));
if (now.isBefore(recruitmentStartDate)) {
long between = ChronoUnit.DAYS.between(recruitmentStartDate, now);
if (between <= 14) {
club.updateRecruitmentStatus(ClubRecruitmentStatus.UPCOMING);
} else {
club.updateRecruitmentStatus(ClubRecruitmentStatus.CLOSED);
}
} else if (now.isAfter(recruitmentStartDate) && now.isBefore(recruitmentEndDate)) {
club.updateRecruitmentStatus(ClubRecruitmentStatus.OPEN);
} else if (now.isAfter(recruitmentEndDate)) {
club.updateRecruitmentStatus(ClubRecruitmentStatus.CLOSED);
}
Comment on lines +31 to +44
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

날짜 비교 로직 버그 수정 필요

34번 라인의 날짜 차이 계산 로직에 버그가 있습니다. between(recruitmentStartDate, now)는 시작일과 현재 시간의 차이를 음수로 계산합니다. 올바른 계산을 위해서는 순서를 바꿔야 합니다.

- long between = ChronoUnit.DAYS.between(recruitmentStartDate, now);
+ long between = ChronoUnit.DAYS.between(now, recruitmentStartDate);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (recruitmentStartDate != null && recruitmentEndDate != null) {
ZonedDateTime now = ZonedDateTime.now(ZoneId.of("Asia/Seoul"));
if (now.isBefore(recruitmentStartDate)) {
long between = ChronoUnit.DAYS.between(recruitmentStartDate, now);
if (between <= 14) {
club.updateRecruitmentStatus(ClubRecruitmentStatus.UPCOMING);
} else {
club.updateRecruitmentStatus(ClubRecruitmentStatus.CLOSED);
}
} else if (now.isAfter(recruitmentStartDate) && now.isBefore(recruitmentEndDate)) {
club.updateRecruitmentStatus(ClubRecruitmentStatus.OPEN);
} else if (now.isAfter(recruitmentEndDate)) {
club.updateRecruitmentStatus(ClubRecruitmentStatus.CLOSED);
}
if (now.isBefore(recruitmentStartDate)) {
- long between = ChronoUnit.DAYS.between(recruitmentStartDate, now);
+ long between = ChronoUnit.DAYS.between(now, recruitmentStartDate);
if (between <= 14) {
club.updateRecruitmentStatus(ClubRecruitmentStatus.UPCOMING);
} else {
club.updateRecruitmentStatus(ClubRecruitmentStatus.CLOSED);
}

} else {
club.updateRecruitmentStatus(ClubRecruitmentStatus.CLOSED);
}
clubRepository.save(club);
}
}
Comment on lines +22 to +50
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

예외 처리 추가 필요

DB 작업 중 발생할 수 있는 예외에 대한 처리가 없습니다. 스케줄링 작업은 백그라운드에서 실행되므로 예외 처리와 로깅이 특히 중요합니다.

@Scheduled(fixedRate = 60 * 60 * 1000) // 1시간마다 실행
public void performTask() {
+   try {
        List<Club> clubs = clubRepository.findAll();
        for (Club club : clubs) {
            // 기존 로직...
        }
+   } catch (Exception e) {
+       // 로깅 프레임워크 사용 (예: SLF4J)
+       log.error("Club recruitment status update failed", e);
+       // 필요한 경우 알림 시스템에 통보
+   }
}

}
19 changes: 0 additions & 19 deletions backend/src/main/java/moadong/global/config/SchedulerConfig.java

This file was deleted.

Loading