```
refactor(core): 重构核心模块结构并更新导入路径 - 将配置相关的设置从 app.core.config 移除 - 将常量定义从 app.core.constants 移除 - 将数据库相关功能从 app.core.database 移除 - 将基础数据库模型从 app.core.db_base 移除 - 将敏感信息掩码功能从 app.core.masking 移除 - 将中间件定义从 app.core.middleware 移除 - 将操作保护功能从 app.core.operation_guard 移除 - 将分页工具从 app.core.pagination 移除 - 将请求上下文管理从 app.core.request_context 移除 - 将调度器功能从 app.core.scheduler 移除 - 将安全认证逻辑从 app.core.security 移除 - 将任务队列相关功能从 app.core.task_queue 移除 - 将时间工具从 app.core.time 移除 - 更新 alembic 配置中的 Base 模型导入路径 - 更新各模块中对重构后组件的引用路径 ```
This commit is contained in:
@@ -4,7 +4,7 @@ from alembic import context
|
|||||||
from sqlalchemy import engine_from_config, pool
|
from sqlalchemy import engine_from_config, pool
|
||||||
|
|
||||||
from app.core.config import get_settings
|
from app.core.config import get_settings
|
||||||
from app.core.db_base import Base
|
from app.core.database import Base
|
||||||
from app.modules.ai_memory import models as ai_memory_models
|
from app.modules.ai_memory import models as ai_memory_models
|
||||||
from app.modules.audit import models as audit_models
|
from app.modules.audit import models as audit_models
|
||||||
from app.modules.business import models as business_models
|
from app.modules.business import models as business_models
|
||||||
|
|||||||
1
app/core/background/__init__.py
Normal file
1
app/core/background/__init__.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
"""Background scheduler and queue helpers."""
|
||||||
@@ -33,7 +33,7 @@ def create_scheduler(app: FastAPI | None = None) -> Any:
|
|||||||
from apscheduler.schedulers.background import BackgroundScheduler
|
from apscheduler.schedulers.background import BackgroundScheduler
|
||||||
|
|
||||||
from app.core.database import SessionLocal
|
from app.core.database import SessionLocal
|
||||||
from app.core.task_queue import (
|
from app.core.background.task_queue import (
|
||||||
enqueue_daily_brief_push,
|
enqueue_daily_brief_push,
|
||||||
enqueue_event_dispatch,
|
enqueue_event_dispatch,
|
||||||
enqueue_legacy_project_sync,
|
enqueue_legacy_project_sync,
|
||||||
3
app/core/config/__init__.py
Normal file
3
app/core/config/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
from app.core.config.settings import Settings, get_settings
|
||||||
|
|
||||||
|
__all__ = ["Settings", "get_settings"]
|
||||||
23
app/core/constants/__init__.py
Normal file
23
app/core/constants/__init__.py
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
from app.core.constants.values import (
|
||||||
|
BEARER_TOKEN_TEMPLATE,
|
||||||
|
DEFAULT_MODEL_PROVIDER,
|
||||||
|
DEFAULT_OPENCLAW_ACTION_JSON,
|
||||||
|
ActorValue,
|
||||||
|
ApiResponseKey,
|
||||||
|
ApiStatus,
|
||||||
|
ConfigErrorDetail,
|
||||||
|
HttpHeader,
|
||||||
|
SecurityErrorDetail,
|
||||||
|
)
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
"ActorValue",
|
||||||
|
"ApiResponseKey",
|
||||||
|
"ApiStatus",
|
||||||
|
"BEARER_TOKEN_TEMPLATE",
|
||||||
|
"ConfigErrorDetail",
|
||||||
|
"DEFAULT_MODEL_PROVIDER",
|
||||||
|
"DEFAULT_OPENCLAW_ACTION_JSON",
|
||||||
|
"HttpHeader",
|
||||||
|
"SecurityErrorDetail",
|
||||||
|
]
|
||||||
30
app/core/database/__init__.py
Normal file
30
app/core/database/__init__.py
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from app.core.database.base import Base
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
"Base",
|
||||||
|
"LegacySessionLocal",
|
||||||
|
"SessionLocal",
|
||||||
|
"engine",
|
||||||
|
"get_db",
|
||||||
|
"get_legacy_db",
|
||||||
|
"legacy_engine",
|
||||||
|
]
|
||||||
|
|
||||||
|
_SESSION_EXPORTS = {
|
||||||
|
"LegacySessionLocal",
|
||||||
|
"SessionLocal",
|
||||||
|
"engine",
|
||||||
|
"get_db",
|
||||||
|
"get_legacy_db",
|
||||||
|
"legacy_engine",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def __getattr__(name: str) -> Any:
|
||||||
|
if name in _SESSION_EXPORTS:
|
||||||
|
from app.core.database import session
|
||||||
|
|
||||||
|
return getattr(session, name)
|
||||||
|
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
||||||
@@ -4,7 +4,8 @@ from sqlalchemy import create_engine
|
|||||||
from sqlalchemy.orm import Session, sessionmaker
|
from sqlalchemy.orm import Session, sessionmaker
|
||||||
|
|
||||||
from app.core.config import get_settings
|
from app.core.config import get_settings
|
||||||
from app.core.db_base import Base
|
|
||||||
|
from .base import Base
|
||||||
|
|
||||||
|
|
||||||
settings = get_settings()
|
settings = get_settings()
|
||||||
1
app/core/http/__init__.py
Normal file
1
app/core/http/__init__.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
"""HTTP middleware, masking, pagination, and request context helpers."""
|
||||||
@@ -4,7 +4,7 @@ from collections.abc import Callable
|
|||||||
from fastapi import Request, Response
|
from fastapi import Request, Response
|
||||||
|
|
||||||
from app.core.constants import HttpHeader
|
from app.core.constants import HttpHeader
|
||||||
from app.core.request_context import reset_request_id, set_request_id
|
from app.core.http.request_context import reset_request_id, set_request_id
|
||||||
|
|
||||||
|
|
||||||
async def request_id_middleware(request: Request, call_next: Callable) -> Response:
|
async def request_id_middleware(request: Request, call_next: Callable) -> Response:
|
||||||
13
app/core/security/__init__.py
Normal file
13
app/core/security/__init__.py
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
from app.core.security.api_keys import ApiPrincipal, require_api_key, require_audit_api_key
|
||||||
|
from app.core.security.operation_guard import (
|
||||||
|
READ_ONLY_OPERATION_DISABLED,
|
||||||
|
require_operations_enabled,
|
||||||
|
)
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
"ApiPrincipal",
|
||||||
|
"READ_ONLY_OPERATION_DISABLED",
|
||||||
|
"require_api_key",
|
||||||
|
"require_audit_api_key",
|
||||||
|
"require_operations_enabled",
|
||||||
|
]
|
||||||
1
app/core/utils/__init__.py
Normal file
1
app/core/utils/__init__.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
"""Core utility helpers."""
|
||||||
@@ -3,8 +3,8 @@ from fastapi.middleware.cors import CORSMiddleware
|
|||||||
|
|
||||||
from app.api.router import api_router
|
from app.api.router import api_router
|
||||||
from app.core.config import get_settings
|
from app.core.config import get_settings
|
||||||
from app.core.middleware import request_id_middleware
|
from app.core.http.middleware import request_id_middleware
|
||||||
from app.core.scheduler import attach_scheduler
|
from app.core.background.scheduler import attach_scheduler
|
||||||
|
|
||||||
|
|
||||||
def _allow_cors_credentials(cors_origins: list[str]) -> bool:
|
def _allow_cors_credentials(cors_origins: list[str]) -> bool:
|
||||||
|
|||||||
@@ -2,8 +2,7 @@ from fastapi import APIRouter, Depends
|
|||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from app.core.database import get_db
|
from app.core.database import get_db
|
||||||
from app.core.operation_guard import require_operations_enabled
|
from app.core.security import ApiPrincipal, require_api_key, require_operations_enabled
|
||||||
from app.core.security import ApiPrincipal, require_api_key
|
|
||||||
from app.modules.audit.constants import AuditSource
|
from app.modules.audit.constants import AuditSource
|
||||||
from app.modules.ai_agent.schemas import (
|
from app.modules.ai_agent.schemas import (
|
||||||
AIAskRequest,
|
AIAskRequest,
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ from sqlalchemy import JSON, DateTime, Integer, String, Text
|
|||||||
from sqlalchemy.orm import Mapped, mapped_column
|
from sqlalchemy.orm import Mapped, mapped_column
|
||||||
|
|
||||||
from app.core.constants import ActorValue
|
from app.core.constants import ActorValue
|
||||||
from app.core.db_base import Base
|
from app.core.database import Base
|
||||||
from app.core.time import utc_now
|
from app.core.utils.time import utc_now
|
||||||
from app.modules.ai_memory.constants import AIMemoryScope, AIMemorySource, AIMemoryStatus
|
from app.modules.ai_memory.constants import AIMemoryScope, AIMemorySource, AIMemoryStatus
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ from sqlalchemy.orm import Session
|
|||||||
|
|
||||||
from app.core.config import get_settings
|
from app.core.config import get_settings
|
||||||
from app.core.constants import ActorValue
|
from app.core.constants import ActorValue
|
||||||
from app.core.pagination import bounded_limit
|
from app.core.http.pagination import bounded_limit
|
||||||
from app.core.time import utc_now
|
from app.core.utils.time import utc_now
|
||||||
from app.modules.ai_memory.constants import (
|
from app.modules.ai_memory.constants import (
|
||||||
AI_MEMORY_CODE_PREFIX,
|
AI_MEMORY_CODE_PREFIX,
|
||||||
AI_MEMORY_MAX_CONTENT_LENGTH,
|
AI_MEMORY_MAX_CONTENT_LENGTH,
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ from sqlalchemy import DateTime, Integer, String, Text
|
|||||||
from sqlalchemy.orm import Mapped, mapped_column
|
from sqlalchemy.orm import Mapped, mapped_column
|
||||||
|
|
||||||
from app.core.constants import ActorValue
|
from app.core.constants import ActorValue
|
||||||
from app.core.db_base import Base
|
from app.core.database import Base
|
||||||
from app.core.time import utc_now
|
from app.core.utils.time import utc_now
|
||||||
from app.modules.audit.constants import AuditRiskLevel, AuditSource, AuditStatus
|
from app.modules.audit.constants import AuditRiskLevel, AuditSource, AuditStatus
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ from typing import Any
|
|||||||
from sqlalchemy import select
|
from sqlalchemy import select
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from app.core.pagination import bounded_limit
|
from app.core.http.pagination import bounded_limit
|
||||||
from app.core.request_context import get_request_id
|
from app.core.http.request_context import get_request_id
|
||||||
from app.modules.audit.constants import AUDIT_REDACTED_VALUE, AUDIT_SENSITIVE_KEYS
|
from app.modules.audit.constants import AUDIT_REDACTED_VALUE, AUDIT_SENSITIVE_KEYS
|
||||||
from app.modules.audit.models import AuditLog
|
from app.modules.audit.models import AuditLog
|
||||||
from app.modules.audit.schemas import AuditLogCreate
|
from app.modules.audit.schemas import AuditLogCreate
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ from sqlalchemy import JSON, Date, DateTime, Integer, Numeric, String, Text
|
|||||||
from sqlalchemy.orm import Mapped, mapped_column
|
from sqlalchemy.orm import Mapped, mapped_column
|
||||||
|
|
||||||
from app.core.constants import ActorValue
|
from app.core.constants import ActorValue
|
||||||
from app.core.db_base import Base
|
from app.core.database import Base
|
||||||
from app.core.time import utc_now
|
from app.core.utils.time import utc_now
|
||||||
from app.modules.business.constants import (
|
from app.modules.business.constants import (
|
||||||
AccountType,
|
AccountType,
|
||||||
PriorityValue,
|
PriorityValue,
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ from fastapi import status as http_status
|
|||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from app.core.database import get_db
|
from app.core.database import get_db
|
||||||
from app.core.masking import mask_configured
|
from app.core.http.masking import mask_configured
|
||||||
from app.core.security import require_api_key
|
from app.core.security import require_api_key
|
||||||
from app.modules.business.constants import BusinessField, BusinessResponseKey
|
from app.modules.business.constants import BusinessField, BusinessResponseKey
|
||||||
from app.modules.business.registry import supported_domain_values
|
from app.modules.business.registry import supported_domain_values
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ from sqlalchemy import Select, func, select
|
|||||||
from sqlalchemy.sql.schema import Column
|
from sqlalchemy.sql.schema import Column
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from app.core.pagination import bounded_limit, bounded_offset
|
from app.core.http.pagination import bounded_limit, bounded_offset
|
||||||
from app.modules.business.registry import get_domain_model, get_writable_fields
|
from app.modules.business.registry import get_domain_model, get_writable_fields
|
||||||
from app.modules.business.constants import (
|
from app.modules.business.constants import (
|
||||||
INVALID_FIELD_VALUE_TEMPLATE,
|
INVALID_FIELD_VALUE_TEMPLATE,
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ from fastapi import APIRouter, Depends
|
|||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from app.core.database import get_db
|
from app.core.database import get_db
|
||||||
from app.core.masking import mask_configured
|
from app.core.http.masking import mask_configured
|
||||||
from app.core.security import ApiPrincipal, require_api_key
|
from app.core.security import ApiPrincipal, require_api_key
|
||||||
from app.modules.dashboard.service import DashboardService
|
from app.modules.dashboard.service import DashboardService
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ from sqlalchemy import JSON, DateTime, Integer, String, Text
|
|||||||
from sqlalchemy.orm import Mapped, mapped_column
|
from sqlalchemy.orm import Mapped, mapped_column
|
||||||
|
|
||||||
from app.core.constants import ActorValue
|
from app.core.constants import ActorValue
|
||||||
from app.core.db_base import Base
|
from app.core.database import Base
|
||||||
from app.core.time import utc_now
|
from app.core.utils.time import utc_now
|
||||||
from app.modules.events.constants import EventSource, EventStatus
|
from app.modules.events.constants import EventSource, EventStatus
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ from sqlalchemy.orm import Session
|
|||||||
|
|
||||||
from app.core.config import get_settings
|
from app.core.config import get_settings
|
||||||
from app.core.constants import ActorValue
|
from app.core.constants import ActorValue
|
||||||
from app.core.pagination import bounded_limit
|
from app.core.http.pagination import bounded_limit
|
||||||
from app.core.time import utc_now
|
from app.core.utils.time import utc_now
|
||||||
from app.modules.audit.constants import (
|
from app.modules.audit.constants import (
|
||||||
AuditAction,
|
AuditAction,
|
||||||
AuditRiskLevel,
|
AuditRiskLevel,
|
||||||
@@ -189,13 +189,15 @@ class EventService:
|
|||||||
|
|
||||||
def retry_event(self, event_id: str, actor: str = ActorValue.API) -> DomainEvent:
|
def retry_event(self, event_id: str, actor: str = ActorValue.API) -> DomainEvent:
|
||||||
record = self.get_event(event_id)
|
record = self.get_event(event_id)
|
||||||
if record.status == EventStatus.PROCESSED or not self._can_attempt(record):
|
if record.status == EventStatus.PROCESSED:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=status.HTTP_409_CONFLICT,
|
status_code=status.HTTP_409_CONFLICT,
|
||||||
detail=EventErrorDetail.EVENT_NOT_RETRYABLE,
|
detail=EventErrorDetail.EVENT_NOT_RETRYABLE,
|
||||||
)
|
)
|
||||||
record.status = EventStatus.PENDING
|
record.status = EventStatus.PENDING
|
||||||
record.actor = actor
|
record.actor = actor
|
||||||
|
record.attempts = 0
|
||||||
|
record.max_attempts = record.max_attempts or get_settings().event_dispatch_max_attempts
|
||||||
record.last_error = None
|
record.last_error = None
|
||||||
record.locked_by = None
|
record.locked_by = None
|
||||||
record.locked_until = None
|
record.locked_until = None
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ from datetime import datetime
|
|||||||
from sqlalchemy import DateTime, Integer, String
|
from sqlalchemy import DateTime, Integer, String
|
||||||
from sqlalchemy.orm import Mapped, mapped_column
|
from sqlalchemy.orm import Mapped, mapped_column
|
||||||
|
|
||||||
from app.core.db_base import Base
|
from app.core.database import Base
|
||||||
from app.core.time import utc_now
|
from app.core.utils.time import utc_now
|
||||||
|
|
||||||
|
|
||||||
class FeishuEventReceipt(Base):
|
class FeishuEventReceipt(Base):
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
from fastapi import APIRouter, Depends, Query
|
from fastapi import APIRouter, Depends, Query
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
|
from app.core.background.task_queue import enqueue_legacy_project_sync, enqueue_legacy_task_sync
|
||||||
from app.core.database import get_db
|
from app.core.database import get_db
|
||||||
from app.core.masking import mask_configured
|
from app.core.http.masking import mask_configured
|
||||||
from app.core.operation_guard import require_operations_enabled
|
from app.core.security import ApiPrincipal, require_api_key, require_operations_enabled
|
||||||
from app.core.security import ApiPrincipal, require_api_key
|
|
||||||
from app.core.task_queue import enqueue_legacy_project_sync, enqueue_legacy_task_sync
|
|
||||||
from app.modules.legacy_mysql.schemas import (
|
from app.modules.legacy_mysql.schemas import (
|
||||||
LegacyProjectSyncRequest,
|
LegacyProjectSyncRequest,
|
||||||
LegacyProjectSyncResult,
|
LegacyProjectSyncResult,
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ from sqlalchemy.orm import Session
|
|||||||
from app.core.constants import ActorValue, ApiStatus
|
from app.core.constants import ActorValue, ApiStatus
|
||||||
from app.core.config import get_settings
|
from app.core.config import get_settings
|
||||||
from app.core.database import legacy_engine
|
from app.core.database import legacy_engine
|
||||||
from app.core.pagination import bounded_limit
|
from app.core.http.pagination import bounded_limit
|
||||||
from app.core.time import utc_now
|
from app.core.utils.time import utc_now
|
||||||
from app.modules.audit.constants import AuditAction, AuditRiskLevel, AuditSource, AuditStatus
|
from app.modules.audit.constants import AuditAction, AuditRiskLevel, AuditSource, AuditStatus
|
||||||
from app.modules.audit.schemas import AuditLogCreate
|
from app.modules.audit.schemas import AuditLogCreate
|
||||||
from app.modules.audit.service import AuditService
|
from app.modules.audit.service import AuditService
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ from datetime import datetime
|
|||||||
from sqlalchemy import DateTime, Integer, String
|
from sqlalchemy import DateTime, Integer, String
|
||||||
from sqlalchemy.orm import Mapped, mapped_column
|
from sqlalchemy.orm import Mapped, mapped_column
|
||||||
|
|
||||||
from app.core.db_base import Base
|
from app.core.database import Base
|
||||||
from app.core.time import utc_now
|
from app.core.utils.time import utc_now
|
||||||
|
|
||||||
|
|
||||||
class SystemHeartbeat(Base):
|
class SystemHeartbeat(Base):
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ from sqlalchemy.orm import Session
|
|||||||
|
|
||||||
from app.core.config import get_settings
|
from app.core.config import get_settings
|
||||||
from app.core.constants import ActorValue
|
from app.core.constants import ActorValue
|
||||||
from app.core.time import utc_now
|
from app.core.utils.time import utc_now
|
||||||
from app.modules.ai_memory.service import AIMemoryService
|
from app.modules.ai_memory.service import AIMemoryService
|
||||||
from app.modules.audit.constants import (
|
from app.modules.audit.constants import (
|
||||||
AuditAction,
|
AuditAction,
|
||||||
|
|||||||
@@ -3,16 +3,15 @@ from datetime import date
|
|||||||
from fastapi import APIRouter, Depends
|
from fastapi import APIRouter, Depends
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
|
from app.core.background.task_queue import enqueue_daily_brief_push, enqueue_project_weekly_push
|
||||||
from app.core.database import get_db
|
from app.core.database import get_db
|
||||||
from app.core.operation_guard import require_operations_enabled
|
from app.core.security import ApiPrincipal, require_api_key, require_operations_enabled
|
||||||
from app.core.security import ApiPrincipal, require_api_key
|
from app.modules.reports.constants import ReportPushKey
|
||||||
from app.core.task_queue import enqueue_daily_brief_push, enqueue_project_weekly_push
|
|
||||||
from app.modules.reports.schemas import (
|
from app.modules.reports.schemas import (
|
||||||
PushReportRequest,
|
PushReportRequest,
|
||||||
ReportResponse,
|
ReportResponse,
|
||||||
WorkReportGenerateRequest,
|
WorkReportGenerateRequest,
|
||||||
)
|
)
|
||||||
from app.modules.reports.constants import ReportPushKey
|
|
||||||
from app.modules.reports.service import ReportService
|
from app.modules.reports.service import ReportService
|
||||||
|
|
||||||
router = APIRouter(dependencies=[Depends(require_api_key)])
|
router = APIRouter(dependencies=[Depends(require_api_key)])
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ from sqlalchemy import func, or_, select
|
|||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from app.core.constants import ActorValue
|
from app.core.constants import ActorValue
|
||||||
from app.core.pagination import bounded_limit
|
from app.core.http.pagination import bounded_limit
|
||||||
from app.core.time import utc_now
|
from app.core.utils.time import utc_now
|
||||||
from app.modules.audit.constants import AuditAction, AuditSource, AuditTargetType
|
from app.modules.audit.constants import AuditAction, AuditSource, AuditTargetType
|
||||||
from app.modules.audit.schemas import AuditLogCreate
|
from app.modules.audit.schemas import AuditLogCreate
|
||||||
from app.modules.audit.service import AuditService
|
from app.modules.audit.service import AuditService
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
from fastapi import APIRouter, Depends, Query
|
from fastapi import APIRouter, Depends, Query
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
|
from app.core.background.task_queue import enqueue_risk_event_generation
|
||||||
from app.core.database import get_db
|
from app.core.database import get_db
|
||||||
from app.core.operation_guard import require_operations_enabled
|
from app.core.security import ApiPrincipal, require_api_key, require_operations_enabled
|
||||||
from app.core.security import ApiPrincipal, require_api_key
|
|
||||||
from app.core.task_queue import enqueue_risk_event_generation
|
|
||||||
from app.modules.risk.constants import RiskEventActionKey, RiskGenerationResultKey
|
from app.modules.risk.constants import RiskEventActionKey, RiskGenerationResultKey
|
||||||
from app.modules.risk.schemas import (
|
from app.modules.risk.schemas import (
|
||||||
RiskAssignRequest,
|
RiskAssignRequest,
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ from sqlalchemy import select
|
|||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from app.core.constants import ActorValue
|
from app.core.constants import ActorValue
|
||||||
from app.core.pagination import bounded_limit
|
from app.core.http.pagination import bounded_limit
|
||||||
from app.core.time import utc_now
|
from app.core.utils.time import utc_now
|
||||||
from app.modules.audit.constants import (
|
from app.modules.audit.constants import (
|
||||||
AuditAction,
|
AuditAction,
|
||||||
AuditRiskLevel,
|
AuditRiskLevel,
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ from sqlalchemy import JSON, DateTime, Integer, String
|
|||||||
from sqlalchemy.orm import Mapped, mapped_column
|
from sqlalchemy.orm import Mapped, mapped_column
|
||||||
|
|
||||||
from app.core.constants import ActorValue
|
from app.core.constants import ActorValue
|
||||||
from app.core.db_base import Base
|
from app.core.database import Base
|
||||||
from app.core.time import utc_now
|
from app.core.utils.time import utc_now
|
||||||
from app.modules.workflows.constants import WorkflowStatus
|
from app.modules.workflows.constants import WorkflowStatus
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ from sqlalchemy import func, select
|
|||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from app.core.constants import ActorValue
|
from app.core.constants import ActorValue
|
||||||
from app.core.pagination import bounded_limit
|
from app.core.http.pagination import bounded_limit
|
||||||
from app.core.time import utc_now
|
from app.core.utils.time import utc_now
|
||||||
from app.modules.business.service import serialize_model
|
from app.modules.business.service import serialize_model
|
||||||
from app.modules.workflows.constants import (
|
from app.modules.workflows.constants import (
|
||||||
WORKFLOW_ACTION_CODE_PREFIX,
|
WORKFLOW_ACTION_CODE_PREFIX,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from time import sleep
|
from time import sleep
|
||||||
|
|
||||||
from app.core.scheduler import create_scheduler
|
from app.core.background.scheduler import create_scheduler
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
DATABASE_URL: postgresql+psycopg://${POSTGRES_USER:-company_ai}:${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required}@db:5432/${POSTGRES_DB:-company_ai}
|
DATABASE_URL: postgresql+psycopg://${POSTGRES_USER:-company_ai}:${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required}@db:5432/${POSTGRES_DB:-company_ai}
|
||||||
REDIS_URL: redis://redis:6379/0
|
REDIS_URL: redis://redis:6379/0
|
||||||
|
SCHEDULER_ENABLED: "false"
|
||||||
ports:
|
ports:
|
||||||
- "8010:8010"
|
- "8010:8010"
|
||||||
depends_on:
|
depends_on:
|
||||||
@@ -72,6 +73,7 @@ services:
|
|||||||
DATABASE_URL: postgresql+psycopg://${POSTGRES_USER:-company_ai}:${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required}@db:5432/${POSTGRES_DB:-company_ai}
|
DATABASE_URL: postgresql+psycopg://${POSTGRES_USER:-company_ai}:${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required}@db:5432/${POSTGRES_DB:-company_ai}
|
||||||
REDIS_URL: redis://redis:6379/0
|
REDIS_URL: redis://redis:6379/0
|
||||||
TASK_QUEUE_ENABLED: "true"
|
TASK_QUEUE_ENABLED: "true"
|
||||||
|
SCHEDULER_ENABLED: "false"
|
||||||
command: ["celery", "-A", "app.tasks.celery_app", "worker", "--loglevel=info"]
|
command: ["celery", "-A", "app.tasks.celery_app", "worker", "--loglevel=info"]
|
||||||
depends_on:
|
depends_on:
|
||||||
db:
|
db:
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ from fastapi.testclient import TestClient
|
|||||||
|
|
||||||
from app.core.config import Settings, get_settings
|
from app.core.config import Settings, get_settings
|
||||||
from app.core.database import Base, SessionLocal, engine
|
from app.core.database import Base, SessionLocal, engine
|
||||||
from app.core.pagination import bounded_limit, bounded_offset
|
from app.core.http.pagination import bounded_limit, bounded_offset
|
||||||
from app.core.security import require_api_key, require_audit_api_key
|
from app.core.security import require_api_key, require_audit_api_key
|
||||||
from app.main import _allow_cors_credentials, app
|
from app.main import _allow_cors_credentials, app
|
||||||
from app.modules.audit.constants import AUDIT_REDACTED_VALUE
|
from app.modules.audit.constants import AUDIT_REDACTED_VALUE
|
||||||
@@ -268,6 +268,7 @@ def test_v3_event_retry_and_dispatch_pending_route() -> None:
|
|||||||
)
|
)
|
||||||
event.status = EventStatus.FAILED
|
event.status = EventStatus.FAILED
|
||||||
event.last_error = "transient"
|
event.last_error = "transient"
|
||||||
|
event.attempts = event.max_attempts
|
||||||
db.commit()
|
db.commit()
|
||||||
event_id = event.event_id
|
event_id = event.event_id
|
||||||
finally:
|
finally:
|
||||||
@@ -276,6 +277,7 @@ def test_v3_event_retry_and_dispatch_pending_route() -> None:
|
|||||||
retry_response = client.post(f"/api/v1/events/{event_id}/retry", headers=headers)
|
retry_response = client.post(f"/api/v1/events/{event_id}/retry", headers=headers)
|
||||||
assert retry_response.status_code == 200
|
assert retry_response.status_code == 200
|
||||||
assert retry_response.json()["event"]["status"] == EventStatus.PENDING
|
assert retry_response.json()["event"]["status"] == EventStatus.PENDING
|
||||||
|
assert retry_response.json()["event"]["attempts"] == 0
|
||||||
|
|
||||||
dispatch_response = client.post("/api/v1/events/dispatch-pending", headers=headers)
|
dispatch_response = client.post("/api/v1/events/dispatch-pending", headers=headers)
|
||||||
assert dispatch_response.status_code == 200
|
assert dispatch_response.status_code == 200
|
||||||
|
|||||||
Reference in New Issue
Block a user