diff --git a/backend/.gitignore b/backend/.gitignore index ea4dc3a..51fab93 100644 --- a/backend/.gitignore +++ b/backend/.gitignore @@ -196,4 +196,4 @@ $RECYCLE.BIN/ !/gradle/wrapper/gradle-wrapper.jar src/main/resources/application.properties -src/main/resources/firebase/worlabel-firbase-key.json \ No newline at end of file +src/main/resources/firebase/worlabel-firebase-key.json \ No newline at end of file diff --git a/backend/src/main/java/com/worlabel/domain/auth/controller/AuthController.java b/backend/src/main/java/com/worlabel/domain/auth/controller/AuthController.java index 82a02f8..06943b5 100644 --- a/backend/src/main/java/com/worlabel/domain/auth/controller/AuthController.java +++ b/backend/src/main/java/com/worlabel/domain/auth/controller/AuthController.java @@ -3,7 +3,7 @@ package com.worlabel.domain.auth.controller; import com.worlabel.domain.auth.entity.dto.FcmTokenRequest; import com.worlabel.domain.auth.entity.dto.JwtToken; import com.worlabel.domain.auth.entity.dto.AccessTokenResponse; -import com.worlabel.domain.auth.repository.FcmRepository; +import com.worlabel.domain.auth.repository.FcmCacheRepository; import com.worlabel.domain.auth.service.AuthService; import com.worlabel.domain.auth.service.JwtTokenService; import com.worlabel.domain.member.entity.dto.MemberResponse; @@ -22,7 +22,6 @@ import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; -import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.web.bind.annotation.*; import java.util.Arrays; @@ -40,7 +39,7 @@ public class AuthController { @Value("${auth.refreshTokenExpiry}") long refreshExpiry; - private final FcmRepository fcmRepository; + private final FcmCacheRepository fcmCacheRepository; private final JwtTokenService jwtTokenService; private final MemberService memberService; private final AuthService authService; @@ -110,7 +109,7 @@ public class AuthController { @SwaggerApiError({ErrorCode.INVALID_TOKEN, ErrorCode.INVALID_REFRESH_TOKEN, ErrorCode.USER_NOT_FOUND}) @PostMapping("/test") public void testSend(@CurrentUser final Integer memberId) { - String token = fcmRepository.getToken(memberId); + String token = fcmCacheRepository.getToken(memberId); fcmService.testSend(token, "test알림입니다."); } diff --git a/backend/src/main/java/com/worlabel/domain/auth/repository/FcmRepository.java b/backend/src/main/java/com/worlabel/domain/auth/repository/FcmCacheRepository.java similarity index 96% rename from backend/src/main/java/com/worlabel/domain/auth/repository/FcmRepository.java rename to backend/src/main/java/com/worlabel/domain/auth/repository/FcmCacheRepository.java index 48a7e62..7fcca13 100644 --- a/backend/src/main/java/com/worlabel/domain/auth/repository/FcmRepository.java +++ b/backend/src/main/java/com/worlabel/domain/auth/repository/FcmCacheRepository.java @@ -9,7 +9,7 @@ import org.springframework.stereotype.Repository; @Slf4j @Repository @RequiredArgsConstructor -public class FcmRepository { +public class FcmCacheRepository { private final RedisTemplate redisTemplate; diff --git a/backend/src/main/java/com/worlabel/domain/auth/service/AuthService.java b/backend/src/main/java/com/worlabel/domain/auth/service/AuthService.java index c5ce860..d4f8b10 100644 --- a/backend/src/main/java/com/worlabel/domain/auth/service/AuthService.java +++ b/backend/src/main/java/com/worlabel/domain/auth/service/AuthService.java @@ -2,15 +2,12 @@ package com.worlabel.domain.auth.service; import com.worlabel.domain.auth.entity.dto.JwtToken; import com.worlabel.domain.auth.repository.AuthCacheRepository; -import com.worlabel.domain.auth.repository.FcmRepository; +import com.worlabel.domain.auth.repository.FcmCacheRepository; import com.worlabel.global.exception.CustomException; import com.worlabel.global.exception.ErrorCode; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; -import org.springframework.util.StringUtils; - -import java.util.Objects; @Slf4j @Service @@ -19,7 +16,7 @@ public class AuthService { private final AuthCacheRepository authCacheRepository; private final JwtTokenService jwtTokenService; - private final FcmRepository fcmRepository;; + private final FcmCacheRepository fcmCacheRepository;; /** * JWT 토큰 재발급 @@ -45,10 +42,10 @@ public class AuthService { } public void saveFcmToken(int memberId, String fcmToken) { - fcmRepository.save(memberId, fcmToken); + fcmCacheRepository.save(memberId, fcmToken); } public void deleteFcmToken(int memberId) { - fcmRepository.delete(memberId); + fcmCacheRepository.delete(memberId); } } diff --git a/backend/src/main/java/com/worlabel/domain/progress/ProgressController.java b/backend/src/main/java/com/worlabel/domain/progress/controller/ProgressController.java similarity index 96% rename from backend/src/main/java/com/worlabel/domain/progress/ProgressController.java rename to backend/src/main/java/com/worlabel/domain/progress/controller/ProgressController.java index 33bc675..da9fe63 100644 --- a/backend/src/main/java/com/worlabel/domain/progress/ProgressController.java +++ b/backend/src/main/java/com/worlabel/domain/progress/controller/ProgressController.java @@ -1,4 +1,4 @@ -package com.worlabel.domain.progress; +package com.worlabel.domain.progress.controller; import com.google.gson.Gson; import com.google.gson.JsonObject; diff --git a/backend/src/main/java/com/worlabel/domain/progress/repository/ProgressCacheRepository.java b/backend/src/main/java/com/worlabel/domain/progress/repository/ProgressCacheRepository.java new file mode 100644 index 0000000..ddebcd9 --- /dev/null +++ b/backend/src/main/java/com/worlabel/domain/progress/repository/ProgressCacheRepository.java @@ -0,0 +1,32 @@ +package com.worlabel.domain.progress.repository; + +import com.worlabel.global.cache.CacheKey; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Repository; + +@Slf4j +@Repository +@RequiredArgsConstructor +public class ProgressCacheRepository { + + private final RedisTemplate redisTemplate; + + /** + * 현재 오토레이블링중인지 확인하는 메서드 + */ + public boolean predictCheck(final int projectId) { + String key = CacheKey.autoLabelingProgressKey(); + Boolean isProgress = redisTemplate.opsForSet().isMember(key, projectId); + return Boolean.TRUE.equals(isProgress); + } + + /** + * 학습 진행 중 등록 메서드 + */ + public void registerPredictProgress(final int projectId) { + String key = CacheKey.autoLabelingProgressKey(); + redisTemplate.opsForSet().add(key, projectId); + } +} diff --git a/backend/src/main/java/com/worlabel/domain/progress/service/ProgressService.java b/backend/src/main/java/com/worlabel/domain/progress/service/ProgressService.java new file mode 100644 index 0000000..aab44ef --- /dev/null +++ b/backend/src/main/java/com/worlabel/domain/progress/service/ProgressService.java @@ -0,0 +1,26 @@ +package com.worlabel.domain.progress.service; + +import com.worlabel.domain.progress.repository.ProgressCacheRepository; +import com.worlabel.global.exception.CustomException; +import com.worlabel.global.exception.ErrorCode; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +@Slf4j +@Service +@RequiredArgsConstructor +public class ProgressService { + + private final ProgressCacheRepository progressCacheRepository; + + public void predictCheck(final int projectId){ + if(progressCacheRepository.predictCheck(projectId)){ + throw new CustomException(ErrorCode.AI_IN_PROGRESS); + } + } + + public void registerPredictProgress(final int projectId){ + progressCacheRepository.registerPredictProgress(projectId); + } +} diff --git a/backend/src/main/java/com/worlabel/domain/project/service/ProjectService.java b/backend/src/main/java/com/worlabel/domain/project/service/ProjectService.java index 4a25039..7d5690b 100644 --- a/backend/src/main/java/com/worlabel/domain/project/service/ProjectService.java +++ b/backend/src/main/java/com/worlabel/domain/project/service/ProjectService.java @@ -16,6 +16,7 @@ import com.worlabel.domain.participant.entity.WorkspaceParticipant; import com.worlabel.domain.participant.entity.dto.ParticipantRequest; import com.worlabel.domain.participant.repository.ParticipantRepository; import com.worlabel.domain.participant.repository.WorkspaceParticipantRepository; +import com.worlabel.domain.progress.service.ProgressService; import com.worlabel.domain.project.dto.AiDto.AutoLabelingImageRequest; import com.worlabel.domain.project.dto.AiDto.AutoLabelingRequest; import com.worlabel.domain.project.dto.AiDto.AutoLabelingResult; @@ -57,11 +58,12 @@ public class ProjectService { private final AiModelRepository aiModelRepository; private final ProjectRepository projectRepository; private final MemberRepository memberRepository; + private final ProgressService progressService; private final S3UploadService s3UploadService; private final ImageRepository imageRepository; private final AiRequestService aiService; - private final RedisTemplate redisTemplate; + private final Gson gson; @Transactional @@ -160,44 +162,29 @@ public class ProjectService { */ @CheckPrivilege(PrivilegeType.EDITOR) public void autoLabeling(final Integer projectId, final AutoModelRequest request) { - autoLabelingProgressCheck(projectId); - - log.debug("project {}", projectId); + progressService.predictCheck(projectId); + Project project = getProject(projectId); String endPoint = project.getProjectType().getValue() + "/predict"; - log.debug("이미지 조회"); List imageList = imageRepository.findImagesByProjectIdAndPending(projectId); List imageRequestList = imageList.stream() .map(AutoLabelingImageRequest::of) .toList(); - log.debug("카테고리 조회 "); HashMap labelMap = getLabelMap(project); - log.debug("모델 조회"); AiModel aiModel = getAiModel(request); AutoLabelingRequest autoLabelingRequest = AutoLabelingRequest.of(projectId, aiModel.getModelKey(), labelMap, imageRequestList); // 응답없음 log.debug("요청"); + progressService.registerPredictProgress(projectId); List list = aiService.postRequest(endPoint, autoLabelingRequest, List.class, this::converter); saveAutoLabelList(list); - - } - - private void autoLabelingProgressCheck(final int projectId) { - String key = CacheKey.autoLabelingProgressKey(); - - Boolean isProgress = redisTemplate.opsForSet().isMember(key, projectId); - if(Boolean.TRUE.equals(isProgress)) { - throw new CustomException(ErrorCode.AI_IN_PROGRESS); - } - - // 학습 진행중으로 등록 - redisTemplate.opsForSet().add(key, projectId); } + // TODO: 트랜잭션 설정 @Transactional public void saveAutoLabelList(final List resultList) { for(AutoLabelingResult result: resultList) { @@ -216,7 +203,6 @@ public class ProjectService { // Gson에서 리스트 형태로 변환할 타입을 지정 Type listType = new TypeToken>() { }.getType(); - // JSON 배열을 List로 변환 return gson.fromJson(data, listType); } catch (JsonSyntaxException e) {