Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ dependencies {

// firebase
implementation 'com.google.firebase:firebase-admin:9.1.0'

// jackson LocalDateTime 직렬화
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310'
}

tasks.named('test') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
Expand All @@ -13,6 +14,7 @@
import jakarta.annotation.PostConstruct;


@EnableCaching
@EnableScheduling
@EnableJpaAuditing
@EnableJpaRepositories(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import java.util.stream.Collectors;

import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.scheduling.annotation.Scheduled;
Expand All @@ -36,8 +37,16 @@ public class PlaceCategoryLogScheduler {
private final PlaceCategoryRepository placeCategoryRepository;

@Scheduled(cron = "${scheduler.logs.place-category.sync-cron}") // 매 5분마다
@CacheEvict(
value = "place-category-log",
key = "'weekly:' + T(java.time.LocalDate).now().getYear() + '-' + T(java.time.temporal.WeekFields).ISO.weekOfYear().getFrom(T(java.time.LocalDate).now())",
cacheManager = "redisCacheManager",
beforeInvocation = false
)
public void syncPlaceCategoryLogsToDB() {

log.info("[PlaceCategoryLogScheduler] 동기화 스케쥴러 동작");

// 현재 날짜 및 레디스 키 생성
LocalDate now = LocalDate.from(LocalDateTime.now().minusMinutes(1));
String formattedDate = now.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.time.LocalDate;
import java.util.List;

import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.withtime.be.withtimebe.domain.log.placecategorylog.model.PlaceCategoryLog;
Expand All @@ -19,6 +20,11 @@ public class PlaceCategoryLogQueryServiceImpl implements PlaceCategoryLogQuerySe
private final PlaceCategoryLogRepository placeCategoryLogRepository;

@Override
@Cacheable(
value = "place-category-log",
key = "'weekly:' + T(java.time.LocalDate).now().getYear() + '-' + T(java.time.temporal.WeekFields).ISO.weekOfYear().getFrom(T(java.time.LocalDate).now())",
cacheManager = "redisCacheManager"
)
public List<PlaceCategoryLog> findWeeklyPlaceCategoryLogList() {

LocalDate now = LocalDate.now();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.withtime.be.withtimebe.global.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.jsontype.BasicPolymorphicTypeValidator;
import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;

@Configuration
public class MapperConfig {

@Bean
public ObjectMapper objectMapper() {

PolymorphicTypeValidator typeValidator = BasicPolymorphicTypeValidator.builder()
.allowIfSubType(Object.class)
.build();

return new ObjectMapper()
.enable(SerializationFeature.INDENT_OUTPUT)
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.registerModule(new JavaTimeModule()) // LocalDateTime 지원 모듈 추가
.activateDefaultTyping(typeValidator, ObjectMapper.DefaultTyping.NON_FINAL); // 클래스 정보를 포함하여 직렬/역직렬화 하도록 설정
}
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,35 @@
package org.withtime.be.withtimebe.global.config;

import static org.springframework.data.redis.serializer.RedisSerializationContext.SerializationPair.*;

import java.time.Duration;

import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.withtime.be.withtimebe.global.data.RedisConfigData;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.jsontype.BasicPolymorphicTypeValidator;
import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;

@Configuration
@RequiredArgsConstructor
public class RedisConfig {

private final RedisConfigData redisConfigData;
private final ObjectMapper objectMapper;

@Bean
RedisConnectionFactory redisConnectionFactory() {
Expand All @@ -28,4 +44,15 @@ RedisTemplate<String, Object> tokenRedisTemplate(RedisConnectionFactory redisCon
redisTemplate.setValueSerializer(RedisSerializer.java());
return redisTemplate;
}

@Bean
public RedisCacheManager redisCacheManager() {
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
.serializeKeysWith(fromSerializer(new StringRedisSerializer()))
.serializeValuesWith(fromSerializer(new GenericJackson2JsonRedisSerializer(objectMapper)))
.entryTtl(Duration.ofDays(1L));

return RedisCacheManager.RedisCacheManagerBuilder.fromConnectionFactory(redisConnectionFactory())
.cacheDefaults(redisCacheConfiguration).build();
}
}