Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ src/main/resources/application.properties

# 로컬 개발 설정
docker-compose.dev.yml
/data/
/db/

# 환경변수
.env
.env
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package org.ezcode.codetest.application.community.service;

import java.util.Collections;
import java.util.List;
import java.util.Optional;

import org.ezcode.codetest.application.community.dto.request.VoteRequest;
import org.ezcode.codetest.application.community.dto.response.VoteResponse;
import org.ezcode.codetest.application.notification.event.NotificationCreateEvent;
import org.ezcode.codetest.application.notification.port.NotificationEventService;
import org.ezcode.codetest.application.notification.service.NotificationExecutor;
import org.ezcode.codetest.domain.community.model.entity.Discussion;
import org.ezcode.codetest.domain.community.model.entity.DiscussionVote;
import org.ezcode.codetest.domain.community.service.DiscussionDomainService;
Expand All @@ -19,17 +21,17 @@
public class DiscussionVoteService extends BaseVoteService<DiscussionVote, DiscussionVoteDomainService> {

private final DiscussionDomainService discussionDomainService;
private final NotificationEventService notificationEventService;
private final NotificationExecutor notificationExecutor;

public DiscussionVoteService(
DiscussionVoteDomainService domainService,
UserDomainService userDomainService,
DiscussionDomainService discussionDomainService,
NotificationEventService notificationEventService
NotificationExecutor notificationExecutor
) {
super(domainService, userDomainService);
this.discussionDomainService = discussionDomainService;
this.notificationEventService = notificationEventService;
this.notificationExecutor = notificationExecutor;
}

@Transactional
Expand All @@ -43,10 +45,13 @@ public VoteResponse manageVoteOnDiscussion(Long problemId, Long discussionId, Vo
@Override
protected void afterVote(User voter, Long targetId) {

Discussion discussion = discussionDomainService.getDiscussionById(targetId);
notificationExecutor.execute(() -> {

Optional<NotificationCreateEvent> notificationEvent = voteDomainService.createDiscussionVoteNotification(voter, discussion);
Discussion discussion = discussionDomainService.getDiscussionById(targetId);

notificationEvent.ifPresent(notificationEventService::saveAndNotify);
Optional<NotificationCreateEvent> notificationEvent = voteDomainService.createDiscussionVoteNotification(voter, discussion);

return notificationEvent.map(List::of).orElse(Collections.emptyList());
});
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package org.ezcode.codetest.application.community.service;

import java.util.Collections;
import java.util.List;

import org.ezcode.codetest.application.community.dto.request.ReplyCreateRequest;
import org.ezcode.codetest.application.community.dto.request.ReplyModifyRequest;
import org.ezcode.codetest.application.community.dto.response.ReplyResponse;
import org.ezcode.codetest.application.notification.event.NotificationCreateEvent;
import org.ezcode.codetest.application.notification.port.NotificationEventService;
import org.ezcode.codetest.application.notification.service.NotificationExecutor;
import org.ezcode.codetest.domain.community.dto.ReplyQueryResult;
import org.ezcode.codetest.domain.community.model.entity.Discussion;
import org.ezcode.codetest.domain.community.model.entity.Reply;
Expand All @@ -30,7 +30,7 @@ public class ReplyService {
private final DiscussionDomainService discussionDomainService;
private final UserDomainService userDomainService;

private final NotificationEventService notificationEventService;
private final NotificationExecutor notificationExecutor;

@Transactional
public ReplyResponse createReply(
Expand All @@ -46,14 +46,17 @@ public ReplyResponse createReply(

Reply reply = replyDomainService.createReply(discussion, user, request.parentReplyId(), request.content());

List<User> notificationTargets = reply.generateNotificationTargets();
notificationExecutor.execute(() -> {
List<User> notificationTargets = reply.generateNotificationTargets();

if (!notificationTargets.isEmpty()) {
for (User target : notificationTargets) {
NotificationCreateEvent notificationEvent = replyDomainService.createReplyNotification(target, reply);
notificationEventService.saveAndNotify(notificationEvent);
if (notificationTargets.isEmpty()) {
return Collections.emptyList();
}
}

return notificationTargets.stream()
.map(target -> replyDomainService.createReplyNotification(target, reply))
.toList();
});

return ReplyResponse.fromEntity(reply);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package org.ezcode.codetest.application.community.service;

import java.util.Collections;
import java.util.List;
import java.util.Optional;

import org.ezcode.codetest.application.community.dto.request.VoteRequest;
import org.ezcode.codetest.application.community.dto.response.VoteResponse;
import org.ezcode.codetest.application.notification.event.NotificationCreateEvent;
import org.ezcode.codetest.application.notification.port.NotificationEventService;
import org.ezcode.codetest.application.notification.service.NotificationExecutor;
import org.ezcode.codetest.domain.community.model.entity.Reply;
import org.ezcode.codetest.domain.community.model.entity.ReplyVote;
import org.ezcode.codetest.domain.community.service.ReplyDomainService;
Expand All @@ -19,18 +21,18 @@
public class ReplyVoteService extends BaseVoteService<ReplyVote, ReplyVoteDomainService> {

private final ReplyDomainService replyDomainService;
private final NotificationExecutor notificationExecutor;

private final NotificationEventService notificationEventService;

public ReplyVoteService(
ReplyVoteDomainService domainService,
UserDomainService userDomainService,
ReplyDomainService replyDomainService,
NotificationEventService notificationEventService
NotificationExecutor notificationExecutor
) {
super(domainService, userDomainService);
this.replyDomainService = replyDomainService;
this.notificationEventService = notificationEventService;
this.notificationExecutor = notificationExecutor;
}

@Transactional
Expand All @@ -44,10 +46,13 @@ public VoteResponse manageVoteOnReply(Long problemId, Long discussionId, Long re
@Override
protected void afterVote(User voter, Long targetId) {

Reply reply = replyDomainService.getReplyById(targetId);
notificationExecutor.execute(() -> {

Optional<NotificationCreateEvent> notificationEvent = voteDomainService.createReplyVoteNotification(voter, reply);
Reply reply = replyDomainService.getReplyById(targetId);

notificationEvent.ifPresent(notificationEventService::saveAndNotify);
Optional<NotificationCreateEvent> notificationEvent = voteDomainService.createReplyVoteNotification(voter, reply);

return notificationEvent.map(List::of).orElse(Collections.emptyList());
});
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package org.ezcode.codetest.application.notification.event;

public record NotificationReadEvent(
public record NotificationMarkReadEvent(

String principalName,

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
public enum NotificationExceptionCode implements ResponseCode {

NOTIFICATION_CANNOT_FIND_EVENT_TYPE(false, HttpStatus.INTERNAL_SERVER_ERROR, "해당 이벤트 타입의 mapper를 찾을 수 없습니다."),
NOTIFICATION_CONVERT_MESSAGE_ERROR(false, HttpStatus.INTERNAL_SERVER_ERROR, "메시지 변환 과정에서 에러가 발생했습니다."),
NOTIFICATION_NOT_FOUND(false, HttpStatus.NOT_FOUND, "해당 ID의 notification 데이터를 찾지 못했습니다")
;

private final boolean success;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@

import org.ezcode.codetest.application.notification.event.NotificationCreateEvent;
import org.ezcode.codetest.application.notification.event.NotificationListRequestEvent;
import org.ezcode.codetest.application.notification.event.NotificationReadEvent;
import org.ezcode.codetest.application.notification.event.NotificationMarkReadEvent;

public interface NotificationEventService {

void saveAndNotify(NotificationCreateEvent dto);
void notify(NotificationCreateEvent dto);

void notifyList(NotificationListRequestEvent dto);

void setRead(NotificationReadEvent dto);
void setRead(NotificationMarkReadEvent dto);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package org.ezcode.codetest.application.notification.service;

import java.util.List;
import java.util.function.Supplier;

import org.ezcode.codetest.application.notification.event.NotificationCreateEvent;
import org.ezcode.codetest.application.notification.port.NotificationEventService;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Component
@RequiredArgsConstructor
public class NotificationExecutor {

private final NotificationEventService notificationEventService;

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void execute(Supplier<List<NotificationCreateEvent>> notificationsEventSupplier) {

try {
List<NotificationCreateEvent> events = notificationsEventSupplier.get();

if (events != null && !events.isEmpty()) {
for (NotificationCreateEvent event : events) {
notificationEventService.notify(event);
}
log.info("알림 이벤트 {}개 발행 성공", events.size());
}
} catch (Exception ex) {
log.error("알림 이벤트 발행 실패");
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package org.ezcode.codetest.application.notification.service;

import org.ezcode.codetest.application.notification.event.NotificationListRequestEvent;
import org.ezcode.codetest.application.notification.event.NotificationReadEvent;
import org.ezcode.codetest.application.notification.event.NotificationMarkReadEvent;
import org.ezcode.codetest.application.notification.port.NotificationEventService;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
Expand All @@ -24,7 +24,7 @@ public void getNotificationList(String email, Pageable pageable) {
public void modifyNotificationMarksRead(String email, String notificationId) {

notificationEventService.setRead(
new NotificationReadEvent(email, notificationId)
new NotificationMarkReadEvent(email, notificationId)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@
import org.springframework.cache.support.SimpleCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import com.github.benmanes.caffeine.cache.Caffeine;

@Configuration
@EnableCaching
public class CaffeineCacheConfig {

@Primary
@Bean
public CacheManager cacheManager() {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
package org.ezcode.codetest.infrastructure.cache.config;

import org.ezcode.codetest.application.chatting.port.cache.ChatRoomCache;
import org.ezcode.codetest.infrastructure.event.dto.NotificationRecord;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericToStringSerializer;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
Expand Down Expand Up @@ -39,22 +37,4 @@ public RedisTemplate<String, ChatRoomCache> cacheRedisTemplate(

return template;
}

@Bean
public RedisTemplate<String, NotificationRecord> notificationRedisTemplate(
RedisConnectionFactory factory,
ObjectMapper objectMapper
) {

RedisTemplate<String, NotificationRecord> template = new RedisTemplate<>();
template.setConnectionFactory(factory);

template.setKeySerializer(new StringRedisSerializer());

Jackson2JsonRedisSerializer<NotificationRecord> valueSerializer =
new Jackson2JsonRedisSerializer<>(objectMapper, NotificationRecord.class);
template.setValueSerializer(valueSerializer);

return template;
}
}

This file was deleted.

Loading