diff --git a/src/main/java/com/lifelibrarians/lifebookshelf/event/PublicationCreatedEvent.java b/src/main/java/com/lifelibrarians/lifebookshelf/event/PublicationCreatedEvent.java new file mode 100644 index 0000000..99cbbdd --- /dev/null +++ b/src/main/java/com/lifelibrarians/lifebookshelf/event/PublicationCreatedEvent.java @@ -0,0 +1,14 @@ +package com.lifelibrarians.lifebookshelf.event; + +public class PublicationCreatedEvent { + + private final Long publicationId; + + public PublicationCreatedEvent(Long publicationId) { + this.publicationId = publicationId; + } + + public Long getPublicationId() { + return publicationId; + } +} diff --git a/src/main/java/com/lifelibrarians/lifebookshelf/event/PublicationCreatedEventListener.java b/src/main/java/com/lifelibrarians/lifebookshelf/event/PublicationCreatedEventListener.java new file mode 100644 index 0000000..c0e1c05 --- /dev/null +++ b/src/main/java/com/lifelibrarians/lifebookshelf/event/PublicationCreatedEventListener.java @@ -0,0 +1,21 @@ +package com.lifelibrarians.lifebookshelf.event; + +import com.lifelibrarians.lifebookshelf.publication.domain.PublicationManager; +import lombok.RequiredArgsConstructor; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; +import org.springframework.transaction.event.TransactionPhase; +import org.springframework.transaction.event.TransactionalEventListener; + +@Component +@RequiredArgsConstructor +public class PublicationCreatedEventListener { + + private final PublicationManager publicationManager; + + @Async + @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) + public void handlePublicationCreatedEvent(PublicationCreatedEvent event) { + publicationManager.invokeNewPublicationProcessor(event.getPublicationId()); + } +} diff --git a/src/main/java/com/lifelibrarians/lifebookshelf/exception/status/PublicationExceptionStatus.java b/src/main/java/com/lifelibrarians/lifebookshelf/exception/status/PublicationExceptionStatus.java index f004e29..6fd6d78 100644 --- a/src/main/java/com/lifelibrarians/lifebookshelf/exception/status/PublicationExceptionStatus.java +++ b/src/main/java/com/lifelibrarians/lifebookshelf/exception/status/PublicationExceptionStatus.java @@ -17,7 +17,7 @@ public enum PublicationExceptionStatus implements ExceptionStatus { PUBLICATION_TITLE_LENGTH_EXCEEDED(400, "PUB003", "제목은 최소 2자, 최대 64자까지 입력할 수 있습니다."), NO_CHAPTERS_FOR_PUBLICATION(400, "PUB004", "출판을 위한 챕터가 존재하지 않습니다."), NO_AUTOBIOGRAPHY_FOR_CHAPTER(400, "PUB005", "챕터에 대한 자서전이 존재하지 않는 챕터가 있습니다. 모든 챕터에 자서전을 입력해주세요."), - ; + PUBLICATION_PROCESSOR_FAILED(502, "PUB006", "출판 처리 중 오류가 발생했습니다. 다시 시도해주세요."); private final int statusCode; diff --git a/src/main/java/com/lifelibrarians/lifebookshelf/publication/domain/ProdPublicationManager.java b/src/main/java/com/lifelibrarians/lifebookshelf/publication/domain/ProdPublicationManager.java index 25bba82..f8373ad 100644 --- a/src/main/java/com/lifelibrarians/lifebookshelf/publication/domain/ProdPublicationManager.java +++ b/src/main/java/com/lifelibrarians/lifebookshelf/publication/domain/ProdPublicationManager.java @@ -3,13 +3,15 @@ import com.amazonaws.services.lambda.AWSLambda; import com.amazonaws.services.lambda.model.InvokeRequest; import com.amazonaws.services.lambda.model.InvokeResult; -import com.lifelibrarians.lifebookshelf.exception.DomainException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.lifelibrarians.lifebookshelf.exception.status.PublicationExceptionStatus; import com.lifelibrarians.lifebookshelf.log.Logging; import java.nio.charset.StandardCharsets; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Profile; -import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; @Component @@ -20,20 +22,40 @@ public class ProdPublicationManager implements PublicationManager { private final AWSLambda awsLambda; + private final ObjectMapper objectMapper; public void invokeNewPublicationProcessor(Long publicationId) { String functionName = "NewPublicationProcessor"; - InvokeRequest invokeRequest = new InvokeRequest() - .withFunctionName(functionName) - .withPayload("{\"publicationId\": \"" + publicationId + "\"}"); - InvokeResult invokeResult = null; try { - invokeResult = awsLambda.invoke(invokeRequest); + + ObjectNode payloadNode = objectMapper.createObjectNode(); + ObjectNode bodyNode = objectMapper.createObjectNode(); + bodyNode.put("publicationId", publicationId); + payloadNode.set("body", bodyNode); + + String payload = objectMapper.valueToTree(payloadNode).toString(); + + System.out.println("Payload: " + payload); + + InvokeRequest invokeRequest = new InvokeRequest() + .withFunctionName(functionName) + .withPayload(payload); + + InvokeResult invokeResult = awsLambda.invoke(invokeRequest); String ans = new String(invokeResult.getPayload().array(), StandardCharsets.UTF_8); + JsonNode jsonResponse = objectMapper.readTree(ans); + if ( + !jsonResponse.has("statusCode") || + (jsonResponse.has("statusCode") && jsonResponse.get("statusCode").asInt() != 200) + ) { + log.error("Lambda function returned: {}", ans); + throw PublicationExceptionStatus.PUBLICATION_PROCESSOR_FAILED.toDomainException(); + } log.info("Lambda function returned: {}", ans); } catch (Exception e) { - throw new DomainException(HttpStatus.BAD_GATEWAY, "Failed to invoke lambda function"); + log.error("Error invoking lambda function: {}", e.getMessage()); + throw PublicationExceptionStatus.PUBLICATION_PROCESSOR_FAILED.toDomainException(); } } } \ No newline at end of file diff --git a/src/main/java/com/lifelibrarians/lifebookshelf/publication/service/PublicationCommandService.java b/src/main/java/com/lifelibrarians/lifebookshelf/publication/service/PublicationCommandService.java index 2ad8358..2a7257c 100644 --- a/src/main/java/com/lifelibrarians/lifebookshelf/publication/service/PublicationCommandService.java +++ b/src/main/java/com/lifelibrarians/lifebookshelf/publication/service/PublicationCommandService.java @@ -12,7 +12,7 @@ import com.lifelibrarians.lifebookshelf.log.Logging; import com.lifelibrarians.lifebookshelf.member.domain.Member; import com.lifelibrarians.lifebookshelf.publication.domain.Publication; -import com.lifelibrarians.lifebookshelf.publication.domain.PublicationManager; +import com.lifelibrarians.lifebookshelf.event.PublicationCreatedEvent; import com.lifelibrarians.lifebookshelf.publication.domain.PublishStatus; import com.lifelibrarians.lifebookshelf.publication.dto.request.PublicationCreateRequestDto; import com.lifelibrarians.lifebookshelf.publication.repository.PublicationRepository; @@ -22,6 +22,7 @@ import java.util.stream.Collectors; import javax.persistence.EntityManager; import lombok.RequiredArgsConstructor; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -36,7 +37,8 @@ public class PublicationCommandService { private final EntityManager entityManager; private final BookChapterRepository bookChapterRepository; private final BookContentRepository bookContentRepository; - private final PublicationManager publicationManager; + private final ApplicationEventPublisher eventPublisher; + private int calculateTotalPages(List chapters, int charactersPerPage) { long totalTextLength = 0; @@ -176,7 +178,7 @@ public void createPublication(Member member, PublicationCreateRequestDto request ); publicationRepository.save(publication); - publicationManager.invokeNewPublicationProcessor(publication.getId()); + eventPublisher.publishEvent(new PublicationCreatedEvent(publication.getId())); deleteAllRelatedData(chapters.stream().map(Chapter::getId).collect(Collectors.toList()), member.getId());