Skip to content

Commit

Permalink
✨ feat(notification): change memory storage -> mongoDB storage (#210)
Browse files Browse the repository at this point in the history
* ✨ feat: create UserDeviceRepository

* ✨ chore: find device token by userId

* ✨ chore: find all device tokens

* ✨ feat: save token

* ✨ feat: update token

* ✨ feat: delete token

* ✨ chore: combine saveToken and insertToken

* ✨ chore: add Transactional annotation

* ✨ chore: change TokenRepository -> UserDeviceRepository in PushService

* ✨ chore: change TokenRepository -> UserDeviceRepository in TopicService

* ✨ chore: delete TokenRepository and MemoryTokenRepository

* ✨ chore: rename createToken -> saveToken

* ✨ feat: save notification

* 🐛 fix: fix Query annotation of findAllDeviceTokens

* ♻️ refactor: delete UserDevice

* ♻️ refactor: delete deleteToken service logic

* ♻️ refactor: change findDeviceTokenByUserId -> findByUserId

* ♻️ refactor: find tokens using findDeviceTokenByUserId -> findByUserId

* ♻️ refactor: add transactional annotation

* ♻️ refactor: extract getting tokens logic into private method

* ♻️ refactor: give space

* ♻️ refactor: change token not found error message

* 🔥 chore: remove Param annotation

* ♻️ refactor: find tokens using findByUserId -> findDeviceTokenByUserId

* ♻️ refactor: change token not found error message

* ♻️ refactor: remove unused import statement

* ♻️ refactor: notificationList save -> saveAll
  • Loading branch information
siyeonSon authored and seonghun-dev committed Jul 18, 2023
1 parent 24772b1 commit 1050ab0
Show file tree
Hide file tree
Showing 10 changed files with 178 additions and 93 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
@RequiredArgsConstructor
@RequestMapping("/push")
public class PushController {

private final PushService pushService;

@PostMapping("/send")
Expand All @@ -30,4 +31,5 @@ public void sendAllPush(@RequestBody AllPushRequestDto allPushRequestDto) {
public void sendTopicPush(@RequestBody TopicPushRequestDto topicPushRequestDto) {
pushService.sendTopicPush(topicPushRequestDto);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,12 @@ public class TokenController {
private final TokenService tokenService;

@PostMapping
public void createToken(@RequestBody TokenRequestDto tokenRequestDto) {
tokenService.createToken(tokenRequestDto);
public void saveToken(@RequestBody TokenRequestDto tokenRequestDto) {
tokenService.saveToken(tokenRequestDto);
}

@PutMapping
public void updateToken(@RequestBody TokenRequestDto tokenRequestDto) {
tokenService.updateToken(tokenRequestDto);
}

@DeleteMapping
public void deleteToken(@RequestBody Long userId) {
@DeleteMapping("/{userId}")
public void deleteToken(@PathVariable("userId") Long userId) {
tokenService.deleteToken(userId);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@

import com.depromeet.domain.vo.OsType;
import lombok.Builder;
import lombok.Getter;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.mongodb.core.mapping.Document;

import java.util.Date;

@Getter
@Builder
@Document(collection = "user_device")
public class UserDevice {
Expand All @@ -24,4 +26,10 @@ public class UserDevice {
private Date createdAt;
@LastModifiedDate
private Date modifiedAt;

public UserDevice updateDeviceToken(String deviceToken) {
this.deviceToken = deviceToken;
return this;
}

}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.depromeet.repository;

import com.depromeet.domain.UserDevice;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.mongodb.repository.Query;

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

public interface UserDeviceRepository extends MongoRepository<UserDevice, String> {

@Query(value = "{ 'userId' : ?0 }")
Optional<UserDevice> findByUserId(Long userId);

@Query(value = "{ 'userId' : ?0 }", fields = "{ 'deviceToken' : 1 }")
Optional<String> findDeviceTokenByUserId(Long userId);

@Query(value = "{}", fields = "{ 'deviceToken' : 1 }")
List<String> findAllDeviceTokens();

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package com.depromeet.service;

import com.depromeet.domain.Notification;
import com.depromeet.domain.Target;
import com.depromeet.domain.User;
import com.depromeet.domain.UserDevice;
import com.depromeet.domain.vo.Channel;
import com.depromeet.dto.request.AllPushRequestDto;
import com.depromeet.dto.request.PushRequestDto;
import com.depromeet.dto.request.TopicPushRequestDto;
import com.depromeet.repository.NotificationRepository;
import com.depromeet.repository.UserDeviceRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

@Service
@RequiredArgsConstructor
public class NotificationService {

private final NotificationRepository notificationRepository;
private final UserDeviceRepository userDeviceRepository;

@Transactional
public void save(PushRequestDto pushRequestDto) {
List<Notification> notificationList = new ArrayList<>();

for (Long userId : pushRequestDto.getUserIds()) {
var userDevice = userDeviceRepository.findByUserId(userId)
.orElseThrow(() -> new RuntimeException("Token not found for userId: " + userId));
User user = User.builder()
.userId(userId)
.deviceToken(userDevice.getDeviceToken())
.build();

Target target = Target.builder()
.channel(Channel.GENERAL)
.build();

Notification notification = Notification.builder()
.user(user)
.target(target)
.title(pushRequestDto.getTitle())
.content(pushRequestDto.getContent())
.build();

notificationList.add(notification);
}

notificationRepository.saveAll(notificationList);
}


@Transactional
public void save(AllPushRequestDto pushRequestDto) {
List<Notification> notificationList = new ArrayList<>();

List<UserDevice> userDevices = userDeviceRepository.findAll();
for (UserDevice userDevice : userDevices) {
User user = User.builder()
.userId(userDevice.getUserId())
.deviceToken(userDevice.getDeviceToken())
.build();

Target target = Target.builder()
.channel(Channel.GENERAL)
.build();

Notification notification = Notification.builder()
.user(user)
.target(target)
.title(pushRequestDto.getTitle())
.content(pushRequestDto.getContent())
.build();

notificationList.add(notification);
}

notificationRepository.saveAll(notificationList);
}

@Transactional
public void save(TopicPushRequestDto tokenPushRequestDto) {
// TODO: 토픽 저장에 따른 스키마 변경 후 구체화
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,29 @@
import com.depromeet.dto.request.PushRequestDto;
import com.depromeet.dto.request.TopicPushRequestDto;
import com.depromeet.external.fcm.FcmService;
import com.depromeet.repository.TokenRepository;
import com.depromeet.repository.UserDeviceRepository;
import com.google.firebase.messaging.FirebaseMessagingException;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
@RequiredArgsConstructor
public class PushService {

private final TokenRepository tokenRepository;
private final UserDeviceRepository userDeviceRepository;
private final NotificationService notificationService;
private final FcmService fcmService;

@Transactional
public void sendPush(PushRequestDto pushRequestDto) {
List<String> tokens = tokenRepository.findByUserIds(pushRequestDto.getUserIds());
if (tokens.isEmpty()) {
throw new RuntimeException("token not found");
}
List<String> tokens = pushRequestDto.getUserIds().stream()
.map(userId -> userDeviceRepository.findDeviceTokenByUserId(userId)
.orElseThrow(() -> new RuntimeException("Token not found for userId: " + userId)))
.toList();

try {
if (tokens.size() == 1) {
fcmService.sendMessageSync(tokens.get(0), pushRequestDto.getContent());
Expand All @@ -35,10 +39,13 @@ public void sendPush(PushRequestDto pushRequestDto) {
}
} catch (FirebaseMessagingException e) {
}

notificationService.save(pushRequestDto);
}

@Transactional
public void sendAllPush(AllPushRequestDto pushRequestDto) {
List<String> tokens = tokenRepository.findAll();
List<String> tokens = userDeviceRepository.findAllDeviceTokens();
try {
if (pushRequestDto.getTitle() != null) {
fcmService.sendMulticastMessageSync(tokens, pushRequestDto.getTitle(), pushRequestDto.getContent());
Expand All @@ -47,8 +54,11 @@ public void sendAllPush(AllPushRequestDto pushRequestDto) {
}
} catch (FirebaseMessagingException e) {
}

notificationService.save(pushRequestDto);
}

@Transactional
public void sendTopicPush(TopicPushRequestDto tokenPushRequestDto) {
try {
if (tokenPushRequestDto.getTitle() != null) {
Expand All @@ -58,6 +68,8 @@ public void sendTopicPush(TopicPushRequestDto tokenPushRequestDto) {
}
} catch (FirebaseMessagingException e) {
}

notificationService.save(tokenPushRequestDto);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,39 @@
package com.depromeet.service;

import com.depromeet.domain.UserDevice;
import com.depromeet.dto.request.TokenRequestDto;
import com.depromeet.repository.TokenRepository;
import com.depromeet.repository.UserDeviceRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Optional;

@Service
@RequiredArgsConstructor
public class TokenService {

private final TokenRepository tokenRepository;

public void createToken(TokenRequestDto tokenRequestDto) {
tokenRepository.save(tokenRequestDto.getUserId(), tokenRequestDto.getToken());
}
private final UserDeviceRepository userDeviceRepository;

public void updateToken(TokenRequestDto tokenRequestDto) {
tokenRepository.update(tokenRequestDto.getUserId(), tokenRequestDto.getToken());
@Transactional
public void saveToken(TokenRequestDto tokenRequestDto) {
Optional<UserDevice> userDevice = userDeviceRepository.findByUserId(tokenRequestDto.getUserId());
if (userDevice.isPresent()) {
UserDevice updatedUserDevice = userDevice.get().updateDeviceToken(tokenRequestDto.getToken());
userDeviceRepository.save(updatedUserDevice);
} else {
UserDevice createdUserDevice = UserDevice.builder()
.userId(tokenRequestDto.getUserId())
.deviceToken(tokenRequestDto.getToken())
.build();
userDeviceRepository.save(createdUserDevice);
}
}

@Transactional
public void deleteToken(Long userId) {
tokenRepository.delete(userId);
var userDevice = userDeviceRepository.findByUserId(userId)
.orElseThrow(() -> new RuntimeException("Token not found for userId: " + userId));
userDeviceRepository.delete(userDevice);
}
}
Loading

0 comments on commit 1050ab0

Please sign in to comment.