Skip to content

Commit

Permalink
Refactor: UserImageScheduler 기능 수정[박한솔]
Browse files Browse the repository at this point in the history
  • Loading branch information
pjhcsols committed May 4, 2024
1 parent 901d6fd commit c760e7d
Show file tree
Hide file tree
Showing 11 changed files with 208 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,13 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

@Component
@Slf4j
@Component
public class ProductImageScheduler {
private final ProductService productService;
private final S3StorageService s3StorageService;
Expand All @@ -25,11 +24,11 @@ public ProductImageScheduler(ProductService productService, S3StorageService s3S
}


//@Scheduled(cron = "0 0 0 * * ?") // 매일 자정마다 실행
//@Scheduled(initialDelay = 60000, fixedDelay = 120000) // 1분 후에 시작하고, 그 이후에는 매 2분마다 실행
@Transactional
@Scheduled(initialDelay = 60000, fixedDelay = 120000) // 1분 후에 시작하고, 그 이후에는 매 2분마다 실행
@Scheduled(cron = "0 0 0 * * ?") // 매일 자정마다 실행
public void deleteUnusedProductImages() {
log.info("product 스케줄링 시작");
log.info("[product 스케줄링 시작]");
// 1. 데이터베이스와 S3 스토리지에서 상품 이미지 URL을 가져옵니다.
List<String> databaseUrls = productService.getAllProductImageUrls();
List<String> s3Urls = s3StorageService.getAllImageUrls();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,161 @@
package basilium.basiliumserver.batchJobScheduler;

import basilium.basiliumserver.domain.user.BrandUser;
import basilium.basiliumserver.domain.user.NormalUser;
import basilium.basiliumserver.domain.user.SuperUser;
import basilium.basiliumserver.domain.user.User;
import jakarta.persistence.EntityManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import basilium.basiliumserver.domain.user.BrandUser;
import basilium.basiliumserver.domain.user.NormalUser;
import basilium.basiliumserver.domain.user.SuperUser;
import basilium.basiliumserver.repository.user.BrandUserRepository;
import basilium.basiliumserver.repository.user.NormalUserRepository;
import basilium.basiliumserver.repository.user.SuperUserRepository;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Slf4j
@Component
public class UserImageScheduler {

@Autowired
private EntityManager em;

@Autowired
private NormalUserRepository normalUserRepository;
@Autowired
private BrandUserRepository brandUserRepository;
@Autowired
private SuperUserRepository superUserRepository;

@Value("${uploadDir}")
private String uploadDir;

@Transactional
@Scheduled(fixedRate = 24 * 60 * 60 * 1000) // 서버시작시간기준, 24시간마다 실행
public void deleteUnusedImages() {
log.info("************************************************************************************");
log.info("[ [user Image] 스케줄링 시작]");

// 디렉토리에 존재하는 이미지 파일과 데이터베이스에 저장된 모든 이미지 URL 가져오기
Set<String> directoryImageUrls = getDirectoryImageUrls();
Set<String> dbImageUrls = getAllUserImageUrls();
log.info("userImageStorage urls: {}", directoryImageUrls);
log.info("db urls: {}", dbImageUrls);

// 1. 디렉토리에 있는 이미지 파일 중에서 데이터베이스에 없는 파일 삭제
log.info("1. 디렉토리에 있는 이미지 파일 중에서 DB에 없는 파일 삭제");
Set<String> filesToDelete = directoryImageUrls.stream()
.filter(fileName -> !dbImageUrls.contains(fileName))
.collect(Collectors.toSet());

log.info("교차검증: DB에 없는 디렉토리의 이미지 URL 목록(차집합)");
log.info(String.valueOf(filesToDelete));

for (String fileName : filesToDelete) {
deleteImageFile(fileName);
}

// 2. 디렉토리의 파일을 URL로 추출하고,
// 데이터베이스의 각 사용자의 이미지 URL과 비교하여 일치하는 것은 그대로 두고, 데이터베이스에만 있는 이미지 URL을 null로 변경
log.info("2. 데이터베이스에만 있는 이미지 URL을 null로 변경");
updateDatabaseUserImageUrls(directoryImageUrls, dbImageUrls);
log.info("[user Image] 스케줄링 완료");
log.info("************************************************************************************");
}

private Set<String> getDirectoryImageUrls() {
// 디렉토리에 있는 모든 이미지 파일의 URL을 가져와야 함
Set<String> directoryImageUrls = new HashSet<>();
File folder = new File(uploadDir);
File[] listOfFiles = folder.listFiles();
if (listOfFiles != null) {
for (File file : listOfFiles) {
if (file.isFile()) {
directoryImageUrls.add(uploadDir + file.getName()); // uploadDir과 파일명을 합쳐서 전체 경로를 추가
}
}
}
return directoryImageUrls;
}

private Set<String> getAllUserImageUrls() {
// 데이터베이스에 저장된 모든 이미지 URL을 가져오는 메서드
Set<String> allUserImageUrls = new HashSet<>();
allUserImageUrls.addAll(normalUserRepository.getAllUserImageUrls());
allUserImageUrls.addAll(brandUserRepository.getAllUserImageUrls());
allUserImageUrls.addAll(superUserRepository.getAllUserImageUrls());
return allUserImageUrls;
}

private void deleteImageFile(String fileName) {
// 디렉토리에서 이미지 파일을 삭제하는 메서드
String imagePath = fileName;
//log.info(imagePath);
File imageFile = new File(imagePath);
if (imageFile.exists()) {
if (imageFile.delete()) {
log.info("이미지 파일 삭제 성공: {}", fileName);
} else {
log.error("이미지 파일 삭제 실패: {}", fileName);
}
} else {
log.warn("삭제할 이미지 파일이 존재하지 않습니다: {}", fileName);
}
}

private void updateDatabaseUserImageUrls(Set<String> directoryImageUrls, Set<String> dbImageUrls) {
// 데이터베이스에만 있는 이미지 URL을 null로 변경하는 메서드
Set<String> dbOnlyImageUrls = dbImageUrls.stream()
.filter(url -> !directoryImageUrls.contains(url))
.collect(Collectors.toSet());
log.info("교차검증: 디렉토리에 없는 DB 이미지 URL 목록(차집합)");
log.info(String.valueOf(dbOnlyImageUrls));//dbOnlyImageUrls

// 노말 유저의 이미지 URL을 null로 변경
List<NormalUser> normalUsersToUpdate = normalUserRepository.findByUserImageUrlsIn(dbOnlyImageUrls);
updateImageUrlsToNull(normalUsersToUpdate);

// 브랜드 유저의 이미지 URL을 null로 변경
List<BrandUser> brandUsersToUpdate = brandUserRepository.findByUserImageUrlsIn(dbOnlyImageUrls);
updateImageUrlsToNull(brandUsersToUpdate);

// 어드민 유저의 이미지 URL을 null로 변경
List<SuperUser> superUsersToUpdate = superUserRepository.findByUserImageUrlsIn(dbOnlyImageUrls);
updateImageUrlsToNull(superUsersToUpdate);

}

//@Transactional
protected void updateImageUrlsToNull(List<? extends User> usersToUpdate) {
for (User user : usersToUpdate) {
if (user instanceof NormalUser) {
NormalUser normalUser = (NormalUser) user;
normalUser.setUserImageUrl(null);
em.persist(normalUser);
} else if (user instanceof BrandUser) {
BrandUser brandUser = (BrandUser) user;
brandUser.setUserImageUrl(null);
em.persist(brandUser);
} else if (user instanceof SuperUser) {
SuperUser superUser = (SuperUser) user;
superUser.setUserImageUrl(null);
em.persist(superUser);
}
}
}

}

/*
@Slf4j
@Component
public class UserImageScheduler {
Expand All @@ -32,6 +173,7 @@ public class UserImageScheduler {
@Scheduled(fixedRate = 24 * 60 * 60 * 1000) // 24시간마다 실행
public void deleteOldImagesAndUrls() {
log.info("UserImageScheduler 스케줄링 시작");
// 사용자 URL 전체 삭제
Iterable<NormalUser> normalUsers = normalUserRepository.getAllNormalUsers();
for (NormalUser user : normalUsers) {
Expand Down Expand Up @@ -60,4 +202,6 @@ public void deleteOldImagesAndUrls() {
}
}
}
}
}
*/
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import java.util.List;
import java.util.Optional;
import java.util.Set;

public interface BrandUserRepository {
long count();
Expand All @@ -14,4 +15,6 @@ public interface BrandUserRepository {
BrandUser save(BrandUser brandUser);
Optional<BrandUser> findById(String id);
Optional<BrandUser> findByEmail(String emailAddress);
List<String> getAllUserImageUrls();
List<BrandUser> findByUserImageUrlsIn(Set<String> imageUrls);
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

import java.util.List;
import java.util.Optional;
import java.util.Set;

@Slf4j
@Repository
Expand All @@ -36,6 +37,18 @@ public BrandUser save(BrandUser brandUser) {
return brandUser;
}

@Override
public List<String> getAllUserImageUrls() {
return em.createQuery("SELECT m.userImageUrl FROM BrandUser m", String.class).getResultList();
}

@Override
public List<BrandUser> findByUserImageUrlsIn(Set<String> imageUrls) {
return em.createQuery("SELECT u FROM BrandUser u WHERE u.userImageUrl IN :imageUrls", BrandUser.class)
.setParameter("imageUrls", imageUrls)
.getResultList();
}

@Override
public Optional<BrandUser> findById(String id) {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import java.util.List;
import java.util.Optional;
import java.util.Set;

@Slf4j
@Repository
Expand Down Expand Up @@ -36,6 +37,18 @@ public NormalUser save(NormalUser normalUser) {
return normalUser;
}

@Override
public List<String> getAllUserImageUrls() {
return em.createQuery("SELECT m.userImageUrl FROM NormalUser m", String.class).getResultList();
}

@Override
public List<NormalUser> findByUserImageUrlsIn(Set<String> imageUrls) {
return em.createQuery("SELECT u FROM NormalUser u WHERE u.userImageUrl IN :imageUrls", NormalUser.class)
.setParameter("imageUrls", imageUrls)
.getResultList();
}


@Override
public Optional<NormalUser> findById(String id) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

import java.util.List;
import java.util.Optional;
import java.util.Set;

@Slf4j
@Repository
Expand All @@ -30,12 +31,24 @@ public List<SuperUser> getAllSuperUsers() {
return em.createQuery("SELECT m FROM SuperUser m", SuperUser.class).getResultList();
}

@Override
public List<SuperUser> findByUserImageUrlsIn(Set<String> imageUrls) {
return em.createQuery("SELECT u FROM SuperUser u WHERE u.userImageUrl IN :imageUrls", SuperUser.class)
.setParameter("imageUrls", imageUrls)
.getResultList();
}

@Override
public SuperUser save(SuperUser superUser) {
em.persist(superUser);
return superUser;
}

@Override
public List<String> getAllUserImageUrls() {
return em.createQuery("SELECT m.userImageUrl FROM SuperUser m", String.class).getResultList();
}

@Override
public Optional<SuperUser> findById(String id) {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import java.util.List;
import java.util.Optional;
import java.util.Set;

public interface NormalUserRepository {
long count();
Expand All @@ -18,4 +19,6 @@ public interface NormalUserRepository {
List<NormalUser> findByName(String name);
Optional<NormalUser> findByPhoneNumber(String phoneNumber);
//List<NormalUser> findAll();
List<String> getAllUserImageUrls();
List<NormalUser> findByUserImageUrlsIn(Set<String> imageUrls);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import java.util.List;
import java.util.Optional;
import java.util.Set;

public interface SuperUserRepository {
long count();
Expand All @@ -13,4 +14,6 @@ public interface SuperUserRepository {
SuperUser save(SuperUser superUser);
Optional<SuperUser> findById(String id);
Optional<SuperUser> findByEmail(String emailAddress);
List<String> getAllUserImageUrls();
List<SuperUser> findByUserImageUrlsIn(Set<String> imageUrls);
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ public String uploadProductPhoto(MultipartFile file) throws IOException {
*/

//브랜드 유저 id가 없으면 실행안됨
public String uploadProductPhoto(MultipartFile file, BrandUser brandUser) throws IOException {
String fileName = brandUser.getId() + "_" + System.currentTimeMillis() + "_" + file.getOriginalFilename();
byte[] fileBytes = file.getBytes();
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 7 additions & 1 deletion basilium-server/src/main/resources/data.sql
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,13 @@ INSERT INTO basilium.category (category_id, category_name) VALUES (19, '액세
commit;

INSERT INTO brand_user (user_number, id, password, email_address, phone_number, user_grade, login_type, user_image_url, firm_name, firm_address, business_registration, firm_web_url)
VALUES (1,'brand01', '1q2w3e4r!R', 'example@naver.com', '010-1234-5678', 0, 1, '/Users/hansol/Desktop/VirtualFitting_System/basilium-server/src/main/java/basilium/basiliumserver/userImageStorage/example_1713958965868_mysql.png', '박한솔컴퍼니', '대구광역시 달서구 저승길 6길', '20-17777777', 'http://phs-컴퍼니');
VALUES (1,'brand01', '1q2w3e4r!R', 'example@naver.com', '010-1234-5678', 0, 1, '/Users/hansol/Desktop/VirtualFitting_System/basilium-server/src/main/java/basilium/basiliumserver/userImageStorage/brand01_1713958965868_mysql.png', '박한솔컴퍼니', '대구광역시 달서구 저승길 6길', '20-17777777', 'http://phs-컴퍼니');
commit;
INSERT INTO brand_user (user_number, id, password, email_address, phone_number, user_grade, login_type, user_image_url, firm_name, firm_address, business_registration, firm_web_url)
VALUES (2,'brand02', '1q2w3e4r!R', 'example2@naver.com', '010-1234-5678', 0, 1, '/Users/hansol/user2번스케줄링_테스트_날라가야_정상.png', '박한솔컴퍼니', '대구광역시 달서구 저승길 6길', '20-17777777', 'http://phs-컴퍼니');
commit;
INSERT INTO normal_user (user_number, id, password, email_address, phone_number, user_grade, login_type, user_image_url, name, birth_date, address)
VALUES (1, 'example', '1q2w3e4r!R', 'example@naver.com', '010-1234-5678', 0, 0,'/Users/hansol/Desktop/VirtualFitting_System/basilium-server/src/main/java/basilium/basiliumserver/userImageStorage/example_1713958965868_mysql.png', '우정잉', '2000-12-20', '서울특별시 강남구');
commit;

INSERT INTO product (product_id, category_id, product_name, product_price, product_desc, brand_user_number)
Expand Down

0 comments on commit c760e7d

Please sign in to comment.