Fix: 트랜잭션 처리

This commit is contained in:
김용수 2024-09-29 21:09:11 +09:00
parent b94420a91f
commit 8649ae0a67
3 changed files with 27 additions and 16 deletions

View File

@ -11,7 +11,6 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
@ -30,19 +29,18 @@ public class ImageAsyncService {
@Async("imageUploadExecutor")
@Transactional(propagation = Propagation.REQUIRES_NEW)
public CompletableFuture<Void> asyncImageUpload(final List<MultipartFile> imageFileList, final Folder folder, final Integer projectId) {
public CompletableFuture<Void> asyncImageUpload(final List<MultipartFile> imageFileList, final Folder folder, final Integer projectId) {
log.debug("현재 스레드 - {} 업로드 파일 개수 - {}, 현재 작업 큐 용량 - {}",
Thread.currentThread().getName(),
imageFileList.size(),
imageUploadExecutor.getThreadPoolExecutor().getQueue().size()); // 큐에 쌓인 작업 출력);
imageUploadExecutor.getThreadPoolExecutor().getQueue().size()
); // 큐에 쌓인 작업 출력);
imageFileList.forEach(file -> {
try{
String extension = getExtension(file.getOriginalFilename());
String imageKey = s3UploadService.uploadImageFile(file, extension, projectId);
try {
String imageKey = imageUpload(projectId, file);
createImage(file, imageKey, folder);
}catch (Exception e){
} catch (Exception e) {
log.error("이미지 업로드 실패: {}", file.getOriginalFilename(), e);
throw new CustomException(ErrorCode.FAIL_TO_CREATE_FILE);
}
@ -52,15 +50,19 @@ public class ImageAsyncService {
return CompletableFuture.completedFuture(null);
}
@Transactional(propagation = Propagation.REQUIRES_NEW,isolation = Isolation.READ_COMMITTED)
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public String imageUpload(Integer projectId, MultipartFile file) {
String extension = getExtension(file.getOriginalFilename());
return s3UploadService.uploadImageFile(file, extension, projectId);
}
public void createImage(MultipartFile file, String imageKey, Folder folder) {
try {
String name = file.getOriginalFilename();
String extension = getExtension(name);
log.debug("image 파일 {} {} {} {}", name, extension, imageKey, folder.getId());
Image image = Image.of(name, imageKey, extension, folder);
imageRepository.save(image);
}catch (Exception e){
} catch (Exception e) {
log.debug("이미지 DB 저장 실패: ", e);
s3UploadService.deleteImageFromS3(imageKey);
throw new CustomException(ErrorCode.FAIL_TO_CREATE_FILE);

View File

@ -40,7 +40,6 @@ import java.util.stream.Stream;
@Slf4j
@Service
@Transactional
@RequiredArgsConstructor
public class ImageService {
@ -56,9 +55,8 @@ public class ImageService {
@CheckPrivilege(value = PrivilegeType.EDITOR)
public void uploadImageList(final List<MultipartFile> imageList, final Integer folderId, final Integer projectId) {
Folder folder = getOrCreateFolder(folderId, projectId);
folderRepository.flush();
log.debug("folder Id {}, Project Id {}",folder.getId(), folder.getProject().getId());
log.debug("folder Id {}, Project Id {}", folder.getId(), folder.getProject().getId());
long prev = System.currentTimeMillis();
// 동적 배치 크기 계산
@ -78,7 +76,6 @@ public class ImageService {
List<MultipartFile> batch = imageList.subList(i, Math.min(i + batchSize, imageList.size()));
CompletableFuture<Void> future = imageAsyncService.asyncImageUpload(batch, folder, projectId);
// 모든 비동기 작업이 완료될 때까지 기다림
futures.add(future);
}
@ -308,7 +305,8 @@ public class ImageService {
String currentDateTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
Project project = getProject(projectId);
Folder folder = Folder.of(currentDateTime, null, project);
folderRepository.save(folder); // 새로운 폴더를 저장
folderRepository.saveAndFlush(folder); // 새로운 폴더를 저장
return folder;
}
}

View File

@ -1,6 +1,7 @@
package com.worlabel.domain.project.entity;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.worlabel.domain.folder.entity.Folder;
import com.worlabel.domain.labelcategory.entity.ProjectCategory;
import com.worlabel.domain.model.entity.AiModel;
import com.worlabel.domain.workspace.entity.Workspace;
@ -54,6 +55,12 @@ public class Project extends BaseEntity {
@OneToMany(mappedBy = "project", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
private List<ProjectCategory> categoryList = new ArrayList<>();
/**
* 프로젝트에 속한 폴더
*/
@OneToMany(mappedBy = "project", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
private List<Folder> folderList = new ArrayList<>();
/**
* 프로젝트에 속한 모델
*/
@ -74,4 +81,8 @@ public class Project extends BaseEntity {
this.title = title;
this.projectType = projectType;
}
public void createFolder(final Folder folder) {
folderList.add(folder);
}
}