Skip to content

Commit

Permalink
Merge pull request #31 from BbeumbungE/feat/BACK-206
Browse files Browse the repository at this point in the history
feat: 주제별 랭킹 조회 기능 개발 [BACK-206]
  • Loading branch information
Fishphobiagg authored Sep 18, 2023
2 parents 1580031 + 30d57c4 commit e0facad
Show file tree
Hide file tree
Showing 17 changed files with 94 additions and 106 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ public ResponseEntity<Response> convertSketchToCanvas(
@RequestParam Long profileId,
@RequestParam Long subjectId
) throws IOException {
Response response = canvasConvertService.convertSketchToCanvas(profileId, subjectId, sketchFile);
String sketch = s3ImageUploadService.uploadFile(sketchFile, s3PathBuildService.buildPath(profileId, "sketch"));
Response response = canvasConvertService.convertSketchToCanvas(profileId, subjectId, sketch);
return ResponseEntity.status(HttpStatus.CREATED).body(response);
}

Expand All @@ -37,7 +38,8 @@ public ResponseEntity<Response> updateSketchAndCanvas(
@RequestParam Long profileId,
@PathVariable Long canvasId
) throws IOException {
Response response = canvasConvertService.updateSketchAndCanvas(profileId, canvasId, sketchFile);
String sketch = s3ImageUploadService.uploadFile(sketchFile, s3PathBuildService.buildPath(profileId, "sketch"));
Response response = canvasConvertService.updateSketchAndCanvas(profileId, canvasId, sketch);
return ResponseEntity.status(HttpStatus.NO_CONTENT).body(response);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.siliconvalley.domain.canvas.dto;

import com.siliconvalley.domain.canvas.service.CanvasConvertService;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.siliconvalley.domain.canvas.dto;

import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ConvertEventDto {

private Long canvasId;
private String canvasUrl;

public ConvertEventDto(Long canvasId, String canvasUrl){
this.canvasId = canvasId;
this.canvasUrl = canvasUrl;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.siliconvalley.domain.canvas.dao.CanvasFindDao;
import com.siliconvalley.domain.canvas.domain.Canvas;
import com.siliconvalley.domain.canvas.dto.CanvasCreateDto;
import com.siliconvalley.domain.canvas.dto.ConvertEventDto;
import com.siliconvalley.domain.image.service.S3ImageUploadService;
import com.siliconvalley.domain.image.service.S3PathBuildService;
import com.siliconvalley.domain.item.subject.dao.SubjectFindDao;
Expand All @@ -11,6 +12,8 @@
import com.siliconvalley.domain.profile.domain.Profile;
import com.siliconvalley.domain.rabbitMQ.dto.SketchConversionResponse;
import com.siliconvalley.domain.rabbitMQ.service.ConvertRequestSender;
import com.siliconvalley.domain.sse.application.SseEmitterFinder;
import com.siliconvalley.domain.sse.application.SseEmitterSender;
import com.siliconvalley.global.common.dto.Response;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
Expand All @@ -34,23 +37,26 @@ public class CanvasConvertService {
private final CanvasCreateService canvasCreateService;
private final S3ImageUploadService s3ImageUploadService;
private final S3PathBuildService s3PathBuildService;
private final SseEmitterSender sseEmitterSender;
private final SseEmitterFinder sseEmitterFinder;

public Response convertSketchToCanvas(Long profileId, Long subjectId, MultipartFile sketchFile) throws IOException{
String sketch = s3ImageUploadService.uploadFile(sketchFile, s3PathBuildService.buildPath(profileId, "sketch"));
public Response convertSketchToCanvas(Long profileId, Long subjectId, String sketch){
Profile profile = profileFindDao.findById(profileId);
Subject subject = subjectFindDao.findById(subjectId);
Canvas canvas = canvasCreateService.createCanvas(CanvasCreateDto.builder().subject(subject).sketchUrl(sketch).profile(profile).build());
return convertRequestSender.sendSketchConversionRequest(sketch, canvas.getId(), profileId, subjectId);
}

public Response updateSketchAndCanvas(Long profileId, Long canvasId, MultipartFile sketchFile) throws IOException{
String sketch = s3ImageUploadService.uploadFile(sketchFile, s3PathBuildService.buildPath(profileId, "sketch"));
public Response updateSketchAndCanvas(Long profileId, Long canvasId, String sketch){
Canvas canvas = canvasFindDao.findById(canvasId);
return canvasUpdateService.updateSketchAndCanvas(canvas, sketch, profileId);
}

public void updateConvertedData(SketchConversionResponse response){
public void updateConvertedData(SketchConversionResponse response){
Canvas canvas = canvasFindDao.findById(response.getCanvasId());
canvas.updateSketch(response.getCanvasUrl());
Long profileId = canvas.getProfile().getId();
String id = profileId + "_" + System.currentTimeMillis();
canvas.updateCanvas(response.getCanvasUrl());
sseEmitterSender.send(sseEmitterFinder.findByProfileId(profileId), id, new ConvertEventDto(canvas.getId(), response.getCanvasUrl()), profileId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import org.springframework.http.HttpStatus;

public enum RankingCode implements ResponseCode {
UPDATE_RANKING(204, "랭킹이 업데이트 되었습니다.", HttpStatus.NO_CONTENT),
UPDATE_RANKING(201, "랭킹이 업데이트 되었습니다.", HttpStatus.CREATED),
GET_RANKING_SUCCESS(200, "랭킹 조회에 성공하였습니다.", HttpStatus.OK);

private final int code;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,11 @@ public ResponseEntity<Response> getAllPosts(
return ResponseEntity.ok(response);
}

@GetMapping("/posts/ranking")
public ResponseEntity<Response> getRankingThisWeek(){
Response response = rankCachingService.getRankingThisWeek();
@GetMapping("/subjects/{subjectId}/posts/ranking")
public ResponseEntity<Response> getRankingThisWeek(
@PathVariable Long subjectId
){
Response response = rankCachingService.getRankingThisWeekBySubject(subjectId);
return ResponseEntity.ok(response);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public class PostCustomRepository {

private final JPAQueryFactory jpaQueryFactory;

public List<PostRankingDto> getSubjectRankingThisWeek(){
public List<PostRankingDto> getSubjectRankingThisWeek(Long subjectId){
QPost post = QPost.post;
QEmotion emotion = QEmotion.emotion;
QCanvas canvas = QCanvas.canvas1;
Expand All @@ -38,7 +38,8 @@ public List<PostRankingDto> getSubjectRankingThisWeek(){
.from(emotion)
.join(emotion.post, post)
.join(post.canvas, canvas)
.where(emotion.createdAt.between(startOfWeek, endOfWeek)) // 감정 표현의 생성 시간을 기준으로 필터링
.where(emotion.createdAt.between(startOfWeek, endOfWeek).
and(canvas.subject.id.eq(subjectId)))
.groupBy(post.id, canvas.id, canvas.canvas)
.orderBy(emotion.count().desc(), post.createdAt.asc()) // 추가된 정렬 기준
.limit(8)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class RankingCachingDto {
private String time;
private String subjectName;
private List<PostRankingDto> rankerList;

public RankingCachingDto(List<PostRankingDto> dto){
public RankingCachingDto(List<PostRankingDto> dto, String subjectName){
this.time = "Update Time : " + LocalTime.now().getHour() + ":" + LocalTime.now().getMinute();
this.rankerList = dto;
this.subjectName = subjectName;
}

}
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package com.siliconvalley.domain.post.service;

import com.siliconvalley.domain.item.subject.dao.SubjectFindDao;
import com.siliconvalley.domain.item.subject.domain.Subject;
import com.siliconvalley.domain.notification.application.NotificationPushService;
import com.siliconvalley.domain.notification.domain.NotificationType;
import com.siliconvalley.domain.post.dao.PostCustomRepository;
import com.siliconvalley.domain.post.dto.PostRankingDto;
import com.siliconvalley.domain.post.dto.RankingCachingDto;
import com.siliconvalley.domain.sse.application.SseEmitterFinder;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
Expand All @@ -15,24 +15,27 @@
import java.util.List;

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

private final RankCachingService rankCachingService;
private final PostCustomRepository postCustomRepository;

private final SubjectFindDao subjectFindDao;
private final NotificationPushService notificationPushService;

@Scheduled(cron = "0 0 * * * *")
public void updateRanking(){
List<PostRankingDto> postRankingDtoList = postCustomRepository.getSubjectRankingThisWeek();
log.info("랭킹 개수" + postRankingDtoList.size());
for (PostRankingDto postRankingDto : postRankingDtoList){
log.info(postRankingDto.getPostId() + "번 포스트");
notificationPushService.pushNotification(postRankingDto);
List<Subject> subjects = subjectFindDao.findAllSubjects();
for (Subject subject : subjects){
List<PostRankingDto> postRankingDtoList = postCustomRepository.getSubjectRankingThisWeek(subject.getId());
log.info("랭킹 개수" + postRankingDtoList.size());
for (PostRankingDto postRankingDto : postRankingDtoList){
log.info(postRankingDto.getPostId() + "번 포스트");
notificationPushService.pushNotification(postRankingDto);
}
rankCachingService.cachingRankToRedis(new RankingCachingDto(postRankingDtoList, subject.getSubjectName()));
}
rankCachingService.cachingRankToRedis(new RankingCachingDto(postRankingDtoList));
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.siliconvalley.domain.post.service;

import com.siliconvalley.domain.item.subject.dao.SubjectFindDao;
import com.siliconvalley.domain.item.subject.domain.Subject;
import com.siliconvalley.domain.post.code.RankingCode;
import com.siliconvalley.domain.post.dto.RankingCachingDto;
import com.siliconvalley.domain.post.dto.RankingPeriodDto;
Expand All @@ -19,28 +21,30 @@
public class RankCachingService {

private final RedisTemplate<String, RankingCachingDto> redisTemplate;
private final SubjectFindDao subjectFindDao;

public Response getRankingThisWeek(){
RankingCachingDto rankingCachingDto = redisTemplate.opsForList().index(generateRedisKey(), -1);
public Response getRankingThisWeekBySubject(Long subjectId){
Subject subject = subjectFindDao.findById(subjectId);
RankingCachingDto rankingCachingDto = redisTemplate.opsForList().index(generateRedisKey(subject.getSubjectName()), -1);
return Response.of(RankingCode.GET_RANKING_SUCCESS, rankingCachingDto);
}

public void cachingRankToRedis(RankingCachingDto rankingCachingDto){
redisTemplate.opsForList().rightPush(generateRedisKey(), rankingCachingDto);
redisTemplate.opsForList().rightPush(generateRedisKey(rankingCachingDto.getSubjectName()), rankingCachingDto);
// 키의 만료 시간을 4주로 설정
redisTemplate.expire(generateRedisKey(), 28, TimeUnit.DAYS);
redisTemplate.expire(generateRedisKey(rankingCachingDto.getSubjectName()), 28, TimeUnit.DAYS);
}

public String getTopPostThisWeek(){
RankingCachingDto rankingCachingDto = redisTemplate.opsForList().index(generateRedisKey(), -1);
public String getTopPostThisWeek(String subjectName){
RankingCachingDto rankingCachingDto = redisTemplate.opsForList().index(generateRedisKey(subjectName), -1);
log.info(rankingCachingDto.getRankerList().size() + "개의 리스트");
log.info(rankingCachingDto.getRankerList().get(0).getCanvasUrl());
log.info(rankingCachingDto.getRankerList().get(0).getPostId() + "번 게시물");
return rankingCachingDto.getRankerList().get(0).getCanvasUrl();
}

private String generateRedisKey() {
private String generateRedisKey(String subjectName) {
RankingPeriodDto dateDto = RankingPeriodDto.builder().build();
return "week:" + dateDto.getWeekOfYear() + ":day:" + dateDto.getDayOfWeek() + ":rank";
return "week:" + dateDto.getWeekOfYear() + ":day:" + dateDto.getDayOfWeek() + ':' + subjectName + ":rank";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ public class SketchConversionRequest {
private String sketchUrl;
private Long canvasId;
private Long profileId;
private String subjectName;

public SketchConversionRequest(String sketchUrl, Long canvasId, Long profileId){
public SketchConversionRequest(String sketchUrl, Long canvasId, Long profileId, String subjectName){
this.sketchUrl = sketchUrl;
this.canvasId = canvasId;
this.profileId = profileId;
this.subjectName = subjectName;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.siliconvalley.domain.rabbitMQ.service;

import com.siliconvalley.domain.canvas.dto.CanvasConvertResponse;
import com.siliconvalley.domain.item.subject.dao.SubjectFindDao;
import com.siliconvalley.domain.item.subject.domain.Subject;
import com.siliconvalley.domain.post.service.RankCachingService;
import com.siliconvalley.domain.rabbitMQ.code.RabbitMQCode;
import com.siliconvalley.domain.rabbitMQ.dto.SketchConversionRequest;
Expand All @@ -16,17 +18,15 @@ public class ConvertRequestSender {

private final RabbitTemplate rabbitTemplate;
private final RankCachingService rankCachingService;
private final GenerateRoutingKeyService generateRoutingKeyService;
private final SubjectFindDao subjectFindDao;

@Value("${rabbitmq.exchange}")
private String exchange;


public Response sendSketchConversionRequest(String sketchUrl, Long canvasId, Long profileId, Long subjectId) {
SketchConversionRequest request = new SketchConversionRequest(sketchUrl, canvasId, profileId);
rabbitTemplate.convertAndSend(exchange, generateRoutingKeyService.generateRoutingKey(subjectId), request);
return Response.of(RabbitMQCode.CONVERSION_REQUEST_SUCCESS,
new CanvasConvertResponse(canvasId, rankCachingService.getTopPostThisWeek()));
String subjectName = subjectFindDao.findById(subjectId).getSubjectName();
SketchConversionRequest request = new SketchConversionRequest(sketchUrl, canvasId, profileId, subjectName);
rabbitTemplate.convertAndSend(exchange, "sketch_conversion_request_queue" , request);
return Response.of(RabbitMQCode.CONVERSION_REQUEST_SUCCESS, new CanvasConvertResponse(canvasId, rankCachingService.getTopPostThisWeek(subjectName)));
}

}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
@RequiredArgsConstructor
public class SseEmitterFinder {

private final SseEmitterRepository sseEmitterRepository;
private final SseEmitterRepository sseEmitterRepository;

public SseEmitter findByProfileId(Long profileId) {
return sseEmitterRepository.findById(profileId);
Expand Down
10 changes: 10 additions & 0 deletions src/main/java/com/siliconvalley/global/config/RabbitMqConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,14 @@ ConnectionFactory connectionFactory() {
MessageConverter messageConverter() {
return new Jackson2JsonMessageConverter();
}

@Bean
public Binding bindingRequestQueue(Queue requestQueue, TopicExchange topicExchange) {
return BindingBuilder.bind(requestQueue).to(topicExchange).with("sketch_conversion_request_queue");
}

@Bean
public Binding bindingResponseQueue(Queue responseQueue, TopicExchange topicExchange) {
return BindingBuilder.bind(responseQueue).to(topicExchange).with("sketch_conversion_response_queue");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws
.authorizeHttpRequests(authorize -> authorize
.antMatchers(HttpMethod.OPTIONS).permitAll() // OPTIONS 메서드는 모두 허용
.antMatchers("/api/members/**").authenticated()
.antMatchers("/api/profiles/**").authenticated()
// .antMatchers("/api/profiles/**").authenticated()
.anyRequest().permitAll()
);

Expand Down

0 comments on commit e0facad

Please sign in to comment.