Skip to content

Commit

Permalink
refactor: 알림 시스템 리팩토링 (#63)
Browse files Browse the repository at this point in the history
* refactor/#62: 문의/음악 추천 알림 이벤트와 리스너 생성

* refactor/#62: 문의/음악 추천 서비스에서 이벤트 발행

* refactor/#62: NotificationService 생성 및 테스트 코드 수정

* refactor/#62: 문의/음악 추천 인수 테스트 수정
  • Loading branch information
pushedrumex authored Mar 8, 2024
1 parent bad7856 commit 54e694d
Show file tree
Hide file tree
Showing 27 changed files with 322 additions and 106 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.verby.indp.domain.contact.event;

import com.verby.indp.domain.notification.dto.ContactMail;

public record ContactMailEvent(
ContactMail request
) {

}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package com.verby.indp.domain.contact.service;

import com.verby.indp.domain.common.event.MailSendEvent;
import com.verby.indp.domain.notification.dto.Mail;
import com.verby.indp.domain.contact.event.ContactMailEvent;
import com.verby.indp.domain.contact.Contact;
import com.verby.indp.domain.contact.dto.request.RegisterContactRequest;
import com.verby.indp.domain.contact.repository.ContactRepository;
import com.verby.indp.domain.notification.dto.ContactMail;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationEventPublisher;
Expand All @@ -27,13 +27,15 @@ public long registerContact(RegisterContactRequest request) {
Contact contact = new Contact(request.userName(), request.content(), request.phoneNumber());
Contact persistContact = contactRepository.save(contact);

Mail mail = new Mail(to, "[버비] 문의가 들어왔어요!",
"문의 내용: " + request.content() + "\n" +
"문의자 성함: " + request.userName() + "\n" +
"문의자 연락처: " + request.phoneNumber() + "\n");
applicationEventPublisher.publishEvent(new MailSendEvent(mail));
sendMail(request);

return persistContact.getContactId();
}

private void sendMail(RegisterContactRequest request) {
ContactMail contactMailRequest = ContactMail.of(to, request.content(),
request.userName(), request.phoneNumber());
applicationEventPublisher.publishEvent(new ContactMailEvent(contactMailRequest));
}

}
21 changes: 21 additions & 0 deletions src/main/java/com/verby/indp/domain/mail/dto/Mail.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.verby.indp.domain.mail.dto;

import com.verby.indp.domain.notification.MailNotification;

