From a97f5eb071c1c463f7c715038796f125f95350cf Mon Sep 17 00:00:00 2001 From: sohyundoh Date: Sun, 20 Oct 2024 16:49:39 +0900 Subject: [PATCH 1/4] =?UTF-8?q?#538=20[feat]=20cache=EC=97=90=20NUll=20?= =?UTF-8?q?=EA=B0=92=20=EC=A0=80=EC=9E=A5=20=EB=B6=88=EA=B0=80=ED=95=98?= =?UTF-8?q?=EA=B2=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/mile/common/config/CacheConfig.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/module-domain/src/main/java/com/mile/common/config/CacheConfig.java b/module-domain/src/main/java/com/mile/common/config/CacheConfig.java index 32e8ab0d..1980b1e2 100644 --- a/module-domain/src/main/java/com/mile/common/config/CacheConfig.java +++ b/module-domain/src/main/java/com/mile/common/config/CacheConfig.java @@ -18,7 +18,10 @@ public class CacheConfig { @Bean public CacheManager cacheManager() { CaffeineCacheManager cacheManager = new CaffeineCacheManager(); - cacheManager.setCaffeine(caffeineConfig()); + cacheManager + .setAllowNullValues(false); + cacheManager + .setCaffeine(caffeineConfig()); return cacheManager; } From da4ebdfe7e8a793b345f52424792f2ff67712d71 Mon Sep 17 00:00:00 2001 From: sohyundoh Date: Sun, 20 Oct 2024 16:50:50 +0900 Subject: [PATCH 2/4] =?UTF-8?q?#538=20[feat]=20=EC=9D=B8=EA=B8=B0=EA=B8=80?= =?UTF-8?q?=20=EC=A1=B0=ED=9A=8C=EC=97=90=20=EB=B6=84=EC=82=B0=EB=9D=BD=20?= =?UTF-8?q?=EB=8F=84=EC=9E=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/MoimPopularInfoRepository.java | 4 +- .../lock/AtomicValidateMoimPopulerInfo.java | 12 ++++ .../service/lock/MoimPopularInfoAspect.java | 49 +++++++++++++++ .../popular/MoimPopularInfoRegister.java | 60 +++++++++++++++++++ .../popular/MoimPopularInfoService.java | 43 +------------ 5 files changed, 125 insertions(+), 43 deletions(-) create mode 100644 module-domain/src/main/java/com/mile/moim/service/lock/AtomicValidateMoimPopulerInfo.java create mode 100644 module-domain/src/main/java/com/mile/moim/service/lock/MoimPopularInfoAspect.java create mode 100644 module-domain/src/main/java/com/mile/moim/service/popular/MoimPopularInfoRegister.java diff --git a/module-domain/src/main/java/com/mile/moim/repository/MoimPopularInfoRepository.java b/module-domain/src/main/java/com/mile/moim/repository/MoimPopularInfoRepository.java index 64808e95..5de7304c 100644 --- a/module-domain/src/main/java/com/mile/moim/repository/MoimPopularInfoRepository.java +++ b/module-domain/src/main/java/com/mile/moim/repository/MoimPopularInfoRepository.java @@ -1,16 +1,16 @@ package com.mile.moim.repository; import com.mile.moim.domain.popular.MoimPopularInfo; +import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.repository.Repository; import org.springframework.scheduling.annotation.Scheduled; import java.util.Optional; -public interface MoimPopularInfoRepository extends Repository { +public interface MoimPopularInfoRepository extends JpaRepository { Optional findByMoimId(final long moimId); - MoimPopularInfo save(final MoimPopularInfo moimPopularInfo); @Scheduled(cron = "59 59 23 * * SUN") void deleteAll(); diff --git a/module-domain/src/main/java/com/mile/moim/service/lock/AtomicValidateMoimPopulerInfo.java b/module-domain/src/main/java/com/mile/moim/service/lock/AtomicValidateMoimPopulerInfo.java new file mode 100644 index 00000000..6be34794 --- /dev/null +++ b/module-domain/src/main/java/com/mile/moim/service/lock/AtomicValidateMoimPopulerInfo.java @@ -0,0 +1,12 @@ +package com.mile.moim.service.lock; + + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface AtomicValidateMoimPopulerInfo { +} diff --git a/module-domain/src/main/java/com/mile/moim/service/lock/MoimPopularInfoAspect.java b/module-domain/src/main/java/com/mile/moim/service/lock/MoimPopularInfoAspect.java new file mode 100644 index 00000000..920ce941 --- /dev/null +++ b/module-domain/src/main/java/com/mile/moim/service/lock/MoimPopularInfoAspect.java @@ -0,0 +1,49 @@ +package com.mile.moim.service.lock; + +import com.mile.exception.message.ErrorMessage; +import com.mile.exception.model.MileException; +import com.mile.moim.domain.Moim; +import lombok.RequiredArgsConstructor; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.redisson.api.RLock; +import org.redisson.api.RedissonClient; +import org.springframework.stereotype.Component; + +import java.util.concurrent.TimeUnit; + +@Aspect +@RequiredArgsConstructor +@Component +public class MoimPopularInfoAspect { + + private final RedissonClient redissonClient; + private final static String MOIM_POPULAR_LOCK = "MOIM_POPULAR_LOCK : "; + private final AopForTransaction aopForTransaction; + + @Pointcut("@annotation(com.mile.moim.service.lock.AtomicValidateMoimPopulerInfo)") + public void setMoimPoplarInfoCut() { + } + + @Around("setMoimPoplarInfoCut()") + public Object getLockForPopularInfoTransaction(final ProceedingJoinPoint joinPoint) throws Throwable { + final Moim moim = (Moim) joinPoint.getArgs()[0]; + + final RLock lock = redissonClient.getLock(MOIM_POPULAR_LOCK + moim.getId().toString()); + + try { + checkAvailability(lock.tryLock(3, 4, TimeUnit.SECONDS)); + return aopForTransaction.proceed(joinPoint); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } finally { + lock.unlock(); + } + } + + public void checkAvailability(final Boolean available) { + if (!available) throw new MileException(ErrorMessage.TIME_OUT_EXCEPTION); + } +} diff --git a/module-domain/src/main/java/com/mile/moim/service/popular/MoimPopularInfoRegister.java b/module-domain/src/main/java/com/mile/moim/service/popular/MoimPopularInfoRegister.java new file mode 100644 index 00000000..ef9b2c89 --- /dev/null +++ b/module-domain/src/main/java/com/mile/moim/service/popular/MoimPopularInfoRegister.java @@ -0,0 +1,60 @@ +package com.mile.moim.service.popular; + +import com.mile.curious.repository.dto.PostAndCuriousCountInLastWeek; +import com.mile.curious.service.CuriousRetriever; +import com.mile.moim.domain.Moim; +import com.mile.moim.domain.popular.MoimCuriousPost; +import com.mile.moim.domain.popular.MoimCuriousWriter; +import com.mile.moim.domain.popular.MoimPopularInfo; +import com.mile.moim.repository.MoimPopularInfoRepository; +import com.mile.moim.service.lock.AtomicValidateMoimPopulerInfo; +import com.mile.writername.domain.WriterName; +import lombok.RequiredArgsConstructor; +import org.springframework.cache.annotation.CachePut; +import org.springframework.stereotype.Component; + +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@RequiredArgsConstructor +@Component +public class MoimPopularInfoRegister { + private final MoimPopularInfoRepository moimPopularInfoRepository; + + private final CuriousRetriever curiousRetriever; + + + private List getMoimCuriousPost(final List mostCuriousPostsInLastWeek) { + return mostCuriousPostsInLastWeek.stream().map(p -> + MoimCuriousPost.of(p.getPost())).limit(2).toList(); + } + + private List getMoimCuriousWriter(final List mostCuriousPostsInLastWeek) { + Map writerNameCount = mostCuriousPostsInLastWeek.stream() + .collect(Collectors.groupingBy(p -> p.getPost().getWriterName(), Collectors.summingLong(PostAndCuriousCountInLastWeek::getCount))); + + List topTwoWriters = writerNameCount.entrySet().stream() + .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())) + .limit(2) + .map(Map.Entry::getKey).toList(); + + return topTwoWriters.stream().map(MoimCuriousWriter::of).toList(); + } + + @CachePut(value = "moimPopularInfo", key = "#moim.id") + @AtomicValidateMoimPopulerInfo + public MoimPopularInfo setMostPopularInfoOfMoim(final Moim moim) { + List mostCuriousPostsInLastWeek = curiousRetriever.findMostCuriousPostsInLastWeek(moim); + + List moimCuriousPosts = getMoimCuriousPost(mostCuriousPostsInLastWeek); + + List moimCuriousWriters = getMoimCuriousWriter(mostCuriousPostsInLastWeek); + + MoimPopularInfo moimPopularInfo = MoimPopularInfo.of(moim.getId(), moimCuriousPosts, moimCuriousWriters); + + return moimPopularInfoRepository.saveAndFlush(moimPopularInfo); + } + +} diff --git a/module-domain/src/main/java/com/mile/moim/service/popular/MoimPopularInfoService.java b/module-domain/src/main/java/com/mile/moim/service/popular/MoimPopularInfoService.java index e421deb8..205fe749 100644 --- a/module-domain/src/main/java/com/mile/moim/service/popular/MoimPopularInfoService.java +++ b/module-domain/src/main/java/com/mile/moim/service/popular/MoimPopularInfoService.java @@ -1,63 +1,24 @@ package com.mile.moim.service.popular; -import com.mile.curious.repository.dto.PostAndCuriousCountInLastWeek; -import com.mile.curious.service.CuriousRetriever; import com.mile.moim.domain.Moim; -import com.mile.moim.domain.popular.MoimCuriousPost; -import com.mile.moim.domain.popular.MoimCuriousWriter; import com.mile.moim.domain.popular.MoimPopularInfo; import com.mile.moim.repository.MoimPopularInfoRepository; -import com.mile.writername.domain.WriterName; import lombok.AccessLevel; import lombok.RequiredArgsConstructor; -import org.springframework.cache.annotation.CachePut; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - @Service @RequiredArgsConstructor(access = AccessLevel.PROTECTED) public class MoimPopularInfoService { private final MoimPopularInfoRepository moimPopularInfoRepository; - private final CuriousRetriever curiousRetriever; - - @CachePut(value = "moimPopularInfo", key = "#moim.id") - public MoimPopularInfo setMostPopularInfoOfMoim(final Moim moim) { - List mostCuriousPostsInLastWeek = curiousRetriever.findMostCuriousPostsInLastWeek(moim); - - List moimCuriousPosts = getMoimCuriousPost(mostCuriousPostsInLastWeek); - - List moimCuriousWriters = getMoimCuriousWriter(mostCuriousPostsInLastWeek); - - MoimPopularInfo moimPopularInfo = MoimPopularInfo.of(moim.getId(), moimCuriousPosts, moimCuriousWriters); - - return moimPopularInfoRepository.save(moimPopularInfo); - } - - private List getMoimCuriousPost(final List mostCuriousPostsInLastWeek) { - return mostCuriousPostsInLastWeek.stream().map(p -> - MoimCuriousPost.of(p.getPost())).limit(2).toList(); - } + private final MoimPopularInfoRegister moimPopularInfoRegister; - private List getMoimCuriousWriter(final List mostCuriousPostsInLastWeek) { - Map writerNameCount = mostCuriousPostsInLastWeek.stream() - .collect(Collectors.groupingBy(p -> p.getPost().getWriterName(), Collectors.summingLong(PostAndCuriousCountInLastWeek::getCount))); - - List topTwoWriters = writerNameCount.entrySet().stream() - .sorted(Map.Entry.comparingByValue()) - .limit(2) - .map(Map.Entry::getKey).toList(); - - return topTwoWriters.stream().map(MoimCuriousWriter::of).toList(); - } @Cacheable(value = "moimPopularInfo", key = "#moim.id") public MoimPopularInfo getMoimPopularInfo(final Moim moim) { return moimPopularInfoRepository.findByMoimId(moim.getId()).orElseGet( - () -> setMostPopularInfoOfMoim(moim) + () -> moimPopularInfoRegister.setMostPopularInfoOfMoim(moim) ); } From da309a6fc42d1fa6da198aa99e6df8fbce9b2866 Mon Sep 17 00:00:00 2001 From: sohyundoh Date: Sun, 20 Oct 2024 16:51:25 +0900 Subject: [PATCH 3/4] =?UTF-8?q?#538=20[feat]=20S3=20=EA=B4=80=EB=A0=A8=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitattributes | 1 + .../src/main/java/com/mile/moim/service/MoimService.java | 1 - module-external/src/main/java/com/mile/aws/utils/S3Service.java | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..1b0bc892 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +./module-external/src/main/java/com/mile/aws/utils/S3Service merge=ours \ No newline at end of file diff --git a/module-domain/src/main/java/com/mile/moim/service/MoimService.java b/module-domain/src/main/java/com/mile/moim/service/MoimService.java index e82c9b68..2d5fe021 100644 --- a/module-domain/src/main/java/com/mile/moim/service/MoimService.java +++ b/module-domain/src/main/java/com/mile/moim/service/MoimService.java @@ -68,7 +68,6 @@ public class MoimService { private final MoimRetriever moimRetriever; private final MoimCreator moimCreator; private final WriterNameRemover writerNameRemover; - private final CuriousRetriever curiousRetriever; private final TopicRemover topicRemover; private final TopicRetriever topicRetriever; private final TopicCreator topicCreator; diff --git a/module-external/src/main/java/com/mile/aws/utils/S3Service.java b/module-external/src/main/java/com/mile/aws/utils/S3Service.java index 2101e55e..e95e9663 100644 --- a/module-external/src/main/java/com/mile/aws/utils/S3Service.java +++ b/module-external/src/main/java/com/mile/aws/utils/S3Service.java @@ -27,7 +27,7 @@ @Component public class S3Service { - private static final Long PRE_SIGNED_URL_EXPIRE_MINUTE = 120L; // 만료시간 2시간 + private static final Long PRE_SIGNED_URL_EXPIRE_MINUTE = 1L; // 만료시간 2시간 private final String bucketName; private final AwsConfig awsConfig; From 6e15bab06397bc2eecd01731ea3ccfaf54f4a718 Mon Sep 17 00:00:00 2001 From: sohyundoh Date: Sun, 20 Oct 2024 16:53:55 +0900 Subject: [PATCH 4/4] =?UTF-8?q?#538=20[feat]=20=EC=BA=90=EC=8B=9C=20?= =?UTF-8?q?=EC=9C=A0=ED=9A=A8=EA=B8=B0=EA=B0=84=201=EC=9D=BC=EB=A1=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/mile/common/config/CacheConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module-domain/src/main/java/com/mile/common/config/CacheConfig.java b/module-domain/src/main/java/com/mile/common/config/CacheConfig.java index 1980b1e2..c8d0104d 100644 --- a/module-domain/src/main/java/com/mile/common/config/CacheConfig.java +++ b/module-domain/src/main/java/com/mile/common/config/CacheConfig.java @@ -35,7 +35,7 @@ private Scheduler getScheduler() { private Caffeine caffeineConfig() { return Caffeine.newBuilder() .maximumSize(200) - .expireAfterAccess(5, TimeUnit.DAYS) + .expireAfterAccess(1, TimeUnit.DAYS) .scheduler(getScheduler()); } }