-
Notifications
You must be signed in to change notification settings - Fork 0
[HCR-425] 새로 배포 #70
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
[HCR-425] 새로 배포 #70
Changes from all commits
Commits
Show all changes
34 commits
Select commit
Hold shift + click to select a range
40264dc
[HSC-195] chore: Add GitHub Actions workflow for central release disp…
tkv00 d470a90
Merge pull request #12 from one-year-gap/release/HSC-206
tkv00 452896d
Merge pull request #25 from one-year-gap/release/HSC-251
tkv00 118cca7
Merge pull request #31 from one-year-gap/release/HSC-288
tkv00 052f6fc
Merge pull request #36 from one-year-gap/release/HSC-294
tkv00 d57db30
Merge pull request #44 from one-year-gap/release/HSC-345
tkv00 da6e155
Merge pull request #47 from one-year-gap/release/HSC-348
tkv00 e9325c8
Merge pull request #54 from one-year-gap/refactor/HSC-350
tkv00 95ad423
[HSC-364] fix: analysis server cdc on으로 설정
tkv00 54fb06e
Merge pull request #56 from one-year-gap/fix/HSC-364
tkv00 098a6b1
Merge pull request #60 from one-year-gap/release/HSC-398
tkv00 027a367
config: Pinpoint 설정 추가
tkv00 8b0ce16
Merge branch 'main' into config/HSC-418
tkv00 baa939a
Merge pull request #62 from one-year-gap/config/HSC-418
tkv00 c95a562
[HSC-419] feat: 로그
rettooo 2a84d4a
Merge pull request #64 from one-year-gap/hotfix/HSC-419
rettooo bbcba23
[HSC-421] chore: traceId 로그 추가
rettooo 74a61ee
Merge pull request #67 from one-year-gap/hotfix/HSC-421
rettooo 70c8bff
[HSC-422] chore: 로깅 traceId 추가
rettooo 5ba5177
[HSC-422] feat: DB 한번에 실행 unionALL
rettooo 5b843da
[HSC-422] refactor: producer 생성, start stop 앱 생성시 관리
rettooo 8a5bb14
[HSC-422] refactor: main에 producer start, stop
rettooo 817451e
[HSC-422] refactor: 공유 producer가 있으면 send_and_wait만 호출 ( 매번 start/sto…
rettooo d0306d7
[HSC-422] refactor: OpenAI 클라이언트 연결 풀
rettooo 21d1565
[HSC-422] refactor: start openai client 한번 생성
rettooo d91ae2e
[HSC-422] chore: constants, utils, weights 모듈 분리
rettooo 2379d61
[HSC-422] chore: context_loader, retrieval 분리
rettooo 90f816b
[HSC-422] chore: LLM, 임베딩 파이프라인 분리
rettooo 1604772
[HSC-422] chore: service, Kafka, 공개 API 및 recommendation service 래퍼
rettooo 964d48d
Merge branch 'main' into hotfix/HSC-422
rettooo 5e3c24d
Merge pull request #69 from one-year-gap/hotfix/HSC-422
rettooo e0cea71
[HSC-422] fix: 핀포인트 제거
rettooo 7df777c
[HSC-422] fix: 프롬프트 길이 줄이기
rettooo 7b81527
[HSC-425] chore: redeploy
rettooo File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| """추천 결과 발행용 Kafka producer. 앱 lifespan 동안 1개 인스턴스를 재사용한다.""" | ||
|
|
||
| from __future__ import annotations | ||
|
|
||
| import json | ||
| import logging | ||
| from typing import Any | ||
|
|
||
| from app.core.config import Settings, get_settings | ||
| from app.infra.kafka.client_options import build_kafka_client_options | ||
|
|
||
| logger = logging.getLogger(__name__) | ||
|
|
||
| _producer: Any = None | ||
|
|
||
|
|
||
| async def start_recommendation_kafka_producer(settings: Settings | None = None) -> None: | ||
| """bootstrap이 설정된 경우에만 producer를 생성·시작한다. 실패 시 로그만 남기고 계속 기동.""" | ||
| global _producer | ||
| if _producer is not None: | ||
| return | ||
| try: | ||
| from aiokafka import AIOKafkaProducer | ||
| except ImportError: | ||
| logger.info("aiokafka 미설치, 추천용 Kafka producer 생략") | ||
| return | ||
|
|
||
| s = settings or get_settings() | ||
| bootstrap = (s.kafka_bootstrap_servers or "").strip() | ||
| if not bootstrap: | ||
| logger.info("kafka_bootstrap_servers 비어 있음, 추천용 Kafka producer 생략") | ||
| return | ||
|
|
||
| producer = AIOKafkaProducer( | ||
| value_serializer=lambda v: json.dumps(v, ensure_ascii=False).encode("utf-8"), | ||
| **build_kafka_client_options(s), | ||
| ) | ||
| try: | ||
| await producer.start() | ||
| except Exception: | ||
| logger.exception("추천용 Kafka producer 시작 실패 (bootstrap=%s)", bootstrap[:80]) | ||
| return | ||
| _producer = producer | ||
| logger.info("추천용 Kafka producer 시작됨 topic=%s", getattr(s, "kafka_recommendation_topic", "")) | ||
|
|
||
|
|
||
| async def stop_recommendation_kafka_producer() -> None: | ||
| global _producer | ||
| if _producer is None: | ||
| return | ||
| try: | ||
| await _producer.stop() | ||
| except Exception: | ||
| logger.exception("추천용 Kafka producer 종료 중 오류") | ||
| finally: | ||
| _producer = None | ||
| logger.info("추천용 Kafka producer 종료됨") | ||
|
|
||
|
|
||
| def get_recommendation_kafka_producer() -> Any: | ||
| """시작된 공유 producer. 없으면 None (스크립트·미설정 환경).""" | ||
| return _producer |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| """앱 lifespan에서 유지하는 AsyncOpenAI 클라이언트 (연결 풀 재사용).""" | ||
|
|
||
| from __future__ import annotations | ||
|
|
||
| import logging | ||
| from typing import Any | ||
|
|
||
| from app.core.config import Settings, get_settings | ||
|
|
||
| logger = logging.getLogger(__name__) | ||
|
|
||
| _client: Any = None | ||
|
|
||
|
|
||
| def start_openai_client(settings: Settings | None = None) -> None: | ||
| """OPENAI_API_KEY가 있을 때만 공유 클라이언트를 만든다. 동기 함수(내부 I/O 없음).""" | ||
| global _client | ||
| if _client is not None: | ||
| return | ||
| s = settings or get_settings() | ||
| api_key = (getattr(s, "openai_api_key", "") or "").strip() | ||
| if not api_key: | ||
| logger.info("OPENAI_API_KEY 비어 있음, 공유 AsyncOpenAI 클라이언트 생략") | ||
| return | ||
| from openai import AsyncOpenAI | ||
|
|
||
| _client = AsyncOpenAI(api_key=api_key) | ||
| logger.info("공유 AsyncOpenAI 클라이언트 생성됨") | ||
|
|
||
|
|
||
| async def stop_openai_client() -> None: | ||
| global _client | ||
| if _client is None: | ||
| return | ||
| try: | ||
| await _client.close() | ||
| except Exception: | ||
| logger.exception("AsyncOpenAI close 중 오류") | ||
| finally: | ||
| _client = None | ||
| logger.info("공유 AsyncOpenAI 클라이언트 종료됨") | ||
|
|
||
|
|
||
| def get_openai_client() -> Any: | ||
| """lifespan에서 초기화된 클라이언트. 없으면 None (스크립트·키 미설정 기동).""" | ||
| return _client |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,6 +11,15 @@ | |
|
|
||
| from app.core.config import get_settings | ||
| from app.core.logging import configure_logging | ||
| from app.infra.kafka.recommendation_producer import ( | ||
| start_recommendation_kafka_producer, | ||
| stop_recommendation_kafka_producer, | ||
| ) | ||
| from app.infra.openai.app_client import ( | ||
| get_openai_client, | ||
| start_openai_client, | ||
| stop_openai_client, | ||
| ) | ||
| from app.realtime.api.router import api_router | ||
| from app.services.cdc_analysis_service import CdcAnalysisService | ||
|
|
||
|
|
@@ -30,29 +39,48 @@ async def lifespan(application: FastAPI): | |
| runtime_settings = get_settings() | ||
| cdc_service = None | ||
|
|
||
| if runtime_settings.cdc_analysis_enabled: | ||
| if runtime_settings.effective_cdc_analysis_enabled: | ||
| cdc_service = CdcAnalysisService(runtime_settings) | ||
| await cdc_service.start() | ||
| application.state.cdc_service = cdc_service | ||
| logging.info("CDC analysis service enabled inside unified intelligence runtime.") | ||
| logging.info("APP_MODE: %s", runtime_settings.app_mode or "(unset)") | ||
| logging.info( | ||
| "CDC analysis enabled: %s", | ||
| runtime_settings.effective_cdc_analysis_enabled, | ||
| ) | ||
|
|
||
| start_openai_client(runtime_settings) | ||
| application.state.openai_client = get_openai_client() | ||
|
|
||
| await start_recommendation_kafka_producer(runtime_settings) | ||
|
|
||
| try: | ||
| yield | ||
| finally: | ||
| await stop_recommendation_kafka_producer() | ||
| await stop_openai_client() | ||
| application.state.openai_client = None | ||
| if cdc_service is not None: | ||
| await cdc_service.stop() | ||
|
|
||
|
|
||
| def create_app() -> FastAPI: | ||
| application = FastAPI(title=settings.app_name, lifespan=lifespan) | ||
| application = FastAPI( | ||
| title=settings.app_name, | ||
| lifespan=lifespan, | ||
| ) | ||
| application.include_router(api_router, prefix=settings.api_v1_prefix) | ||
|
|
||
| @application.on_event("startup") | ||
| async def log_db_target() -> None: | ||
| runtime_settings = get_settings() | ||
| url = runtime_settings.effective_database_url | ||
| logging.info("DB 연결 대상: %s", _mask_database_url(url)) | ||
| logging.info("CDC analysis enabled: %s", runtime_settings.cdc_analysis_enabled) | ||
| logging.info("APP_MODE: %s", runtime_settings.app_mode or "(unset)") | ||
| logging.info( | ||
| "CDC analysis enabled: %s", | ||
| runtime_settings.effective_cdc_analysis_enabled, | ||
| ) | ||
|
Comment on lines
74
to
+83
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
|
||
| @application.get("/") | ||
| async def root() -> dict[str, str]: | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| """개인화 추천 파이프라인 (컨텍스트 로드·검색·LLM·Kafka).""" | ||
|
|
||
| from .kafka_publish import publish_recommendation_to_kafka | ||
| from .service import ( | ||
| RecommendationService, | ||
| get_recommendation, | ||
| run_recommendation_and_publish_to_kafka, | ||
| ) | ||
| from .weights import compute_product_type_weights | ||
|
|
||
| __all__ = [ | ||
| "RecommendationService", | ||
| "compute_product_type_weights", | ||
| "get_recommendation", | ||
| "publish_recommendation_to_kafka", | ||
| "run_recommendation_and_publish_to_kafka", | ||
| ] |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
애플리케이션의 주요 설정 정보(DB 연결 대상, APP_MODE, CDC 활성화 여부)는
effective_cdc_analysis_enabled값과 관계없이 항상 로그로 남기는 것이 운영 및 디버깅 측면에서 유리합니다. 또한, 아래on_event("startup")블록에서 중복으로 수행하던 로깅을 이곳으로 통합하여 관리하는 것을 권장합니다.