public record Mail(
long id,
String to,
String subject,
String text
) {

public static Mail from(MailNotification notification) {
return new Mail(
notification.getMailNotificationId(),
notification.getReceiverEmail(),
notification.getSubject(),
notification.getText()
);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.verby.indp.domain.mail.service;

import com.verby.indp.domain.mail.dto.Mail;

public interface MailService {

void sendMail(Mail mail);

}
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
package com.verby.indp.domain.notification.service;
package com.verby.indp.domain.mail.service;

import static org.springframework.transaction.event.TransactionPhase.AFTER_COMMIT;

import com.verby.indp.domain.common.event.MailSendEvent;
import com.verby.indp.domain.notification.event.SendMailEvent;
import lombok.RequiredArgsConstructor;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.event.TransactionalEventListener;

@Service
@RequiredArgsConstructor
public class MailSendListener {
public class SendMailListener {

private final MailService mailService;

@Async
@TransactionalEventListener(phase = AFTER_COMMIT)
public void handleMailSendEvent(MailSendEvent event) {
public void handleSendMailEvent(SendMailEvent event) {
mailService.sendMail(event.mail());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@
import lombok.NoArgsConstructor;

@Entity
@Table(name = "notification")
@Getter
@Table(name = "mail_notification")
@NoArgsConstructor(access = lombok.AccessLevel.PROTECTED)
public class Notification extends BaseTimeEntity {
public class MailNotification extends BaseTimeEntity {

@Id
@Getter
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "notification_id")
private Long notificationId;
@Column(name = "mail_notification_id")
private Long mailNotificationId;

@Column(name = "subject")
private String subject;
Expand All @@ -30,7 +30,7 @@ public class Notification extends BaseTimeEntity {
@Column(name = "receiver_email")
private String receiverEmail;

public Notification(String subject, String text, String receiverEmail) {
public MailNotification(String subject, String text, String receiverEmail) {
this.subject = subject;
this.text = text;
this.receiverEmail = receiverEmail;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.verby.indp.domain.notification.dto;

public record ContactMail(
String to,
String content,
String userName,
String phoneNumber
) {

public static ContactMail of(
String to,
String content,
String userName,
String phoneNumber
) {
return new ContactMail(to, content, userName, phoneNumber);
}

}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.verby.indp.domain.notification.dto;

public record RecommendationMail(
String to,
String information,
String phoneNumber,
String storeName,
String storeAddress
) {
public static RecommendationMail of(
String to,
String information,
String phoneNumber,
String storeName,
String storeAddress
) {
return new RecommendationMail(to, information, phoneNumber, storeName, storeAddress);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.verby.indp.domain.notification.event;

import com.verby.indp.domain.mail.dto.Mail;

public record SendMailEvent(Mail mail) {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.verby.indp.domain.notification.repository;

import com.verby.indp.domain.notification.MailNotification;
import org.springframework.data.jpa.repository.JpaRepository;

public interface NotificationRepository extends JpaRepository<MailNotification, Long> {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.verby.indp.domain.notification.service;

import static org.springframework.transaction.event.TransactionPhase.AFTER_COMMIT;

import com.verby.indp.domain.contact.event.ContactMailEvent;
import lombok.RequiredArgsConstructor;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.event.TransactionalEventListener;

@Service
@RequiredArgsConstructor
public class ContactMailListener {

private final NotificationService notificationService;

@Async
@TransactionalEventListener(phase = AFTER_COMMIT)
public void handleContactMailEvent(ContactMailEvent event) {
notificationService.sendContactMail(event.request());
}

}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.verby.indp.domain.notification.service;

import com.verby.indp.domain.notification.MailNotification;
import com.verby.indp.domain.mail.dto.Mail;
import com.verby.indp.domain.notification.dto.ContactMail;
import com.verby.indp.domain.notification.dto.RecommendationMail;
import com.verby.indp.domain.notification.event.SendMailEvent;
import com.verby.indp.domain.notification.repository.NotificationRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class NotificationService {

private final NotificationRepository notificationRepository;
private final ApplicationEventPublisher applicationEventPublisher;

@Transactional
public void sendContactMail(ContactMail request) {
MailNotification mailNotification = new MailNotification("[버비] 문의가 들어왔어요!",
"문의 내용: " + request.content() + "\n" +
"문의자 성함: " + request.userName() + "\n" +
"문의자 연락처: " + request.phoneNumber() + "\n", request.to());
MailNotification persistMailNotification = notificationRepository.save(mailNotification);
sendMail(persistMailNotification);
}

@Transactional
public void sendRecommendationMail(RecommendationMail request) {
MailNotification mailNotification = new MailNotification("[버비] 인디피 서비스에 음악이 추천되었어요!",
"추천 음악 정보: " + request.information() + "\n" +
"추천인 연락처: " + request.phoneNumber() + "\n" +
"매장 이름: " + request.storeName() + "\n" +
"매장 주소: " + request.storeAddress() + "\n", request.to());
MailNotification persistMailNotification = notificationRepository.save(mailNotification);
sendMail(persistMailNotification);
}

private void sendMail(MailNotification persistMailNotification) {
Mail mail = Mail.from(persistMailNotification);
applicationEventPublisher.publishEvent(new SendMailEvent(mail));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.verby.indp.domain.notification.service;

import static org.springframework.transaction.event.TransactionPhase.AFTER_COMMIT;

import com.verby.indp.domain.recommendation.event.RecommendationMailEvent;
import lombok.RequiredArgsConstructor;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.event.TransactionalEventListener;

@Service
@RequiredArgsConstructor
public class RecommendationMailListener {

private final NotificationService notificationService;

@Async
@TransactionalEventListener(phase = AFTER_COMMIT)
public void handleRecommendationMailEvent(RecommendationMailEvent event) {
notificationService.sendRecommendationMail(event.request());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.verby.indp.domain.recommendation.event;

import com.verby.indp.domain.notification.dto.RecommendationMail;

public record RecommendationMailEvent(
RecommendationMail request
) {
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.verby.indp.domain.recommendation.service;

import com.verby.indp.domain.common.event.MailSendEvent;
import com.verby.indp.domain.recommendation.event.RecommendationMailEvent;
import com.verby.indp.domain.common.exception.NotFoundException;
import com.verby.indp.domain.notification.dto.Mail;
import com.verby.indp.domain.notification.dto.RecommendationMail;
import com.verby.indp.domain.recommendation.Recommendation;
import com.verby.indp.domain.recommendation.dto.request.RegisterRecommendationRequest;
import com.verby.indp.domain.recommendation.repository.RecommendationRepository;
Expand All @@ -29,17 +29,14 @@ public class RecommendationService {
@Transactional
public long registerRecommendation(RegisterRecommendationRequest request) {
Store store = getStore(request);

Recommendation recommendation = new Recommendation(store, request.information(),
request.phoneNumber());

Recommendation persistRecommendation = recommendationRepository.save(recommendation);

Mail mail = new Mail(to, "[버비] 인디피 서비스에 음악이 추천되었어요!",
"추천 음악 정보: " + request.information() + "\n" +
"추천인 연락처: " + request.phoneNumber() + "\n" +
"매장 이름: " + store.getName() + "\n" +
"매장 주소: " + store.getAddress() + "\n");
applicationEventPublisher.publishEvent(new MailSendEvent(mail));
RecommendationMail recommendationMail = RecommendationMail.of(to,
request.information(), request.phoneNumber(), store.getName(), store.getAddress());
applicationEventPublisher.publishEvent(new RecommendationMailEvent(recommendationMail));

return persistRecommendation.getRecommendationId();
}
Expand Down
13 changes: 0 additions & 13 deletions src/main/java/com/verby/indp/global/config/AsyncConfig.java
Original file line number Diff line number Diff line change
@@ -1,23 +1,10 @@
package com.verby.indp.global.config;

import java.util.concurrent.Executor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

@EnableAsync
@Configuration
public class AsyncConfig {

@Bean(name = "asyncEmailSendExecutor")
public Executor asyncEmailSendExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(2);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(100);
executor.setThreadNamePrefix("Executor-");
return executor;
}

}
Loading

0 comments on commit 54e694d

Please sign in to comment.