aiteamutils 0.2.37__py3-none-any.whl → 0.2.39__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
aiteamutils/database.py CHANGED
@@ -9,6 +9,7 @@ from sqlalchemy import or_
9
9
  from fastapi import Request, Depends
10
10
  from ulid import ULID
11
11
  from sqlalchemy.sql import Select
12
+ import logging
12
13
 
13
14
  from .exceptions import ErrorCode, CustomException
14
15
  from .base_model import Base, BaseColumn
@@ -31,18 +32,33 @@ def get_database_service() -> 'DatabaseService':
31
32
  if _database_service is None:
32
33
  raise CustomException(
33
34
  ErrorCode.DB_CONNECTION_ERROR,
34
- detail="database_service",
35
+ detail="Database service is not initialized. Call init_database_service() first.",
35
36
  source_function="get_database_service"
36
37
  )
37
38
  return _database_service
38
39
 
39
40
  async def get_db() -> AsyncGenerator[AsyncSession, None]:
40
- """데이터베이스 세션을 생성하고 반환하는 비동기 제너레이터."""
41
+ """데이터베이스 세션을 생성하고 반환하는 비동기 제너레이터.
42
+
43
+ Yields:
44
+ AsyncSession: 데이터베이스 세션
45
+
46
+ Raises:
47
+ CustomException: 세션 생성 실패 시
48
+ """
41
49
  db_service = get_database_service()
42
- async with db_service.get_session() as session:
43
- try:
50
+ try:
51
+ async with db_service.get_session() as session:
44
52
  yield session
45
- finally:
53
+ except Exception as e:
54
+ raise CustomException(
55
+ ErrorCode.DB_CONNECTION_ERROR,
56
+ detail=f"Failed to get database session: {str(e)}",
57
+ source_function="get_db",
58
+ original_error=e
59
+ )
60
+ finally:
61
+ if 'session' in locals():
46
62
  await session.close()
47
63
 
48
64
  def get_database_session(db: AsyncSession = Depends(get_db)) -> 'DatabaseService':
