-
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.
* feat: 곽두철 뼈대 엔티티 정의 * feat: 곽두철 뼈대 엔티티 재정의 * [Feat] fcm 메시지 알람 기능 구현 (#9) * 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]> * refactor: 중복 코드 삭제 * refactor: 잘못된 코드 리팩터링 * chore: mock 의존성 추가 * feat: 수강신청 메서드 구현 * feat: Redis의 setNX를 사용한 수강신청 락 구현 * [Feat] 알람 기능구현 및 spring batch를 사용한 스케줄기능 구현 (#13) * feat: Batch 설정 및 user엔티티 재정 * feat: Batch를 사용해 수업전 리마인드 알람 스케줄 작성 * feat: Batch를 사용해 수업전 리마인드 알람 스케줄 작성(JPA -> 쿼리로 변경) * feat: Batch를 사용해 수업후 알람 및 이용권 개수 차감 * feat: job을 실행시키는 스케줄러 구현 * feat: batch로 스케줄 로직 이동 및 클래스 네이밍 오타 수정 * feat: TaskExecutor 설정 * feat: 페키지 이동(service -> application) * feat: Batch 설정 및 user엔티티 재정 * feat: Batch를 사용해 수업전 리마인드 알람 스케줄 작성 * feat: Batch를 사용해 수업전 리마인드 알람 스케줄 작성(JPA -> 쿼리로 변경) * feat: Batch를 사용해 수업후 알람 및 이용권 개수 차감 * feat: job을 실행시키는 스케줄러 구현 * feat: batch로 스케줄 로직 이동 및 클래스 네이밍 오타 수정 * feat: TaskExecutor 설정 * feat: 페키지 이동(service -> application) * refactor: final 키워드 추가 * [Feat] kakao 소셜 로그인 및 JWT 구현 (#18) * chore: jwt 의존성 추가 * feat: JWT 및 카카오 소셜 로그인 구현 * feat: 토큰 응답 dto 구현 * Update application.properties * refactor: 불필요한 코드 리팩터링 * refactor: WebClientConfig 삭제 및 리팩터링 * refactor: Data -> Getter로 변경 * refactor: Builder -> 정적 팩토리 메서드로 변경 * refactor: 유저 인증 및 인가 정보를 담당하는 UserPrincipal 생성 및 코드 리팩터링 * refactor: class에서 record로 변경 * refactor: 종료하고 시작할때마다 자동으로 secretKey가 바뀌게 구현 * refactor: service로 로직 분리 * refactor: 클래스 이름 변경 * refactor: 불필요한 클래스 삭제 * refactor: 전체 코드 리팩터링 * refactor: 헤더에서 쿠키형식으로 변경 * Update application.properties * Update application.properties * feat: gitignore 추가 * refactor: 전체 코드 리팩터링 * [Feat] 상품 등록 및 조회 기능 (#22) * feat: 상품 조회 기능 구현 * feat: 상품 등록 기능 구현 * refactor: 전체 코드 리팩터링 * refactor: ProductRepository -> Product * refactor: 테스트 코드 삭제 * refactor: 사용하지 않는 메서드 제거 및 리팩터링 * Graceful Shutdown 적용 (#28) * fact: 비동기 스레드 timeout설정 * fact: graceful shutdown 설정 * [Feat] PT 한개 조회, PT 삭제 기능 추가 (#31) * feat: product 지우는 메서드 구현 * feat: product 1개 조회 메서드 구현 * feat: product 서비스 테스트 코드 구현 * refactor: PostMapping으로 변경 * refactor:api 변경 * refactor: 멱등성을 고려하여 변경 * [Feat] 라이엇 API에 사용할 API bucket4j 적용 (#24) * chore: bucket4j 의존성 주입 * chore: Redis 설정 변경 * feat: bucket4j config설정 및 유량제어 정책 정의 * feat: bucket4j config설정 및 유량제어 정책 정의 * refactor: 패키지 이 * refactor: 유량제어 정책 enum 네이밍 변경 --------- Co-authored-by: yuseonjun <[email protected]> Co-authored-by: SeonJuuuun <[email protected]>
- Loading branch information
1 parent
e793c3f
commit e6c7fc8
Showing
70 changed files
with
2,294 additions
and
15 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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 |
---|---|---|
|
@@ -18,6 +18,7 @@ bin/ | |
!**/src/test/**/bin/ | ||
|
||
### IntelliJ IDEA ### | ||
application.properties | ||
.idea | ||
*.iws | ||
*.iml | ||
|
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 |
---|---|---|
@@ -1,34 +1,48 @@ | ||
plugins { | ||
id 'java' | ||
id 'org.springframework.boot' version '3.2.3' | ||
id 'io.spring.dependency-management' version '1.1.4' | ||
id 'java' | ||
id 'org.springframework.boot' version '3.2.3' | ||
id 'io.spring.dependency-management' version '1.1.4' | ||
} | ||
|
||
group = 'org' | ||
version = '0.0.1-SNAPSHOT' | ||
|
||
java { | ||
sourceCompatibility = '17' | ||
sourceCompatibility = '17' | ||
} | ||
|
||
configurations { | ||
compileOnly { | ||
extendsFrom annotationProcessor | ||
} | ||
compileOnly { | ||
extendsFrom annotationProcessor | ||
} | ||
} | ||
|
||
repositories { | ||
mavenCentral() | ||
mavenCentral() | ||
} | ||
|
||
dependencies { | ||
implementation 'org.springframework.boot:spring-boot-starter-data-jpa' | ||
implementation 'org.springframework.boot:spring-boot-starter-web' | ||
compileOnly 'org.projectlombok:lombok' | ||
annotationProcessor 'org.projectlombok:lombok' | ||
testImplementation 'org.springframework.boot:spring-boot-starter-test' | ||
implementation 'org.springframework.boot:spring-boot-starter-data-jpa' | ||
implementation 'org.springframework.boot:spring-boot-starter-web' | ||
implementation 'org.springframework.boot:spring-boot-starter-webflux' | ||
implementation 'org.springframework.boot:spring-boot-starter-data-redis' | ||
implementation 'io.jsonwebtoken:jjwt-api:0.11.5' | ||
implementation 'org.springframework.boot:spring-boot-starter-batch' | ||
implementation 'com.google.firebase:firebase-admin:9.2.0' | ||
implementation 'com.bucket4j:bucket4j-redis:8.7.0' | ||
|
||
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5' | ||
runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.5' | ||
runtimeOnly 'com.h2database:h2' | ||
|
||
compileOnly 'org.projectlombok:lombok' | ||
annotationProcessor 'org.projectlombok:lombok' | ||
|
||
testImplementation 'org.springframework.batch:spring-batch-test' | ||
testImplementation 'org.springframework.boot:spring-boot-starter-test' | ||
testImplementation 'org.mockito:mockito-core:3.12.4' | ||
} | ||
|
||
tasks.named('test') { | ||
useJUnitPlatform() | ||
useJUnitPlatform() | ||
} |
39 changes: 39 additions & 0 deletions
39
doochul/src/main/java/org/doochul/application/AuthService.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,39 @@ | ||
package org.doochul.application; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.doochul.domain.oauth.jwt.JwtProvider; | ||
import org.doochul.domain.user.User; | ||
import org.doochul.domain.user.UserRepository; | ||
import org.doochul.infra.KakaoLoginTokenClient; | ||
import org.doochul.infra.KakaoLoginUserClient; | ||
import org.doochul.ui.dto.KakaoTokenResponse; | ||
import org.doochul.ui.dto.KakaoUserInfoResponse; | ||
import org.doochul.ui.dto.LoginRequest; | ||
import org.springframework.stereotype.Service; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
@Slf4j | ||
public class AuthService { | ||
|
||
private final KakaoLoginTokenClient kakaoLoginTokenClient; | ||
private final KakaoLoginUserClient kakaoLoginUserClient; | ||
private final JwtProvider jwtProvider; | ||
private final UserRepository userRepository; | ||
|
||
public String login(final LoginRequest request) { | ||
final KakaoTokenResponse kakaoTokenResponse = kakaoLoginTokenClient.getTokenInfo(request.authorizationCode()); | ||
final KakaoUserInfoResponse userInfo = kakaoLoginUserClient.getUserInfo(kakaoTokenResponse.access_token()); | ||
|
||
final User user = userRepository.findBySocialIdAndSocialType(userInfo.id(), request.socialType()) | ||
.orElseGet(() -> initUser(userInfo, userInfo.id())); | ||
|
||
return jwtProvider.createToken(user.getId()); | ||
} | ||
|
||
private User initUser(final KakaoUserInfoResponse userInfo, final Long socialId) { | ||
final User user = User.of(socialId.toString(), userInfo.getName()); | ||
return userRepository.save(user); | ||
} | ||
} |
36 changes: 36 additions & 0 deletions
36
doochul/src/main/java/org/doochul/application/MemberShipService.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,36 @@ | ||
package org.doochul.application; | ||
|
||
import java.time.Duration; | ||
import lombok.RequiredArgsConstructor; | ||
import org.doochul.domain.membership.MemberShip; | ||
import org.doochul.domain.membership.MemberShipRepository; | ||
import org.doochul.domain.product.Product; | ||
import org.doochul.domain.product.ProductRepository; | ||
import org.doochul.domain.user.User; | ||
import org.doochul.domain.user.UserRepository; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
@Transactional | ||
public class MemberShipService { | ||
|
||
private final MemberShipRepository memberShipRepository; | ||
private final ProductRepository productRepository; | ||
private final UserRepository userRepository; | ||
private final RedisService redisService; | ||
|
||
public Long save(final Long userId, final Long productId) { | ||
final Product product = productRepository.findById(productId).orElseThrow(); | ||
final User user = userRepository.findById(userId).orElseThrow(); | ||
|
||
final String key = Long.toString(userId); | ||
if (redisService.setNX(key, "apply", Duration.ofSeconds(5))) { | ||
final Long id = memberShipRepository.save(MemberShip.of(user, product, product.getCount())).getId(); | ||
redisService.delete(key); | ||
return id; | ||
} | ||
throw new IllegalArgumentException(); | ||
} | ||
} |
7 changes: 7 additions & 0 deletions
7
doochul/src/main/java/org/doochul/application/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,7 @@ | ||
package org.doochul.application; | ||
|
||
import org.doochul.infra.dto.Letter; | ||
|
||
public interface MessageSendManager { | ||
void sendTo(final Letter letter); | ||
} |
28 changes: 28 additions & 0 deletions
28
doochul/src/main/java/org/doochul/application/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,28 @@ | ||
package org.doochul.application; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.doochul.application.event.LessonCreateEvent; | ||
import org.doochul.application.event.LessonWithdrawnEvent; | ||
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); | ||
} | ||
} |
56 changes: 56 additions & 0 deletions
56
doochul/src/main/java/org/doochul/application/NotificationService.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,56 @@ | ||
package org.doochul.application; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.doochul.domain.lesson.Lesson; | ||
import org.doochul.domain.user.User; | ||
import org.doochul.application.event.LessonCreateEvent; | ||
import org.doochul.application.event.LessonWithdrawnEvent; | ||
import org.doochul.infra.dto.Letter; | ||
import org.doochul.support.KeyGenerator; | ||
import org.springframework.scheduling.annotation.Async; | ||
import org.springframework.stereotype.Service; | ||
|
||
import java.time.Duration; | ||
|
||
import static org.doochul.domain.lesson.LessonStatus.SCHEDULED_LESSON; | ||
import static org.doochul.domain.lesson.LessonStatus.WITHDRAWN_LESSON; | ||
|
||
@Slf4j | ||
@Service | ||
@RequiredArgsConstructor | ||
public class NotificationService { | ||
private final MessageSendManager messageSendManager; | ||
private final KeyGenerator keyGenerator; | ||
private final RedisService redisService; | ||
|
||
public void applyForLesson(final LessonCreateEvent event) { | ||
final User student = event.student(); | ||
final User teacher = event.teacher(); | ||
final Lesson lesson = event.lesson(); | ||
sendNotification( | ||
Letter.of(student.getDeviceToken(), | ||
student.getName(), | ||
teacher.getName(), | ||
lesson.getStartedAt(), | ||
SCHEDULED_LESSON)); | ||
} | ||
|
||
public void withdrawnForLessons(final LessonWithdrawnEvent event) { | ||
sendNotification( | ||
Letter.of(event.student().getDeviceToken(), | ||
event.student().getName(), | ||
event.teacher().getName(), | ||
event.lesson().getStartedAt(), | ||
WITHDRAWN_LESSON)); | ||
} | ||
|
||
@Async | ||
public void sendNotification(final Letter letter) { | ||
final String key = keyGenerator.generateAccountKey(letter.targetToken()); | ||
if (redisService.setNX(key, "notification", Duration.ofSeconds(5))) { | ||
messageSendManager.sendTo(letter); | ||
redisService.delete(key); | ||
} | ||
} | ||
} |
42 changes: 42 additions & 0 deletions
42
doochul/src/main/java/org/doochul/application/ProductService.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,42 @@ | ||
package org.doochul.application; | ||
|
||
import java.util.List; | ||
import lombok.RequiredArgsConstructor; | ||
import org.doochul.domain.product.Product; | ||
import org.doochul.domain.product.ProductRepository; | ||
import org.doochul.domain.user.User; | ||
import org.doochul.domain.user.UserRepository; | ||
import org.doochul.ui.dto.ProductRegisterRequest; | ||
import org.doochul.ui.dto.ProductResponse; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
@Transactional | ||
public class ProductService { | ||
|
||
private final ProductRepository productRepository; | ||
private final UserRepository userRepository; | ||
|
||
public Long save(final Long userId, final ProductRegisterRequest productRegisterRequest) { | ||
final User user = userRepository.findById(userId).orElseThrow(); | ||
final Product product = Product.of(user, productRegisterRequest); | ||
productRepository.save(product); | ||
return product.getId(); | ||
} | ||
|
||
public ProductResponse findProduct(final Long productId) { | ||
final Product product = productRepository.getById(productId); | ||
return ProductResponse.from(product); | ||
} | ||
|
||
public List<ProductResponse> findProducts() { | ||
final List<Product> products = productRepository.findAll(); | ||
return ProductResponse.to(products); | ||
} | ||
|
||
public void deleteProduct(final Long productId) { | ||
productRepository.deleteById(productId); | ||
} | ||
} |
24 changes: 24 additions & 0 deletions
24
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,24 @@ | ||
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)); | ||
} | ||
} |
25 changes: 25 additions & 0 deletions
25
doochul/src/main/java/org/doochul/application/UserService.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 java.util.Optional; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.doochul.domain.user.Identity; | ||
import org.doochul.domain.user.User; | ||
import org.doochul.domain.user.UserRepository; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
@Service | ||
@Slf4j | ||
@RequiredArgsConstructor | ||
public class UserService { | ||
|
||
private final UserRepository userRepository; | ||
|
||
@Transactional | ||
public String createUser(final String socialId, final String nickname) { | ||
final User user = User.of(socialId, nickname); | ||
userRepository.save(user); | ||
return user.getSocialId().toString(); | ||
} | ||
} |
11 changes: 11 additions & 0 deletions
11
doochul/src/main/java/org/doochul/application/event/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.application.event; | ||
|
||
import org.doochul.domain.lesson.Lesson; | ||
import org.doochul.domain.user.User; | ||
|
||
public record LessonCreateEvent( | ||
User student, | ||
User teacher, | ||
Lesson lesson | ||
) { | ||
} |
11 changes: 11 additions & 0 deletions
11
doochul/src/main/java/org/doochul/application/event/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.application.event; | ||
|
||
import org.doochul.domain.lesson.Lesson; | ||
import org.doochul.domain.user.User; | ||
|
||
public record LessonWithdrawnEvent( | ||
User student, | ||
User teacher, | ||
Lesson lesson | ||
) { | ||
} |
Oops, something went wrong.