From dc8605ce3fd5394df585ef4c9605f2867d3d1c77 Mon Sep 17 00:00:00 2001 From: JiuContinent Date: Thu, 9 Jul 2026 17:41:16 +0800 Subject: [PATCH] =?UTF-8?q?```=20refactor(core):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E6=A0=B8=E5=BF=83=E6=A8=A1=E5=9D=97=E7=BB=93=E6=9E=84=E5=B9=B6?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=AF=BC=E5=85=A5=E8=B7=AF=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将配置相关的设置从 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 模型导入路径 - 更新各模块中对重构后组件的引用路径 ``` --- alembic/env.py | 2 +- app/core/background/__init__.py | 1 + app/core/{ => background}/scheduler.py | 2 +- app/core/{ => background}/task_queue.py | 0 app/core/config/__init__.py | 3 ++ app/core/{config.py => config/settings.py} | 0 app/core/constants/__init__.py | 23 ++++++++++++++ .../{constants.py => constants/values.py} | 0 app/core/database/__init__.py | 30 +++++++++++++++++++ app/core/{db_base.py => database/base.py} | 0 app/core/{database.py => database/session.py} | 3 +- app/core/http/__init__.py | 1 + app/core/{ => http}/masking.py | 0 app/core/{ => http}/middleware.py | 2 +- app/core/{ => http}/pagination.py | 0 app/core/{ => http}/request_context.py | 0 app/core/security/__init__.py | 13 ++++++++ .../{security.py => security/api_keys.py} | 0 app/core/{ => security}/operation_guard.py | 0 app/core/utils/__init__.py | 1 + app/core/{ => utils}/time.py | 0 app/main.py | 4 +-- app/modules/ai_agent/routes.py | 3 +- app/modules/ai_memory/models.py | 4 +-- app/modules/ai_memory/service.py | 4 +-- app/modules/audit/models.py | 4 +-- app/modules/audit/service.py | 4 +-- app/modules/business/models.py | 4 +-- app/modules/business/routes.py | 2 +- app/modules/business/service.py | 2 +- app/modules/dashboard/routes.py | 2 +- app/modules/events/models.py | 4 +-- app/modules/events/service.py | 8 +++-- app/modules/feishu/models.py | 4 +-- app/modules/legacy_mysql/routes.py | 7 ++--- app/modules/legacy_mysql/service.py | 4 +-- app/modules/observability/models.py | 4 +-- app/modules/observability/service.py | 2 +- app/modules/reports/routes.py | 7 ++--- app/modules/reports/service.py | 4 +-- app/modules/risk/routes.py | 5 ++-- app/modules/risk/service.py | 4 +-- app/modules/workflows/models.py | 4 +-- app/modules/workflows/service.py | 4 +-- app/tools/run_scheduler.py | 2 +- docker-compose.yml | 2 ++ tests/test_smoke.py | 4 ++- 47 files changed, 129 insertions(+), 54 deletions(-) create mode 100644 app/core/background/__init__.py rename app/core/{ => background}/scheduler.py (99%) rename app/core/{ => background}/task_queue.py (100%) create mode 100644 app/core/config/__init__.py rename app/core/{config.py => config/settings.py} (100%) create mode 100644 app/core/constants/__init__.py rename app/core/{constants.py => constants/values.py} (100%) create mode 100644 app/core/database/__init__.py rename app/core/{db_base.py => database/base.py} (100%) rename app/core/{database.py => database/session.py} (97%) create mode 100644 app/core/http/__init__.py rename app/core/{ => http}/masking.py (100%) rename app/core/{ => http}/middleware.py (87%) rename app/core/{ => http}/pagination.py (100%) rename app/core/{ => http}/request_context.py (100%) create mode 100644 app/core/security/__init__.py rename app/core/{security.py => security/api_keys.py} (100%) rename app/core/{ => security}/operation_guard.py (100%) create mode 100644 app/core/utils/__init__.py rename app/core/{ => utils}/time.py (100%) diff --git a/alembic/env.py b/alembic/env.py index 6a91fe4..0eec56f 100644 --- a/alembic/env.py +++ b/alembic/env.py @@ -4,7 +4,7 @@ from alembic import context from sqlalchemy import engine_from_config, pool 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.audit import models as audit_models from app.modules.business import models as business_models diff --git a/app/core/background/__init__.py b/app/core/background/__init__.py new file mode 100644 index 0000000..aebb260 --- /dev/null +++ b/app/core/background/__init__.py @@ -0,0 +1 @@ +"""Background scheduler and queue helpers.""" diff --git a/app/core/scheduler.py b/app/core/background/scheduler.py similarity index 99% rename from app/core/scheduler.py rename to app/core/background/scheduler.py index 93964b8..bff71bd 100644 --- a/app/core/scheduler.py +++ b/app/core/background/scheduler.py @@ -33,7 +33,7 @@ def create_scheduler(app: FastAPI | None = None) -> Any: from apscheduler.schedulers.background import BackgroundScheduler from app.core.database import SessionLocal - from app.core.task_queue import ( + from app.core.background.task_queue import ( enqueue_daily_brief_push, enqueue_event_dispatch, enqueue_legacy_project_sync, diff --git a/app/core/task_queue.py b/app/core/background/task_queue.py similarity index 100% rename from app/core/task_queue.py rename to app/core/background/task_queue.py diff --git a/app/core/config/__init__.py b/app/core/config/__init__.py new file mode 100644 index 0000000..62f018f --- /dev/null +++ b/app/core/config/__init__.py @@ -0,0 +1,3 @@ +from app.core.config.settings import Settings, get_settings + +__all__ = ["Settings", "get_settings"] diff --git a/app/core/config.py b/app/core/config/settings.py similarity index 100% rename from app/core/config.py rename to app/core/config/settings.py diff --git a/app/core/constants/__init__.py b/app/core/constants/__init__.py new file mode 100644 index 0000000..8c5f654 --- /dev/null +++ b/app/core/constants/__init__.py @@ -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", +] diff --git a/app/core/constants.py b/app/core/constants/values.py similarity index 100% rename from app/core/constants.py rename to app/core/constants/values.py diff --git a/app/core/database/__init__.py b/app/core/database/__init__.py new file mode 100644 index 0000000..6c4ff81 --- /dev/null +++ b/app/core/database/__init__.py @@ -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}") diff --git a/app/core/db_base.py b/app/core/database/base.py similarity index 100% rename from app/core/db_base.py rename to app/core/database/base.py diff --git a/app/core/database.py b/app/core/database/session.py similarity index 97% rename from app/core/database.py rename to app/core/database/session.py index e559571..5003a0a 100644 --- a/app/core/database.py +++ b/app/core/database/session.py @@ -4,7 +4,8 @@ from sqlalchemy import create_engine from sqlalchemy.orm import Session, sessionmaker from app.core.config import get_settings -from app.core.db_base import Base + +from .base import Base settings = get_settings() diff --git a/app/core/http/__init__.py b/app/core/http/__init__.py new file mode 100644 index 0000000..05f0a3b --- /dev/null +++ b/app/core/http/__init__.py @@ -0,0 +1 @@ +"""HTTP middleware, masking, pagination, and request context helpers.""" diff --git a/app/core/masking.py b/app/core/http/masking.py similarity index 100% rename from app/core/masking.py rename to app/core/http/masking.py diff --git a/app/core/middleware.py b/app/core/http/middleware.py similarity index 87% rename from app/core/middleware.py rename to app/core/http/middleware.py index a7dd376..5edaaa8 100644 --- a/app/core/middleware.py +++ b/app/core/http/middleware.py @@ -4,7 +4,7 @@ from collections.abc import Callable from fastapi import Request, Response 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: diff --git a/app/core/pagination.py b/app/core/http/pagination.py similarity index 100% rename from app/core/pagination.py rename to app/core/http/pagination.py diff --git a/app/core/request_context.py b/app/core/http/request_context.py similarity index 100% rename from app/core/request_context.py rename to app/core/http/request_context.py diff --git a/app/core/security/__init__.py b/app/core/security/__init__.py new file mode 100644 index 0000000..f768bff --- /dev/null +++ b/app/core/security/__init__.py @@ -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", +] diff --git a/app/core/security.py b/app/core/security/api_keys.py similarity index 100% rename from app/core/security.py rename to app/core/security/api_keys.py diff --git a/app/core/operation_guard.py b/app/core/security/operation_guard.py similarity index 100% rename from app/core/operation_guard.py rename to app/core/security/operation_guard.py diff --git a/app/core/utils/__init__.py b/app/core/utils/__init__.py new file mode 100644 index 0000000..9b3c869 --- /dev/null +++ b/app/core/utils/__init__.py @@ -0,0 +1 @@ +"""Core utility helpers.""" diff --git a/app/core/time.py b/app/core/utils/time.py similarity index 100% rename from app/core/time.py rename to app/core/utils/time.py diff --git a/app/main.py b/app/main.py index 9a7ac9b..8fb373c 100644 --- a/app/main.py +++ b/app/main.py @@ -3,8 +3,8 @@ from fastapi.middleware.cors import CORSMiddleware from app.api.router import api_router from app.core.config import get_settings -from app.core.middleware import request_id_middleware -from app.core.scheduler import attach_scheduler +from app.core.http.middleware import request_id_middleware +from app.core.background.scheduler import attach_scheduler def _allow_cors_credentials(cors_origins: list[str]) -> bool: diff --git a/app/modules/ai_agent/routes.py b/app/modules/ai_agent/routes.py index 8b71f4a..f8bacb7 100644 --- a/app/modules/ai_agent/routes.py +++ b/app/modules/ai_agent/routes.py @@ -2,8 +2,7 @@ from fastapi import APIRouter, Depends from sqlalchemy.orm import Session 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 +from app.core.security import ApiPrincipal, require_api_key, require_operations_enabled from app.modules.audit.constants import AuditSource from app.modules.ai_agent.schemas import ( AIAskRequest, diff --git a/app/modules/ai_memory/models.py b/app/modules/ai_memory/models.py index e63d707..9117068 100644 --- a/app/modules/ai_memory/models.py +++ b/app/modules/ai_memory/models.py @@ -4,8 +4,8 @@ from sqlalchemy import JSON, DateTime, Integer, String, Text from sqlalchemy.orm import Mapped, mapped_column from app.core.constants import ActorValue -from app.core.db_base import Base -from app.core.time import utc_now +from app.core.database import Base +from app.core.utils.time import utc_now from app.modules.ai_memory.constants import AIMemoryScope, AIMemorySource, AIMemoryStatus diff --git a/app/modules/ai_memory/service.py b/app/modules/ai_memory/service.py index f6690a7..57e2512 100644 --- a/app/modules/ai_memory/service.py +++ b/app/modules/ai_memory/service.py @@ -5,8 +5,8 @@ from sqlalchemy.orm import Session from app.core.config import get_settings from app.core.constants import ActorValue -from app.core.pagination import bounded_limit -from app.core.time import utc_now +from app.core.http.pagination import bounded_limit +from app.core.utils.time import utc_now from app.modules.ai_memory.constants import ( AI_MEMORY_CODE_PREFIX, AI_MEMORY_MAX_CONTENT_LENGTH, diff --git a/app/modules/audit/models.py b/app/modules/audit/models.py index 99750db..73c4d6d 100644 --- a/app/modules/audit/models.py +++ b/app/modules/audit/models.py @@ -4,8 +4,8 @@ from sqlalchemy import DateTime, Integer, String, Text from sqlalchemy.orm import Mapped, mapped_column from app.core.constants import ActorValue -from app.core.db_base import Base -from app.core.time import utc_now +from app.core.database import Base +from app.core.utils.time import utc_now from app.modules.audit.constants import AuditRiskLevel, AuditSource, AuditStatus diff --git a/app/modules/audit/service.py b/app/modules/audit/service.py index 2c46e46..bebab68 100644 --- a/app/modules/audit/service.py +++ b/app/modules/audit/service.py @@ -4,8 +4,8 @@ from typing import Any from sqlalchemy import select from sqlalchemy.orm import Session -from app.core.pagination import bounded_limit -from app.core.request_context import get_request_id +from app.core.http.pagination import bounded_limit +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.models import AuditLog from app.modules.audit.schemas import AuditLogCreate diff --git a/app/modules/business/models.py b/app/modules/business/models.py index 9dd9d56..4a5d96a 100644 --- a/app/modules/business/models.py +++ b/app/modules/business/models.py @@ -5,8 +5,8 @@ from sqlalchemy import JSON, Date, DateTime, Integer, Numeric, String, Text from sqlalchemy.orm import Mapped, mapped_column from app.core.constants import ActorValue -from app.core.db_base import Base -from app.core.time import utc_now +from app.core.database import Base +from app.core.utils.time import utc_now from app.modules.business.constants import ( AccountType, PriorityValue, diff --git a/app/modules/business/routes.py b/app/modules/business/routes.py index 8b303b8..f9522cc 100644 --- a/app/modules/business/routes.py +++ b/app/modules/business/routes.py @@ -3,7 +3,7 @@ from fastapi import status as http_status from sqlalchemy.orm import Session 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.modules.business.constants import BusinessField, BusinessResponseKey from app.modules.business.registry import supported_domain_values diff --git a/app/modules/business/service.py b/app/modules/business/service.py index ac48d8f..76db64a 100644 --- a/app/modules/business/service.py +++ b/app/modules/business/service.py @@ -10,7 +10,7 @@ from sqlalchemy import Select, func, select from sqlalchemy.sql.schema import Column 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.constants import ( INVALID_FIELD_VALUE_TEMPLATE, diff --git a/app/modules/dashboard/routes.py b/app/modules/dashboard/routes.py index 8c15c75..4a57357 100644 --- a/app/modules/dashboard/routes.py +++ b/app/modules/dashboard/routes.py @@ -2,7 +2,7 @@ from fastapi import APIRouter, Depends from sqlalchemy.orm import Session 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.modules.dashboard.service import DashboardService diff --git a/app/modules/events/models.py b/app/modules/events/models.py index b820681..e7ec762 100644 --- a/app/modules/events/models.py +++ b/app/modules/events/models.py @@ -4,8 +4,8 @@ from sqlalchemy import JSON, DateTime, Integer, String, Text from sqlalchemy.orm import Mapped, mapped_column from app.core.constants import ActorValue -from app.core.db_base import Base -from app.core.time import utc_now +from app.core.database import Base +from app.core.utils.time import utc_now from app.modules.events.constants import EventSource, EventStatus diff --git a/app/modules/events/service.py b/app/modules/events/service.py index 9f9face..b055f4a 100644 --- a/app/modules/events/service.py +++ b/app/modules/events/service.py @@ -8,8 +8,8 @@ from sqlalchemy.orm import Session from app.core.config import get_settings from app.core.constants import ActorValue -from app.core.pagination import bounded_limit -from app.core.time import utc_now +from app.core.http.pagination import bounded_limit +from app.core.utils.time import utc_now from app.modules.audit.constants import ( AuditAction, AuditRiskLevel, @@ -189,13 +189,15 @@ class EventService: def retry_event(self, event_id: str, actor: str = ActorValue.API) -> DomainEvent: record = self.get_event(event_id) - if record.status == EventStatus.PROCESSED or not self._can_attempt(record): + if record.status == EventStatus.PROCESSED: raise HTTPException( status_code=status.HTTP_409_CONFLICT, detail=EventErrorDetail.EVENT_NOT_RETRYABLE, ) record.status = EventStatus.PENDING record.actor = actor + record.attempts = 0 + record.max_attempts = record.max_attempts or get_settings().event_dispatch_max_attempts record.last_error = None record.locked_by = None record.locked_until = None diff --git a/app/modules/feishu/models.py b/app/modules/feishu/models.py index 0d328ad..6c4ed2e 100644 --- a/app/modules/feishu/models.py +++ b/app/modules/feishu/models.py @@ -3,8 +3,8 @@ from datetime import datetime from sqlalchemy import DateTime, Integer, String from sqlalchemy.orm import Mapped, mapped_column -from app.core.db_base import Base -from app.core.time import utc_now +from app.core.database import Base +from app.core.utils.time import utc_now class FeishuEventReceipt(Base): diff --git a/app/modules/legacy_mysql/routes.py b/app/modules/legacy_mysql/routes.py index 53f1f18..0ecc28d 100644 --- a/app/modules/legacy_mysql/routes.py +++ b/app/modules/legacy_mysql/routes.py @@ -1,11 +1,10 @@ from fastapi import APIRouter, Depends, Query 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.masking import mask_configured -from app.core.operation_guard import 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.core.http.masking import mask_configured +from app.core.security import ApiPrincipal, require_api_key, require_operations_enabled from app.modules.legacy_mysql.schemas import ( LegacyProjectSyncRequest, LegacyProjectSyncResult, diff --git a/app/modules/legacy_mysql/service.py b/app/modules/legacy_mysql/service.py index 1800f55..447defd 100644 --- a/app/modules/legacy_mysql/service.py +++ b/app/modules/legacy_mysql/service.py @@ -11,8 +11,8 @@ from sqlalchemy.orm import Session from app.core.constants import ActorValue, ApiStatus from app.core.config import get_settings from app.core.database import legacy_engine -from app.core.pagination import bounded_limit -from app.core.time import utc_now +from app.core.http.pagination import bounded_limit +from app.core.utils.time import utc_now from app.modules.audit.constants import AuditAction, AuditRiskLevel, AuditSource, AuditStatus from app.modules.audit.schemas import AuditLogCreate from app.modules.audit.service import AuditService diff --git a/app/modules/observability/models.py b/app/modules/observability/models.py index 609a910..d5c48e5 100644 --- a/app/modules/observability/models.py +++ b/app/modules/observability/models.py @@ -3,8 +3,8 @@ from datetime import datetime from sqlalchemy import DateTime, Integer, String from sqlalchemy.orm import Mapped, mapped_column -from app.core.db_base import Base -from app.core.time import utc_now +from app.core.database import Base +from app.core.utils.time import utc_now class SystemHeartbeat(Base): diff --git a/app/modules/observability/service.py b/app/modules/observability/service.py index 6a212d8..459a9ed 100644 --- a/app/modules/observability/service.py +++ b/app/modules/observability/service.py @@ -6,7 +6,7 @@ from sqlalchemy.orm import Session from app.core.config import get_settings 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.audit.constants import ( AuditAction, diff --git a/app/modules/reports/routes.py b/app/modules/reports/routes.py index 42f7da9..27a2494 100644 --- a/app/modules/reports/routes.py +++ b/app/modules/reports/routes.py @@ -3,16 +3,15 @@ from datetime import date from fastapi import APIRouter, Depends 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.operation_guard import require_operations_enabled -from app.core.security import ApiPrincipal, require_api_key -from app.core.task_queue import enqueue_daily_brief_push, enqueue_project_weekly_push +from app.core.security import ApiPrincipal, require_api_key, require_operations_enabled +from app.modules.reports.constants import ReportPushKey from app.modules.reports.schemas import ( PushReportRequest, ReportResponse, WorkReportGenerateRequest, ) -from app.modules.reports.constants import ReportPushKey from app.modules.reports.service import ReportService router = APIRouter(dependencies=[Depends(require_api_key)]) diff --git a/app/modules/reports/service.py b/app/modules/reports/service.py index 3502528..16eb163 100644 --- a/app/modules/reports/service.py +++ b/app/modules/reports/service.py @@ -6,8 +6,8 @@ from sqlalchemy import func, or_, select from sqlalchemy.orm import Session from app.core.constants import ActorValue -from app.core.pagination import bounded_limit -from app.core.time import utc_now +from app.core.http.pagination import bounded_limit +from app.core.utils.time import utc_now from app.modules.audit.constants import AuditAction, AuditSource, AuditTargetType from app.modules.audit.schemas import AuditLogCreate from app.modules.audit.service import AuditService diff --git a/app/modules/risk/routes.py b/app/modules/risk/routes.py index 087fb31..5fe0703 100644 --- a/app/modules/risk/routes.py +++ b/app/modules/risk/routes.py @@ -1,10 +1,9 @@ from fastapi import APIRouter, Depends, Query 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.operation_guard import require_operations_enabled -from app.core.security import ApiPrincipal, require_api_key -from app.core.task_queue import enqueue_risk_event_generation +from app.core.security import ApiPrincipal, require_api_key, require_operations_enabled from app.modules.risk.constants import RiskEventActionKey, RiskGenerationResultKey from app.modules.risk.schemas import ( RiskAssignRequest, diff --git a/app/modules/risk/service.py b/app/modules/risk/service.py index 53160cc..7655b12 100644 --- a/app/modules/risk/service.py +++ b/app/modules/risk/service.py @@ -6,8 +6,8 @@ from sqlalchemy import select from sqlalchemy.orm import Session from app.core.constants import ActorValue -from app.core.pagination import bounded_limit -from app.core.time import utc_now +from app.core.http.pagination import bounded_limit +from app.core.utils.time import utc_now from app.modules.audit.constants import ( AuditAction, AuditRiskLevel, diff --git a/app/modules/workflows/models.py b/app/modules/workflows/models.py index 1f3bba2..55180d3 100644 --- a/app/modules/workflows/models.py +++ b/app/modules/workflows/models.py @@ -4,8 +4,8 @@ from sqlalchemy import JSON, DateTime, Integer, String from sqlalchemy.orm import Mapped, mapped_column from app.core.constants import ActorValue -from app.core.db_base import Base -from app.core.time import utc_now +from app.core.database import Base +from app.core.utils.time import utc_now from app.modules.workflows.constants import WorkflowStatus diff --git a/app/modules/workflows/service.py b/app/modules/workflows/service.py index 2058db0..1227cc0 100644 --- a/app/modules/workflows/service.py +++ b/app/modules/workflows/service.py @@ -5,8 +5,8 @@ from sqlalchemy import func, select from sqlalchemy.orm import Session from app.core.constants import ActorValue -from app.core.pagination import bounded_limit -from app.core.time import utc_now +from app.core.http.pagination import bounded_limit +from app.core.utils.time import utc_now from app.modules.business.service import serialize_model from app.modules.workflows.constants import ( WORKFLOW_ACTION_CODE_PREFIX, diff --git a/app/tools/run_scheduler.py b/app/tools/run_scheduler.py index 65772b4..850ecfd 100644 --- a/app/tools/run_scheduler.py +++ b/app/tools/run_scheduler.py @@ -1,6 +1,6 @@ from time import sleep -from app.core.scheduler import create_scheduler +from app.core.background.scheduler import create_scheduler def main() -> None: diff --git a/docker-compose.yml b/docker-compose.yml index aa4f750..49681d6 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -43,6 +43,7 @@ services: environment: 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 + SCHEDULER_ENABLED: "false" ports: - "8010:8010" 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} REDIS_URL: redis://redis:6379/0 TASK_QUEUE_ENABLED: "true" + SCHEDULER_ENABLED: "false" command: ["celery", "-A", "app.tasks.celery_app", "worker", "--loglevel=info"] depends_on: db: diff --git a/tests/test_smoke.py b/tests/test_smoke.py index 16c7df7..c463133 100644 --- a/tests/test_smoke.py +++ b/tests/test_smoke.py @@ -31,7 +31,7 @@ from fastapi.testclient import TestClient from app.core.config import Settings, get_settings 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.main import _allow_cors_credentials, app 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.last_error = "transient" + event.attempts = event.max_attempts db.commit() event_id = event.event_id 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) assert retry_response.status_code == 200 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) assert dispatch_response.status_code == 200