-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* chore: 외부통신을 위한 webflux의존성 추가 * feat: KAKAO API를 통해 메시지를 보내는 기능 구현 * feat: 시스템 시간 정의(Clock) * chore: firebase의존성 주입 * feat: fcm을 사용해 알람기능 구현 * feat: 이벤트 객체 정의(수업 생성) * feat: lessonid에 따른 객체 찾는 기능구현 * feat: 이벤트 객체 정의(수업 철회) * feat: 알람 기능 추상화 밑 스케줄러 기능 구현 * feat: Letter기능 및 알람 메시지 구현 * feat: 오후 **시 **분 형식으로 변경하는 메서드 구현 * feat: 알람기능 구현(수업신청, 수업철회) * feat: 알람기능의 필요한 스케줄 기능 추가 * chore: DB의존성 추가 * feat:서버가 재시작했을때 알림을 초기화해주는 기능구현 * feat: 알람 확인을 위한 프론트코드 구현 * feat: firebase 설정 추가 * feat: 알람 테스트를 위한 컨트롤러 작성 * feat: 스케쥴러 빈 등록 * feat: Redis를 활용하여 분산된서버일 때 중복으로 알람이 발생하는 문제 해결로직 작성 --------- Co-authored-by: yuseonjun <[email protected]>
- Loading branch information
1 parent
9ebbfc1
commit de57354
Showing
29 changed files
with
672 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
25 changes: 25 additions & 0 deletions
25
doochul/src/main/java/org/doochul/application/RedisService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package org.doochul.application; | ||
|
||
import org.springframework.data.redis.core.RedisTemplate; | ||
import org.springframework.stereotype.Service; | ||
|
||
import java.time.Duration; | ||
|
||
@Service | ||
public class RedisService { | ||
|
||
private final RedisTemplate<String, String> redisTemplate; | ||
|
||
public RedisService(final RedisTemplate<String, String> redisTemplate) { | ||
this.redisTemplate = redisTemplate; | ||
} | ||
|
||
public void delete(final String key) { | ||
redisTemplate.delete(key); | ||
} | ||
|
||
|
||
public boolean setNX(final String key, final String value, final Duration duration) { | ||
return Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(key, value, duration)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package org.doochul.config; | ||
|
||
import java.time.Clock; | ||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
import org.springframework.scheduling.TaskScheduler; | ||
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; | ||
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; | ||
|
||
@Configuration | ||
public class AppConfig { | ||
|
||
@Bean | ||
public Clock clock() { | ||
return Clock.systemDefaultZone(); | ||
} | ||
|
||
@Bean | ||
public TaskScheduler taskScheduler() { | ||
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler(); | ||
taskScheduler.setPoolSize(10); | ||
return taskScheduler; | ||
} | ||
|
||
@Bean | ||
public ThreadPoolTaskScheduler taskScheduler() { | ||
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler(); | ||
scheduler.setPoolSize(2); | ||
return scheduler; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package org.doochul.config; | ||
|
||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
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.StringRedisSerializer; | ||
|
||
@Configuration | ||
public class RedisConfig { | ||
|
||
@Bean | ||
public RedisConnectionFactory redisConnectionFactory() { | ||
return new LettuceConnectionFactory(); | ||
} | ||
|
||
@Bean | ||
public RedisTemplate<String, String> redisTemplate() { | ||
RedisTemplate<String, String> redisTemplate = new RedisTemplate<>(); | ||
redisTemplate.setConnectionFactory(redisConnectionFactory()); | ||
redisTemplate.setKeySerializer(new StringRedisSerializer()); | ||
redisTemplate.setValueSerializer(new StringRedisSerializer()); | ||
return redisTemplate; | ||
} | ||
} |
10 changes: 10 additions & 0 deletions
10
doochul/src/main/java/org/doochul/config/SchedulingConfig.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package org.doochul.config; | ||
|
||
import org.springframework.context.annotation.Configuration; | ||
import org.springframework.scheduling.annotation.EnableScheduling; | ||
|
||
@Configuration | ||
@EnableScheduling | ||
public class SchedulingConfig { | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
doochul/src/main/java/org/doochul/domain/membership/MemberShipRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
5 changes: 5 additions & 0 deletions
5
doochul/src/main/java/org/doochul/domain/membership/MemberShipType.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package org.doochul.domain.membership; | ||
|
||
public enum MemberShipType { | ||
LOL, TFT | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
67 changes: 67 additions & 0 deletions
67
doochul/src/main/java/org/doochul/infra/FcmMessageSender.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package org.doochul.infra; | ||
|
||
import com.google.auth.oauth2.GoogleCredentials; | ||
import com.google.firebase.FirebaseApp; | ||
import com.google.firebase.FirebaseOptions; | ||
import com.google.firebase.messaging.FirebaseMessaging; | ||
import com.google.firebase.messaging.Message; | ||
import com.google.firebase.messaging.Notification; | ||
import jakarta.annotation.PostConstruct; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.doochul.service.Letter; | ||
import org.doochul.service.MessageSendManager; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.core.io.ClassPathResource; | ||
import org.springframework.stereotype.Component; | ||
|
||
import java.io.FileNotFoundException; | ||
import java.io.IOException; | ||
import java.util.concurrent.ExecutionException; | ||
|
||
@Slf4j | ||
@Component | ||
@RequiredArgsConstructor | ||
public class FcmMessageSender implements MessageSendManager { | ||
|
||
@Value("${fcm.certification.path}") | ||
private String FCM_CERTIFICATION_PATH; | ||
|
||
@PostConstruct | ||
public void initialize() { | ||
try { | ||
ClassPathResource resource = new ClassPathResource(FCM_CERTIFICATION_PATH); | ||
FirebaseOptions options = FirebaseOptions.builder() | ||
.setCredentials(GoogleCredentials.fromStream(resource.getInputStream())) | ||
.build(); | ||
|
||
if (FirebaseApp.getApps().isEmpty()) { | ||
FirebaseApp.initializeApp(options); | ||
} | ||
} catch (FileNotFoundException e) { | ||
log.error("파일을 찾을 수 없습니다. ", e); | ||
} catch (IOException e) { | ||
log.error("FCM 인증이 실패했습니다. ", e); | ||
} | ||
} | ||
|
||
@Override | ||
public void sendTo(final Letter letter) { | ||
final Notification notification = Notification.builder() | ||
.setTitle(letter.title()) | ||
.setBody(letter.body()) | ||
.build(); | ||
final Message message = Message.builder() | ||
.setToken(letter.targetToken()) | ||
.setNotification(notification) | ||
.build(); | ||
try { | ||
final String response = FirebaseMessaging.getInstance().sendAsync(message).get(); | ||
log.info("알림 전송 성공 : " + response); | ||
} catch (InterruptedException e) { | ||
log.error("FCM 알림 스레드에서 문제가 발생했습니다.", e); | ||
} catch (ExecutionException e) { | ||
log.error("FCM 알림 전송에 실패했습니다.", e); | ||
} | ||
} | ||
} |
11 changes: 11 additions & 0 deletions
11
doochul/src/main/java/org/doochul/service/LessonCreateEvent.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package org.doochul.service; | ||
|
||
import org.doochul.domain.lesson.Lesson; | ||
import org.doochul.domain.user.User; | ||
|
||
public record LessonCreateEvent( | ||
User student, | ||
User teacher, | ||
Lesson lesson | ||
) { | ||
} |
40 changes: 40 additions & 0 deletions
40
doochul/src/main/java/org/doochul/service/LessonStatus.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package org.doochul.service; | ||
|
||
import java.time.LocalDateTime; | ||
import java.time.format.DateTimeFormatter; | ||
|
||
@FunctionalInterface | ||
interface LessonStatusMessage { | ||
String getMessage(String name, LocalDateTime time, String teacher); | ||
} | ||
|
||
public enum LessonStatus { | ||
BEFORE_LESSON("수업 전", | ||
(name, time, teacher) -> name + "님 " + formatToLocalTime(time) + " " + teacher + " 강사님 수업 잊지 않으셨죠?"), | ||
AFTER_LESSON("수업 후", (name, time, teacher) -> name + "님 오늘 수업 잘 받으셨나요?"), | ||
SCHEDULED_LESSON("수업 신청", | ||
(name, time, teacher) -> formatToLocalTime(time) + " " + name + "님 " + teacher + " 강사님 수업을 신청했습니다."), | ||
WITHDRAWN_LESSON("수업 철회", | ||
(name, time, teacher) -> formatToLocalTime(time) + " " + name + "님 " + teacher + " 강사님의 수업을 철회했습니다."), | ||
END_LESSON("수업 종료", (name, time, teacher) -> teacher + " 강사님의 수업이 모두 종료되었습니다."); | ||
|
||
private final String title; | ||
private final LessonStatusMessage message; | ||
|
||
LessonStatus(String title, LessonStatusMessage message) { | ||
this.title = title; | ||
this.message = message; | ||
} | ||
|
||
private static String formatToLocalTime(LocalDateTime time) { | ||
return time.format(DateTimeFormatter.ofPattern("a HH시 mm분")); | ||
} | ||
|
||
public String getTitle() { | ||
return title; | ||
} | ||
|
||
public String getMessage(String name, LocalDateTime time, String teacher) { | ||
return message.getMessage(name, time, teacher); | ||
} | ||
} |
11 changes: 11 additions & 0 deletions
11
doochul/src/main/java/org/doochul/service/LessonWithdrawnEvent.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package org.doochul.service; | ||
|
||
import org.doochul.domain.lesson.Lesson; | ||
import org.doochul.domain.user.User; | ||
|
||
public record LessonWithdrawnEvent( | ||
User student, | ||
User teacher, | ||
Lesson lesson | ||
) { | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package org.doochul.service; | ||
|
||
import org.doochul.domain.user.User; | ||
|
||
import java.time.LocalDateTime; | ||
|
||
public record Letter( | ||
String targetToken, | ||
String title, | ||
String body | ||
) { | ||
public static Letter of( | ||
final User student, | ||
final User teacher, | ||
final LocalDateTime startedAt, | ||
final LessonStatus lessonStatus | ||
) { | ||
final String message = lessonStatus.getMessage(student.getName(), startedAt, teacher.getName()); | ||
return new Letter(student.getDeviceToken(), lessonStatus.getTitle(), message); | ||
} | ||
} |
5 changes: 5 additions & 0 deletions
5
doochul/src/main/java/org/doochul/service/MessageSendManager.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package org.doochul.service; | ||
|
||
public interface MessageSendManager { | ||
void sendTo(final Letter letter); | ||
} |
26 changes: 26 additions & 0 deletions
26
doochul/src/main/java/org/doochul/service/NotificationEventListener.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package org.doochul.service; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.context.event.EventListener; | ||
import org.springframework.scheduling.annotation.Async; | ||
import org.springframework.stereotype.Component; | ||
|
||
@Slf4j | ||
@Component | ||
@RequiredArgsConstructor | ||
public class NotificationEventListener { | ||
private final NotificationService notificationService; | ||
|
||
@EventListener | ||
@Async | ||
public void scheduleLessonNotificationEvent(final LessonCreateEvent event) { | ||
notificationService.applyForLesson(event); | ||
} | ||
|
||
@EventListener | ||
@Async | ||
public void withdrawnLessonNotificationEvent1(final LessonWithdrawnEvent event) { | ||
notificationService.withdrawnForLessons(event); | ||
} | ||
} |
Oops, something went wrong.