afterMissionComplete()
执行任务并进行后处理,还有一个方法
sendNotificationToUsersInRoom()
在执行任务后向同一组的成员发送通知。
// After mission complete. Create mission log, Do user progression
@PostMapping("/complete")
@ResponseStatus(HttpStatus.CREATED)
public BaseResponse<MissionLogCreateRes> postMissionLog(
@Parameter(hidden = true) @AuthUser Integer userId,
@RequestBody @Valid MissionLogCreateReq missionLogCreateReq
) {
UserStat userStat = missionService.afterMissionComplete(userId, missionLogCreateReq);
if (Objects.nonNull(missionLogCreateReq.getRoomId())) {
notificationService.sendNotificationToUsersInRoom(missionLogCreateReq.getAlarmId(), userId);
}
return new BaseResponse<>(Status.SUCCESS_CREATED, new MissionLogCreateRes(userStat));
}
@Transactional
public UserStat afterMissionComplete(int userId, MissionLogCreateReq req) {
User user = userRepository.findById(userId)
.orElseThrow(() -> new BaseException(Status.USER_NOT_FOUND));
createMissionLog(user, req);
userService.userProgress(user);
return UserStat.from(user);
}
public void sendNotificationToUsersInRoom(Integer alarmId, Integer missionCompleteUserId) {
User user = userRepository.findById(missionCompleteUserId)
.orElseThrow(() -> new BaseException(Status.USER_NOT_FOUND));
Room room = roomRepository.findByAlarmId(alarmId)
.orElseThrow(() -> new BaseException(Status.ROOM_NOT_FOUND));
List<Integer> userIdsInRoom = room.getRoomUsers().stream()
.map(RoomUser::getUser)
.map(User::getId)
.filter(userId -> userId != user.getId())
.collect(Collectors.toList());
if (userIdsInRoom.size() > 0)
fcmService.sendMessageToTokens(
new RoomMissionLogNotificationVo(
user,
room,
fcmTokenRepository.findAllByUser_IdIn(userIdsInRoom)
)
);
}
我认为我们应该像当前控制器代码一样将这两个方法分开,但我的同事说我们应该在 sendNotificationToUsersInRoom()
中包含
afterMissionComplete()
,以便这两个功能都在一个事务中执行。但是,即使通知失败,我也不赞成不运行任务后流程。
您认为应该怎样做?请自由发表您的意见。
我会将 sendNotification 调用移至 afterComplete 方法中,因为这是您希望在完成后发生的事情,并且将两者绑定在一起在商业上是有意义的。
为了防止失败的 sendNotification 回滚整个操作,您可以将其包装在 try{} catch 块中以捕获失败并记录异常,但让进程继续而不回滚操作。如果电子邮件/通知不重要,我会经常对与电子邮件相关的交易执行此操作。
@Transactional
public UserStat afterMissionComplete(int userId, MissionLogCreateReq req) {
User user = userRepository.findById(userId)
.orElseThrow(() -> new BaseException(Status.USER_NOT_FOUND));
createMissionLog(user, req);
userService.userProgress(user);
try{
if (Objects.nonNull(missionLogCreateReq.getRoomId())) {
notificationService.sendNotificationToUsersInRoom(missionLogCreateReq.getAlarmId(), userId);
}
} catch (ex Exception) {
logMyException(ex)
}
return UserStat.from(user);
}