@@ -921,14 +937,40 @@ def init_database_service(
921
937
 
922
938
  Returns:
923
939
  DatabaseService: 초기화된 데이터베이스 서비스 인스턴스
940
+
941
+ Raises:
942
+ CustomException: 데이터베이스 초기화 실패 시
924
943
  """
925
- global _database_service
926
- _database_service = DatabaseService(
927
- db_url=db_url,
928
- db_echo=db_echo,
929
- db_pool_size=db_pool_size,
930
- db_max_overflow=db_max_overflow,
931
- db_pool_timeout=db_pool_timeout,
932
- db_pool_recycle=db_pool_recycle
933
- )
934
- return _database_service
944
+ try:
945
+ global _database_service
946
+ if _database_service is not None:
947
+ logging.info("Database service already initialized")
948
+ return _database_service
949
+
950
+ logging.info(f"Initializing database service with URL: {db_url}")
951
+ _database_service = DatabaseService(
952
+ db_url=db_url,
953
+ db_echo=db_echo,
954
+ db_pool_size=db_pool_size,
955
+ db_max_overflow=db_max_overflow,
956
+ db_pool_timeout=db_pool_timeout,
957
+ db_pool_recycle=db_pool_recycle
958
+ )
959
+
960
+ if not _database_service.engine:
961
+ raise CustomException(
962
+ ErrorCode.DB_CONNECTION_ERROR,
963
+ detail="Database engine initialization failed",
964
+ source_function="init_database_service"
965
+ )
966
+
967
+ logging.info("Database service initialized successfully")
968
+ return _database_service
969
+ except Exception as e:
970
+ logging.error(f"Failed to initialize database service: {str(e)}")
971
+ raise CustomException(
972
+ ErrorCode.DB_CONNECTION_ERROR,
973
+ detail=f"Failed to initialize database service: {str(e)}",
974
+ source_function="init_database_service",
975
+ original_error=e
976
+ )
@@ -3,6 +3,7 @@ from fastapi import Depends, status
3
3
  from fastapi.security import OAuth2PasswordBearer
4
4
  from jose import JWTError, jwt
5
5
  from sqlalchemy.ext.asyncio import AsyncSession
6
+ import logging
6
7
 
7
8
  from .database import DatabaseService, get_database_service, get_db
8
9
  from .exceptions import CustomException, ErrorCode
@@ -12,10 +13,12 @@ class ServiceRegistry:
12
13
  """서비스 레지스트리를 관리하는 클래스"""
13
14
  def __init__(self):
14
15
  self._services: Dict[str, Tuple[Type, Type]] = {}
16
+ self._initialized = False
15
17
 
16
18
  def clear(self):
17
19
  """등록된 모든 서비스를 초기화합니다."""
18
20
  self._services.clear()
21
+ self._initialized = False
19
22
 
20
23
  def register(self, name: str, repository_class: Type, service_class: Type):
21
24
  """서비스를 레지스트리에 등록
@@ -28,13 +31,28 @@ class ServiceRegistry:
28
31
  Raises:
29
32
  CustomException: 이미 등록된 서비스인 경우
30
33
  """
31
- if name in self._services:
34
+ try:
35
+ if name in self._services:
36
+ logging.warning(f"Service '{name}' is already registered. Skipping...")
37
+ return
38
+
39
+ if not repository_class or not service_class:
40
+ raise CustomException(
41
+ ErrorCode.INTERNAL_ERROR,
42
+ detail=f"Invalid service classes for '{name}'",
43
+ source_function="ServiceRegistry.register"
44
+ )
45
+
46
+ self._services[name] = (repository_class, service_class)
47
+ logging.info(f"Service '{name}' registered successfully")
48
+
49
+ except Exception as e:
32
50
  raise CustomException(
33
51
  ErrorCode.INTERNAL_ERROR,
34
- detail=f"service|{name}",
35
- source_function="ServiceRegistry.register"
52
+ detail=f"Failed to register service '{name}': {str(e)}",
53
+ source_function="ServiceRegistry.register",
54
+ original_error=e
36
55
  )
37
- self._services[name] = (repository_class, service_class)
38
56
 
39
57
  def get(self, name: str) -> Tuple[Type, Type]:
40
58
  """등록된 서비스를 조회
@@ -50,11 +68,19 @@ class ServiceRegistry:
50
68
  """
51
69
  if name not in self._services:
52
70
  raise CustomException(
53
- ErrorCode.NOT_FOUND,
54
- detail=f"service|{name}",
71
+ ErrorCode.SERVICE_NOT_REGISTERED,
72
+ detail=f"Service '{name}' is not registered",
55
73
  source_function="ServiceRegistry.get"
56
74
  )
57
75
  return self._services[name]
76
+
77
+ def is_initialized(self) -> bool:
78
+ """서비스 레지스트리 초기화 여부를 반환합니다."""
79
+ return self._initialized
80
+
81
+ def set_initialized(self):
82
+ """서비스 레지스트리를 초기화 상태로 설정합니다."""
83
+ self._initialized = True
58
84
 
59
85
  # ServiceRegistry 초기화
60
86
  service_registry = ServiceRegistry()
@@ -67,11 +93,44 @@ def get_service(name: str):
67
93
 
68
94
  Returns:
69
95
  Callable: 서비스 인스턴스를 반환하는 의존성 함수
96
+
97
+ Raises:
98
+ CustomException: 서비스 생성 실패 시
70
99
  """
71
100
  def _get_service(db_service: DatabaseService = Depends(get_database_service)):
72
- repository_class, service_class = service_registry.get(name)
73
- repository = repository_class(db_service)
74
- return service_class(repository, db_service)
101
+ try:
102
+ # 서비스 레지스트리에서 클래스 조회
103
+ try:
104
+ repository_class, service_class = service_registry.get(name)
105
+ except CustomException as e:
106
+ raise CustomException(
107
+ ErrorCode.SERVICE_NOT_REGISTERED,
108
+ detail=f"Service '{name}' is not registered",
109
+ source_function="dependencies.get_service",
110
+ original_error=e
111
+ )
112
+
113
+ # 서비스 인스턴스 생성
114
+ try:
115
+ repository = repository_class(db_service)
116
+ return service_class(repository)
117
+ except Exception as e:
118
+ raise CustomException(
119
+ ErrorCode.INTERNAL_ERROR,
120
+ detail=f"Failed to create service instance for '{name}': {str(e)}",
121
+ source_function="dependencies.get_service",
122
+ original_error=e
123
+ )
124
+
125
+ except CustomException as e:
126
+ raise e
127
+ except Exception as e:
128
+ raise CustomException(
129
+ ErrorCode.INTERNAL_ERROR,
130
+ detail=f"Unexpected error while creating service '{name}': {str(e)}",
131
+ source_function="dependencies.get_service",
132
+ original_error=e
133
+ )
75
134
  return _get_service
76
135
 
77
136
  oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/users/token")
aiteamutils/exceptions.py CHANGED
@@ -1,6 +1,6 @@
1
1
  """예외 처리 모듈."""
2
2
  import logging
3
- from enum import Enum
3
+ from enum import Enum, IntEnum
4
4
  from typing import Dict, Any, Optional, Tuple, List
5
5
  from fastapi import Request
6
6
  from fastapi.responses import JSONResponse
@@ -69,6 +69,7 @@ class ErrorCode(Enum):
69
69
  NOT_FOUND = ErrorResponse(5001, "GENERAL_NOT_FOUND", 404, "리소스를 찾을 수 없습니다")
70
70
  INTERNAL_ERROR = ErrorResponse(5002, "GENERAL_INTERNAL_ERROR", 500, "내부 서버 오류")
71
71
  SERVICE_UNAVAILABLE = ErrorResponse(5003, "GENERAL_SERVICE_UNAVAILABLE", 503, "서비스를 사용할 수 없습니다")
72
+ SERVICE_NOT_REGISTERED = ErrorResponse(5003, "GENERAL_SERVICE_UNAVAILABLE", 503, "서비스를 사용할 수 없습니다")
72
73
 
73
74
  class CustomException(Exception):
74
75
  """사용자 정의 예외 클래스"""
aiteamutils/version.py CHANGED
@@ -1,2 +1,2 @@
1
1
  """버전 정보"""
2
- __version__ = "0.2.37"
2
+ __version__ = "0.2.39"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aiteamutils
3
- Version: 0.2.37
3
+ Version: 0.2.39
4
4
  Summary: AI Team Utilities
5
5
  Project-URL: Homepage, https://github.com/yourusername/aiteamutils
6
6
  Project-URL: Issues, https://github.com/yourusername/aiteamutils/issues
@@ -4,13 +4,13 @@ aiteamutils/base_repository.py,sha256=qdwQ7Sj2fUqxpDg6cWM48n_QbwPK_VUlG9zTSem8iC
4
4
  aiteamutils/base_service.py,sha256=E4dHGE0DvhmRyFplh46SwKJOSF_nUL7OAsCkf_ZJF_8,24733
5
5
  aiteamutils/cache.py,sha256=tr0Yn8VPYA9QHiKCUzciVlQ2J1RAwNo2K9lGMH4rY3s,1334
6
6
  aiteamutils/config.py,sha256=kFKMeIx1KcuEwwx4VjZdCgoTOHCkG3ySYVJ0G6cvMoA,2849
7
- aiteamutils/database.py,sha256=CaH73g8PPNcmLCz4Xr0DBtNSrLcpRlyt0F1zO5Tigfo,33811
8
- aiteamutils/dependencies.py,sha256=GgN8sFM7qGNmOfpLaFrhuHOgPlBVXWrEgxv29jxjEgI,4226
7
+ aiteamutils/database.py,sha256=ATFiwG_o6o1eeUa0VVQ_2E_ExC2Yg-Ui_eA62SL6vQk,35344
8
+ aiteamutils/dependencies.py,sha256=MQAZnuOrggb1lMKdwOTqFGTPkZKZnY1bP5qmbV6bru8,6563
9
9
  aiteamutils/enums.py,sha256=ipZi6k_QD5-3QV7Yzv7bnL0MjDz-vqfO9I5L77biMKs,632
10
- aiteamutils/exceptions.py,sha256=YV-ISya4wQlHk4twvGo16I5r8h22-tXpn9wa-b3WwDM,15231
10
+ aiteamutils/exceptions.py,sha256=_lKWXq_ujNj41xN6LDE149PwsecAP7lgYWbOBbLOntg,15368
11
11
  aiteamutils/security.py,sha256=9gvEqDtE3RJaoCWqELPCjkg-IsSqZVrpMP6XPZaodWU,16024
12
12
  aiteamutils/validators.py,sha256=3N245cZFjgwtW_KzjESkizx5BBUDaJLbbxfNO4WOFZ0,7764
13
- aiteamutils/version.py,sha256=CmXYar-ylEXzX7J29Pftix8-ss-hnVGdG7rr9Oikfq0,42
14
- aiteamutils-0.2.37.dist-info/METADATA,sha256=TBQe6PWAOtODst1zDCR506fxkYQv-V4nWEo4yhAon08,1718
15
- aiteamutils-0.2.37.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
16
- aiteamutils-0.2.37.dist-info/RECORD,,
13
+ aiteamutils/version.py,sha256=3h-1ecnPMwLBzqnNQJ-HYjP8AuypoYQZFhnuHhMKrEE,42
14
+ aiteamutils-0.2.39.dist-info/METADATA,sha256=xBuYTA8IMw31sg6n_3EUXIFbk81OnGh_RSmXY8py1HY,1718
15
+ aiteamutils-0.2.39.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
16
+ aiteamutils-0.2.39.dist-info/RECORD,,