mirror of
https://github.com/won-ktds/smarketing-backend.git
synced 2025-12-06 07:06:24 +00:00
Merge remote-tracking branch 'origin/ai-recommend' into marketing-contents
This commit is contained in:
commit
552c05c2d7
@ -103,10 +103,14 @@ public class MarketingTipService implements MarketingTipUseCase {
|
|||||||
String aiGeneratedTip = aiTipGenerator.generateTip(storeWithMenuData);
|
String aiGeneratedTip = aiTipGenerator.generateTip(storeWithMenuData);
|
||||||
log.debug("AI 팁 생성 완료: {}", aiGeneratedTip.substring(0, Math.min(50, aiGeneratedTip.length())));
|
log.debug("AI 팁 생성 완료: {}", aiGeneratedTip.substring(0, Math.min(50, aiGeneratedTip.length())));
|
||||||
|
|
||||||
|
String tipSummary = generateTipSummary(aiGeneratedTip);
|
||||||
|
log.info("tipSummary : {}", tipSummary);
|
||||||
|
|
||||||
// 도메인 객체 생성 및 저장
|
// 도메인 객체 생성 및 저장
|
||||||
MarketingTip marketingTip = MarketingTip.builder()
|
MarketingTip marketingTip = MarketingTip.builder()
|
||||||
.storeId(storeWithMenuData.getStoreData().getStoreId())
|
.storeId(storeWithMenuData.getStoreData().getStoreId())
|
||||||
.tipContent(aiGeneratedTip)
|
.tipContent(aiGeneratedTip)
|
||||||
|
.tipSummary(tipSummary)
|
||||||
.storeWithMenuData(storeWithMenuData)
|
.storeWithMenuData(storeWithMenuData)
|
||||||
.createdAt(LocalDateTime.now())
|
.createdAt(LocalDateTime.now())
|
||||||
.build();
|
.build();
|
||||||
@ -122,11 +126,10 @@ public class MarketingTipService implements MarketingTipUseCase {
|
|||||||
* 마케팅 팁을 응답 DTO로 변환 (전체 내용 포함)
|
* 마케팅 팁을 응답 DTO로 변환 (전체 내용 포함)
|
||||||
*/
|
*/
|
||||||
private MarketingTipResponse convertToResponse(MarketingTip marketingTip, StoreData storeData, boolean isRecentlyCreated) {
|
private MarketingTipResponse convertToResponse(MarketingTip marketingTip, StoreData storeData, boolean isRecentlyCreated) {
|
||||||
String tipSummary = generateTipSummary(marketingTip.getTipContent());
|
|
||||||
|
|
||||||
return MarketingTipResponse.builder()
|
return MarketingTipResponse.builder()
|
||||||
.tipId(marketingTip.getId().getValue())
|
.tipId(marketingTip.getId().getValue())
|
||||||
.tipSummary(tipSummary)
|
.tipSummary(marketingTip.getTipSummary())
|
||||||
.tipContent(marketingTip.getTipContent()) // 🆕 전체 내용 포함
|
.tipContent(marketingTip.getTipContent()) // 🆕 전체 내용 포함
|
||||||
.storeInfo(MarketingTipResponse.StoreInfo.builder()
|
.storeInfo(MarketingTipResponse.StoreInfo.builder()
|
||||||
.storeName(storeData.getStoreName())
|
.storeName(storeData.getStoreName())
|
||||||
@ -139,24 +142,187 @@ public class MarketingTipService implements MarketingTipUseCase {
|
|||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 마케팅 팁 요약 생성 (첫 50자 또는 첫 번째 문장)
|
|
||||||
*/
|
|
||||||
private String generateTipSummary(String fullContent) {
|
private String generateTipSummary(String fullContent) {
|
||||||
if (fullContent == null || fullContent.trim().isEmpty()) {
|
if (fullContent == null || fullContent.trim().isEmpty()) {
|
||||||
return "마케팅 팁이 생성되었습니다.";
|
return "마케팅 팁이 생성되었습니다.";
|
||||||
}
|
}
|
||||||
|
|
||||||
// 첫 번째 문장으로 요약 (마침표 기준)
|
try {
|
||||||
String[] sentences = fullContent.split("[.!?]");
|
// JSON 형식 처리: "```html\n..." 패턴
|
||||||
String firstSentence = sentences.length > 0 ? sentences[0].trim() : fullContent;
|
String processedContent = preprocessContent(fullContent);
|
||||||
|
|
||||||
// 50자 제한
|
// 1순위: HTML 블록 밖의 첫 번째 제목 추출
|
||||||
if (firstSentence.length() > 50) {
|
String titleOutsideHtml = extractTitleOutsideHtml(processedContent);
|
||||||
return firstSentence.substring(0, 47) + "...";
|
if (titleOutsideHtml != null && titleOutsideHtml.length() > 5) {
|
||||||
|
return titleOutsideHtml;
|
||||||
}
|
}
|
||||||
|
|
||||||
return firstSentence;
|
// 2순위: <b> 태그 안의 첫 번째 내용 추출
|
||||||
|
String boldContent = extractBoldContent(processedContent);
|
||||||
|
if (boldContent != null && boldContent.length() > 5) {
|
||||||
|
return boldContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3순위: HTML 태그 제거 후 첫 번째 문장
|
||||||
|
return extractFirstSentence(processedContent);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("마케팅 팁 요약 생성 중 오류", e);
|
||||||
|
return "마케팅 팁이 생성되었습니다.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JSON이나 특수 형식 전처리
|
||||||
|
*/
|
||||||
|
private String preprocessContent(String content) {
|
||||||
|
// 먼저 JSON 이스케이프 문자 정리
|
||||||
|
if (content.contains("\\n")) {
|
||||||
|
content = content.replaceAll("\\\\n", "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSON 구조에서 실제 HTML 내용만 추출
|
||||||
|
if (content.contains("```html")) {
|
||||||
|
content = content.replaceAll("```html", "")
|
||||||
|
.replaceAll("```", "")
|
||||||
|
.replaceAll("\"", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
return content.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HTML 블록 밖의 첫 번째 제목 라인 추출
|
||||||
|
* ```html 이후 첫 번째 줄의 내용만 추출
|
||||||
|
*/
|
||||||
|
private String extractTitleOutsideHtml(String content) {
|
||||||
|
// 먼저 이스케이프 문자 정리
|
||||||
|
String processedContent = content.replaceAll("\\\\n", "\n");
|
||||||
|
|
||||||
|
// ```html 패턴 찾기 (이스케이프 처리 후)
|
||||||
|
String[] htmlPatterns = {"```html\n", "```html\\n"};
|
||||||
|
|
||||||
|
for (String pattern : htmlPatterns) {
|
||||||
|
int htmlStart = processedContent.indexOf(pattern);
|
||||||
|
if (htmlStart != -1) {
|
||||||
|
// 패턴 이후부터 시작
|
||||||
|
int contentStart = htmlStart + pattern.length();
|
||||||
|
|
||||||
|
// 첫 번째 줄바꿈까지 또는 \n\n까지 찾기
|
||||||
|
String remaining = processedContent.substring(contentStart);
|
||||||
|
String[] lines = remaining.split("\n");
|
||||||
|
|
||||||
|
if (lines.length > 0) {
|
||||||
|
String firstLine = lines[0].trim();
|
||||||
|
|
||||||
|
// 유효한 내용인지 확인
|
||||||
|
if (firstLine.length() > 5 && !firstLine.contains("🎯") && !firstLine.contains("<")) {
|
||||||
|
return cleanText(firstLine);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 기존 방식으로 fallback
|
||||||
|
return extractFromLines(processedContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 줄별로 처리하는 기존 방식
|
||||||
|
*/
|
||||||
|
private String extractFromLines(String content) {
|
||||||
|
String[] lines = content.split("\n");
|
||||||
|
|
||||||
|
for (String line : lines) {
|
||||||
|
line = line.trim();
|
||||||
|
|
||||||
|
// 빈 줄이나 HTML 태그, 이모지로 시작하는 줄 건너뛰기
|
||||||
|
if (line.isEmpty() ||
|
||||||
|
line.contains("<") ||
|
||||||
|
line.startsWith("🎯") ||
|
||||||
|
line.startsWith("🔍") ||
|
||||||
|
line.equals("```html") ||
|
||||||
|
line.matches("^[\\p{So}\\p{Sk}\\s]+$")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 의미있는 제목 라인 발견
|
||||||
|
if (line.length() > 5) {
|
||||||
|
return cleanText(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <b> 태그 안의 첫 번째 내용 추출
|
||||||
|
*/
|
||||||
|
private String extractBoldContent(String htmlContent) {
|
||||||
|
int startIndex = htmlContent.indexOf("<b>");
|
||||||
|
if (startIndex == -1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
int endIndex = htmlContent.indexOf("</b>", startIndex);
|
||||||
|
if (endIndex == -1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String content = htmlContent.substring(startIndex + 3, endIndex).trim();
|
||||||
|
return cleanText(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 텍스트 정리
|
||||||
|
*/
|
||||||
|
private String cleanText(String text) {
|
||||||
|
if (text == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return text.replaceAll(" ", " ")
|
||||||
|
.replaceAll("\\s+", " ")
|
||||||
|
.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HTML 태그 제거 후 첫 번째 의미있는 문장 추출
|
||||||
|
*/
|
||||||
|
private String extractFirstSentence(String htmlContent) {
|
||||||
|
// HTML 태그 모두 제거
|
||||||
|
String cleanContent = htmlContent.replaceAll("<[^>]+>", "").trim();
|
||||||
|
|
||||||
|
// 줄별로 나누어서 첫 번째 의미있는 줄 찾기
|
||||||
|
String[] lines = cleanContent.split("\\n");
|
||||||
|
|
||||||
|
for (String line : lines) {
|
||||||
|
line = line.trim();
|
||||||
|
|
||||||
|
// 빈 줄이나 이모지만 있는 줄 건너뛰기
|
||||||
|
if (line.isEmpty() || line.matches("^[\\p{So}\\p{Sk}\\s]+$")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 최소 길이 체크하고 반환
|
||||||
|
if (line.length() > 5) {
|
||||||
|
// 50자 제한
|
||||||
|
if (line.length() > 50) {
|
||||||
|
return line.substring(0, 50).trim() + "...";
|
||||||
|
}
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 모든 방법이 실패하면 기존 방식 사용
|
||||||
|
String[] sentences = cleanContent.split("[.!?]");
|
||||||
|
String firstSentence = sentences.length > 0 ? sentences[0].trim() : cleanContent;
|
||||||
|
|
||||||
|
if (firstSentence.length() > 50) {
|
||||||
|
firstSentence = firstSentence.substring(0, 50).trim() + "...";
|
||||||
|
}
|
||||||
|
|
||||||
|
return firstSentence.isEmpty() ? "마케팅 팁이 생성되었습니다." : firstSentence;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -0,0 +1,24 @@
|
|||||||
|
//package com.won.smarketing.recommend.config;
|
||||||
|
//
|
||||||
|
//import com.azure.messaging.eventhubs.EventHubClientBuilder;
|
||||||
|
//import com.azure.messaging.eventhubs.EventHubProducerClient;
|
||||||
|
//import org.springframework.beans.factory.annotation.Value;
|
||||||
|
//import org.springframework.context.annotation.Bean;
|
||||||
|
//import org.springframework.context.annotation.Configuration;
|
||||||
|
//
|
||||||
|
//@Configuration
|
||||||
|
//public class EventHubConfig {
|
||||||
|
//
|
||||||
|
// @Value("${spring.cloud.azure.eventhubs.connection-string}")
|
||||||
|
// private String connectionString;
|
||||||
|
//
|
||||||
|
// @Value("${azure.eventhub.marketing-tip-hub}")
|
||||||
|
// private String marketingTipHub;
|
||||||
|
//
|
||||||
|
// @Bean
|
||||||
|
// public EventHubProducerClient marketingTipProducerClient() {
|
||||||
|
// return new EventHubClientBuilder()
|
||||||
|
// .connectionString(connectionString, marketingTipHub)
|
||||||
|
// .buildProducerClient();
|
||||||
|
// }
|
||||||
|
//}
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
package com.won.smarketing.recommend.domain.event;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class MarketingTipRequestEvent {
|
||||||
|
|
||||||
|
private String requestId; // 요청 고유 ID
|
||||||
|
private Long userId; // 사용자 ID
|
||||||
|
private Long storeId; // 매장 ID
|
||||||
|
private String storeName; // 매장명
|
||||||
|
private String businessType; // 업종
|
||||||
|
private String location; // 위치
|
||||||
|
private Integer seatCount; // 좌석 수
|
||||||
|
private String menuData; // 메뉴 데이터 (JSON)
|
||||||
|
private LocalDateTime requestedAt; // 요청 시각
|
||||||
|
private Integer retryCount; // 재시도 횟수
|
||||||
|
}
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
//package com.won.smarketing.recommend.domain.service;
|
||||||
|
//
|
||||||
|
//import com.won.smarketing.recommend.domain.model.StoreWithMenuData;
|
||||||
|
//
|
||||||
|
//public interface AsyncMarketingTipGenerator {
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * 마케팅 팁 생성 요청 (비동기)
|
||||||
|
// */
|
||||||
|
// String requestMarketingTip(Long userId, StoreWithMenuData storeWithMenuData);
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * 마케팅 팁 상태 조회
|
||||||
|
// */
|
||||||
|
// MarketingTipStatus getMarketingTipStatus(String requestId);
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * 마케팅 팁 결과 조회
|
||||||
|
// */
|
||||||
|
// String getMarketingTipResult(String requestId);
|
||||||
|
//}
|
||||||
@ -0,0 +1,117 @@
|
|||||||
|
//package com.won.smarketing.recommend.infrastructure.event;
|
||||||
|
//
|
||||||
|
//import com.azure.messaging.eventhubs.EventData;
|
||||||
|
//import com.azure.messaging.eventhubs.models.EventContext;
|
||||||
|
//import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
//import com.won.smarketing.recommend.domain.event.MarketingTipRequestEvent;
|
||||||
|
//import com.won.smarketing.recommend.domain.repository.MarketingTipRepository;
|
||||||
|
//import com.won.smarketing.recommend.infrastructure.external.PythonMarketingTipGenerator;
|
||||||
|
//import com.won.smarketing.recommend.infrastructure.persistence.MarketingTipEntity;
|
||||||
|
//import lombok.RequiredArgsConstructor;
|
||||||
|
//import lombok.extern.slf4j.Slf4j;
|
||||||
|
//import org.springframework.beans.factory.annotation.Value;
|
||||||
|
//import org.springframework.stereotype.Service;
|
||||||
|
//
|
||||||
|
//import java.time.LocalDateTime;
|
||||||
|
//
|
||||||
|
///**
|
||||||
|
// * 마케팅 팁 이벤트 소비자
|
||||||
|
// */
|
||||||
|
//@Slf4j
|
||||||
|
//@Service
|
||||||
|
//@RequiredArgsConstructor
|
||||||
|
//public class MarketingTipEventConsumer {
|
||||||
|
//
|
||||||
|
// private final ObjectMapper objectMapper;
|
||||||
|
// private final PythonMarketingTipGenerator pythonMarketingTipGenerator;
|
||||||
|
// private final MarketingTipRepository marketingTipRepository;
|
||||||
|
//
|
||||||
|
// @Value("${azure.eventhub.marketing-tip-hub}")
|
||||||
|
// private String marketingTipHub;
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Azure Event Hub 이벤트 처리
|
||||||
|
// */
|
||||||
|
// public void processMarketingTipRequest(EventContext eventContext) {
|
||||||
|
// try {
|
||||||
|
// EventData eventData = eventContext.getEventData();
|
||||||
|
// String eventBody = eventData.getBodyAsString();
|
||||||
|
//
|
||||||
|
// MarketingTipRequestEvent request = objectMapper.readValue(eventBody, MarketingTipRequestEvent.class);
|
||||||
|
//
|
||||||
|
// log.info("마케팅 팁 요청 처리 시작: requestId={}", request.getRequestId());
|
||||||
|
//
|
||||||
|
// // 상태를 PROCESSING으로 업데이트
|
||||||
|
// updateProcessingStatus(request.getRequestId(), MarketingTipEntity.ProcessingStatus.PROCESSING);
|
||||||
|
//
|
||||||
|
// // AI 마케팅 팁 생성
|
||||||
|
// String marketingTip = generateMarketingTip(request);
|
||||||
|
//
|
||||||
|
// // 완료 처리
|
||||||
|
// completeMarketingTip(request.getRequestId(), marketingTip);
|
||||||
|
//
|
||||||
|
// // 체크포인트 설정
|
||||||
|
// eventContext.updateCheckpoint();
|
||||||
|
//
|
||||||
|
// log.info("마케팅 팁 요청 처리 완료: requestId={}", request.getRequestId());
|
||||||
|
//
|
||||||
|
// } catch (Exception e) {
|
||||||
|
// log.error("마케팅 팁 요청 처리 실패", e);
|
||||||
|
// handleProcessingError(eventContext, e);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// private void updateProcessingStatus(String requestId, MarketingTipEntity.ProcessingStatus status) {
|
||||||
|
// marketingTipRepository.findByRequestId(requestId)
|
||||||
|
// .ifPresent(entity -> {
|
||||||
|
// entity.setStatus(status);
|
||||||
|
// if (status == MarketingTipEntity.ProcessingStatus.PROCESSING) {
|
||||||
|
// entity.setUpdatedAt(LocalDateTime.now());
|
||||||
|
// }
|
||||||
|
// marketingTipRepository.save(entity);
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// private String generateMarketingTip(MarketingTipRequestEvent request) {
|
||||||
|
// // StoreWithMenuData 객체 생성 로직
|
||||||
|
// // Python AI 서비스 호출
|
||||||
|
// return pythonMarketingTipGenerator.generateTipFromEvent(request);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// private void completeMarketingTip(String requestId, String tipContent) {
|
||||||
|
// marketingTipRepository.findByRequestId(requestId)
|
||||||
|
// .ifPresent(entity -> {
|
||||||
|
// entity.setStatus(MarketingTipEntity.ProcessingStatus.COMPLETED);
|
||||||
|
// entity.setTipContent(tipContent);
|
||||||
|
// entity.setCompletedAt(LocalDateTime.now());
|
||||||
|
//
|
||||||
|
// // 처리 시간 계산
|
||||||
|
// if (entity.getCreatedAt() != null) {
|
||||||
|
// long processingTime = java.time.Duration.between(
|
||||||
|
// entity.getCreatedAt(), LocalDateTime.now()).getSeconds();
|
||||||
|
// entity.setProcessingTimeSeconds((int) processingTime);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// marketingTipRepository.save(entity);
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// private void handleProcessingError(EventContext eventContext, Exception e) {
|
||||||
|
// try {
|
||||||
|
// EventData eventData = eventContext.getEventData();
|
||||||
|
// String eventBody = eventData.getBodyAsString();
|
||||||
|
// MarketingTipRequestEvent request = objectMapper.readValue(eventBody, MarketingTipRequestEvent.class);
|
||||||
|
//
|
||||||
|
// // 실패 상태로 업데이트
|
||||||
|
// marketingTipRepository.findByRequestId(request.getRequestId())
|
||||||
|
// .ifPresent(entity -> {
|
||||||
|
// entity.setStatus(MarketingTipEntity.ProcessingStatus.FAILED);
|
||||||
|
// entity.setErrorMessage(e.getMessage());
|
||||||
|
// marketingTipRepository.save(entity);
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// } catch (Exception ex) {
|
||||||
|
// log.error("오류 처리 중 추가 오류 발생", ex);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
@ -0,0 +1,43 @@
|
|||||||
|
//import com.azure.messaging.eventhubs.EventData;
|
||||||
|
//import com.azure.messaging.eventhubs.EventHubProducerClient;
|
||||||
|
//import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
//import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
//import com.won.smarketing.recommend.domain.event.MarketingTipRequestEvent;
|
||||||
|
//import lombok.RequiredArgsConstructor;
|
||||||
|
//import lombok.extern.slf4j.Slf4j;
|
||||||
|
//import org.springframework.stereotype.Service;
|
||||||
|
//
|
||||||
|
//import java.util.UUID;
|
||||||
|
//
|
||||||
|
///**
|
||||||
|
// * 마케팅 팁 이벤트 발행자
|
||||||
|
// */
|
||||||
|
//@Slf4j
|
||||||
|
//@Service
|
||||||
|
//@RequiredArgsConstructor
|
||||||
|
//public class MarketingTipEventPublisher {
|
||||||
|
//
|
||||||
|
// private final EventHubProducerClient producerClient;
|
||||||
|
// private final ObjectMapper objectMapper;
|
||||||
|
//
|
||||||
|
// public String publishMarketingTipRequest(MarketingTipRequestEvent event) {
|
||||||
|
// try {
|
||||||
|
// String requestId = UUID.randomUUID().toString();
|
||||||
|
// event.setRequestId(requestId);
|
||||||
|
//
|
||||||
|
// String eventData = objectMapper.writeValueAsString(event);
|
||||||
|
//
|
||||||
|
// producerClient.send(EventData.create(eventData));
|
||||||
|
//
|
||||||
|
// log.info("마케팅 팁 요청 이벤트 발행 완료: requestId={}", requestId);
|
||||||
|
// return requestId;
|
||||||
|
//
|
||||||
|
// } catch (JsonProcessingException e) {
|
||||||
|
// log.error("마케팅 팁 이벤트 직렬화 실패", e);
|
||||||
|
// throw new RuntimeException("이벤트 발행 실패", e);
|
||||||
|
// } catch (Exception e) {
|
||||||
|
// log.error("마케팅 팁 이벤트 발행 실패", e);
|
||||||
|
// throw new RuntimeException("이벤트 발행 실패", e);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
@ -24,7 +24,7 @@ import java.util.stream.Collectors;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
@Service // 추가된 어노테이션
|
@Service // 추가된 어노테이션
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class PythonAiTipGenerator implements AiTipGenerator {
|
public class PythonMarketingTipGenerator implements AiTipGenerator {
|
||||||
|
|
||||||
private final WebClient webClient;
|
private final WebClient webClient;
|
||||||
|
|
||||||
@ -33,6 +33,12 @@ external:
|
|||||||
api-key: ${PYTHON_AI_API_KEY:dummy-key}
|
api-key: ${PYTHON_AI_API_KEY:dummy-key}
|
||||||
timeout: ${PYTHON_AI_TIMEOUT:30000}
|
timeout: ${PYTHON_AI_TIMEOUT:30000}
|
||||||
|
|
||||||
|
azure:
|
||||||
|
eventhub:
|
||||||
|
namespace: ${AZURE_EVENTHUB_NAMESPACE}
|
||||||
|
marketing-tip-hub: ${AZURE_EVENTHUB_MARKETING_TIP_HUB:marketing-tip-requests}
|
||||||
|
consumer-group: ${AZURE_EVENTHUB_CONSUMER_GROUP:ai-recommend-service}
|
||||||
|
|
||||||
management:
|
management:
|
||||||
endpoints:
|
endpoints:
|
||||||
web:
|
web:
|
||||||
|
|||||||
@ -47,6 +47,10 @@ subprojects {
|
|||||||
|
|
||||||
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
||||||
testImplementation 'org.springframework.security:spring-security-test'
|
testImplementation 'org.springframework.security:spring-security-test'
|
||||||
|
|
||||||
|
implementation 'com.azure:azure-messaging-eventhubs:5.18.0'
|
||||||
|
implementation 'com.azure:azure-messaging-eventhubs-checkpointstore-blob:1.19.0'
|
||||||
|
implementation 'com.azure:azure-identity:1.11.4'
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.named('test') {
|
tasks.named('test') {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user