Skip to content

Commit

Permalink
Merge pull request #41 from SWM-SMART/feat/#40
Browse files Browse the repository at this point in the history
마인드맵 생성 SSE 적용
  • Loading branch information
noparamin authored Nov 9, 2023
2 parents d1eaf6c + 2823a29 commit 1ee598e
Show file tree
Hide file tree
Showing 5 changed files with 134 additions and 15 deletions.
37 changes: 26 additions & 11 deletions src/main/java/com/smart/watchboard/controller/GraphController.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.smart.watchboard.controller;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.smart.watchboard.dto.KeywordsBodyDto;
import com.smart.watchboard.dto.KeywordsDto;
import com.smart.watchboard.dto.MindmapDto;
import com.smart.watchboard.service.*;
Expand All @@ -9,8 +10,10 @@
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import javax.sound.sampled.UnsupportedAudioFileException;
import java.io.IOException;
Expand All @@ -27,20 +30,22 @@ public class GraphController {
private final RequestService requestService;
private final FileService fileService;
private final WhiteboardService whiteboardService;
private final SseService sseService;

@PostMapping("/graph/{documentID}")
@Operation(summary = "마인드맵 생성", description = "ai 서버에 마인드맵 요청한다.")
public ResponseEntity<?> createMindmap(@PathVariable(value = "documentID") long documentId, @RequestBody List<String> keywords, @RequestHeader("Authorization") String accessToken) throws JsonProcessingException {
if (whiteboardService.isPdfType(documentId)) {
String path = fileService.getPdfUrl(documentId);
ResponseEntity<String> body = requestService.requestPdfMindmap(path, documentId, keywords);
return new ResponseEntity<>(body, HttpStatus.OK);
} else if (whiteboardService.isAudioType(documentId)) {
String text = lectureNoteService.getText(documentId);
ResponseEntity<String> body = requestService.requestSTTMindmap(text, documentId, keywords);
return new ResponseEntity<>(body, HttpStatus.OK);
}
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
public void createMindmap(@PathVariable(value = "documentID") long documentId, @RequestBody KeywordsBodyDto keywordsBodyDto, @RequestHeader("Authorization") String accessToken) throws JsonProcessingException {
sseService.notify(documentId, keywordsBodyDto.getKeywords());
// if (whiteboardService.isPdfType(documentId)) {
// String path = fileService.getPdfUrl(documentId);
// ResponseEntity<String> body = requestService.requestPdfMindmap(path, documentId, keywords);
// return new ResponseEntity<>(body, HttpStatus.OK);
// } else if (whiteboardService.isAudioType(documentId)) {
// String text = lectureNoteService.getText(documentId);
// ResponseEntity<String> body = requestService.requestSTTMindmap(text, documentId, keywords);
// return new ResponseEntity<>(body, HttpStatus.OK);
// }
// return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}

@GetMapping("/documents/{documentID}/mindmap")
Expand Down Expand Up @@ -68,6 +73,16 @@ public ResponseEntity<?> getAnswer(@PathVariable(value = "documentID") long docu
return new ResponseEntity<>(responseEntity, HttpStatus.OK);
}

@GetMapping(value = "/subscribe/{documentID}", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public SseEmitter subscribe(@PathVariable(value = "documentID") long documentId) {
return sseService.subscribe(documentId);
}

@PostMapping("/send-data/{documentID}")
public void sendData(@PathVariable(value = "documentID") long documentId, @RequestBody KeywordsBodyDto keywordsBodyDto) {
sseService.notify(documentId, keywordsBodyDto.getKeywords());
}

@PostMapping("/abc/{documentID}")
public ResponseEntity<?> test(@PathVariable(value = "documentID") long documentId) throws UnsupportedAudioFileException, IOException {
System.out.println(documentId);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.smart.watchboard.repository;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Repository
@RequiredArgsConstructor
public class EmitterRepository {
private final Map<Long, SseEmitter> emitters = new ConcurrentHashMap<>();

public void save(Long id, SseEmitter emitter) {
emitters.put(id, emitter);
}

public void deleteById(Long id) {
emitters.remove(id);
}

public SseEmitter get(Long id) {
return emitters.get(id);
}
}
4 changes: 4 additions & 0 deletions src/main/java/com/smart/watchboard/service/FileService.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,17 @@ public void createFile(FileDto fileDto) {
public void updateFile(FileDto fileDto) {
Document document = whiteboardService.findDoc(fileDto.getDocumentId());
File updatedFile = fileRepository.findByDocument(document);
String key = fileDto.getFileType() + "/" + fileDto.getDocumentId() + "." + fileDto.getFile().getOriginalFilename();
//Optional<File> file = findFile(fileDto.getFileId());
//File updatedFile = file.get();
updatedFile.setFileName(fileDto.getFile().getOriginalFilename());
updatedFile.setObjectKey(key);
updatedFile.setPath(fileDto.getPath());
updatedFile.setFileType(fileDto.getFileType());
updatedFile.setSize(fileDto.getFile().getSize());
updatedFile.setCreatedAt(Instant.now());
updatedFile.setModifiedAt(Instant.now());
updatedFile.setDocument(document);
fileRepository.save(updatedFile);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

Expand Down
77 changes: 77 additions & 0 deletions src/main/java/com/smart/watchboard/service/SseService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package com.smart.watchboard.service;

import com.smart.watchboard.repository.EmitterRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.io.IOException;
import java.util.List;

@Service
@RequiredArgsConstructor
public class SseService {
private static final Long DEFAULT_TIMEOUT = 60L * 1000 * 60;
private final EmitterRepository emitterRepository;
private final FileService fileService;
private final WhiteboardService whiteboardService;
private final RequestService requestService;
private final LectureNoteService lectureNoteService;
private final STTService sttService;

public SseEmitter subscribe(Long documentId) {
SseEmitter emitter = createEmitter(documentId);

sendToClientFirst(documentId, "EventStream Created. [documentId=" + documentId + "]");
return emitter;
}

public void notify(Long documentId, List<String> keywords) {
sendToClient(documentId, keywords);
}

private void sendToClientFirst(Long documentId, Object data) {
SseEmitter emitter = emitterRepository.get(documentId);
if (emitter != null) {
try {
emitter.send(SseEmitter.event().id(String.valueOf(documentId)).name("sse").data(data));
} catch (IOException exception) {
emitterRepository.deleteById(documentId);
emitter.completeWithError(exception);
}
}
}

private void sendToClient(Long documentId, List<String> keywords) {
SseEmitter emitter = emitterRepository.get(documentId);
if (emitter != null) {
try {
if (whiteboardService.isPdfType(documentId)) {
String path = fileService.getPdfUrl(documentId);
ResponseEntity<String> body = requestService.requestPdfMindmap(path, documentId, keywords);
emitter.send(SseEmitter.event().id(String.valueOf(documentId)).name("sse").data(body.getBody()));
} else if (whiteboardService.isAudioType(documentId)) {
String text = lectureNoteService.getText(documentId);
ResponseEntity<String> body = requestService.requestSTTMindmap(text, documentId, keywords);
emitter.send(SseEmitter.event().id(String.valueOf(documentId)).name("sse").data(body.getBody()));
}
} catch (IOException exception) {
emitterRepository.deleteById(documentId);
emitter.completeWithError(exception);
}
}
}

private SseEmitter createEmitter(Long documentId) {
SseEmitter emitter = new SseEmitter(DEFAULT_TIMEOUT);
emitterRepository.save(documentId, emitter);

// Emitter가 완료될 때(모든 데이터가 성공적으로 전송된 상태) Emitter를 삭제한다.
emitter.onCompletion(() -> emitterRepository.deleteById(documentId));
// Emitter가 타임아웃 되었을 때(지정된 시간동안 어떠한 이벤트도 전송되지 않았을 때) Emitter를 삭제한다.
emitter.onTimeout(() -> emitterRepository.deleteById(documentId));

return emitter;
}
}

0 comments on commit 1ee598e

Please sign in to comment.