diff --git a/src/main/java/com/example/moizaspringserver/domain/feed/entity/PublicFeed.java b/src/main/java/com/example/moizaspringserver/domain/feed/entity/PublicFeed.java index ab2f1535..2409d519 100644 --- a/src/main/java/com/example/moizaspringserver/domain/feed/entity/PublicFeed.java +++ b/src/main/java/com/example/moizaspringserver/domain/feed/entity/PublicFeed.java @@ -42,6 +42,13 @@ public class PublicFeed extends BaseTimeEntity { @ColumnDefault("0") private Integer likeCount; + @NotNull + @ColumnDefault("0") + private Integer viewCount; + public void addViewCounts(Integer views) { + viewCount += views; + } + @Builder public PublicFeed(String title, String content, Integer likeCount, Feed feed) { this.title = title; diff --git a/src/main/java/com/example/moizaspringserver/domain/feed/facade/ViewCountFacade.java b/src/main/java/com/example/moizaspringserver/domain/feed/facade/ViewCountFacade.java new file mode 100644 index 00000000..abbe95c2 --- /dev/null +++ b/src/main/java/com/example/moizaspringserver/domain/feed/facade/ViewCountFacade.java @@ -0,0 +1,47 @@ +package com.example.moizaspringserver.domain.feed.facade; + +import com.example.moizaspringserver.domain.feed.entity.PublicFeed; +import com.example.moizaspringserver.domain.feed.exception.FeedNotFoundException; +import com.example.moizaspringserver.domain.feed.properties.ViewCountProperties; +import com.example.moizaspringserver.domain.feed.respository.PublicFeedRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +@RequiredArgsConstructor +@Component +public class ViewCountFacade { + + private final ViewCountProperties viewCountProperties; + private final PublicFeedRepository publicFeedRepository; + private final Map viewCounts = new ConcurrentHashMap<>(); + + @Transactional(readOnly = true) + public Integer getViewCountOf(Integer feedId) { + return publicFeedRepository.findById(feedId) + .orElseThrow(() -> FeedNotFoundException.EXCEPTION) + .getViewCount(); + } + + @Transactional + public void flushViewCount(Integer feedId) { + PublicFeed feed = publicFeedRepository.findById(feedId) + .orElseThrow(() -> FeedNotFoundException.EXCEPTION); + + feed.addViewCounts(viewCounts.get(feedId)); + viewCounts.remove(feedId); + } + + @Transactional + public void addViewCountOf(Integer feedId) { + viewCounts.computeIfAbsent(feedId, key -> viewCounts.put(key, 0)); + + viewCounts.put(feedId, viewCounts.get(feedId)); + + if(viewCounts.get(feedId) >= viewCountProperties.getCacheMaximum()) + flushViewCount(feedId); + } +} diff --git a/src/main/java/com/example/moizaspringserver/domain/feed/properties/ViewCountProperties.java b/src/main/java/com/example/moizaspringserver/domain/feed/properties/ViewCountProperties.java new file mode 100644 index 00000000..f90a72cb --- /dev/null +++ b/src/main/java/com/example/moizaspringserver/domain/feed/properties/ViewCountProperties.java @@ -0,0 +1,14 @@ +package com.example.moizaspringserver.domain.feed.properties; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.ConstructorBinding; + +@Getter +@ConstructorBinding +@AllArgsConstructor +@ConfigurationProperties(prefix = "feed.viewcount") +public class ViewCountProperties { + private final Integer cacheMaximum; +} diff --git a/src/main/java/com/example/moizaspringserver/domain/viewcount/entity/FeedViewCount.java b/src/main/java/com/example/moizaspringserver/domain/viewcount/entity/FeedViewCount.java deleted file mode 100644 index c15fdd09..00000000 --- a/src/main/java/com/example/moizaspringserver/domain/viewcount/entity/FeedViewCount.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.example.moizaspringserver.domain.viewcount.entity; - -import lombok.AccessLevel; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; -import org.springframework.data.annotation.Id; -import org.springframework.data.redis.core.RedisHash; - -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@RedisHash -public class FeedViewCount { - - @Id - private Integer feedId; - - private Integer viewCount; - - @Builder - public FeedViewCount(Integer feedId) { - this.feedId = feedId; - this.viewCount = 0; - } -} diff --git a/src/main/java/com/example/moizaspringserver/domain/viewcount/repository/FeedViewCountRepository.java b/src/main/java/com/example/moizaspringserver/domain/viewcount/repository/FeedViewCountRepository.java deleted file mode 100644 index 3b188274..00000000 --- a/src/main/java/com/example/moizaspringserver/domain/viewcount/repository/FeedViewCountRepository.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.example.moizaspringserver.domain.viewcount.repository; - -import com.example.moizaspringserver.domain.viewcount.entity.FeedViewCount; -import org.springframework.data.repository.CrudRepository; - -public interface FeedViewCountRepository extends CrudRepository { - -} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index e7d39fc3..ba099d15 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -36,4 +36,8 @@ aws: access-key : ${SES_ACCESS} secret-key : ${SES_SECRET} ses-source : ${SES_SOURCE} - aws-regions : ${AWS_REGIONS:ap-northeast-2} \ No newline at end of file + aws-regions : ${AWS_REGIONS:ap-northeast-2} + +feed: + viewcount: + cache-maximum: ${VIEWCOUNT_CACHE_MAXIMUM}