semantics: complete DEF-to-region migration, fix regressions
- Convert legacy [DEF🆔Type] anchors to #region/#endregion across 329 files
- Reinstate _normalize_timestamp_value in sql_generator.py
- Fix MarkerLogger→logger migration in events.py (molecular CoT markers)
- Fix dataset_review orchestrator dependencies (_build_execution_snapshot)
- Fix config_manager stale-record deletion (moved to save path only)
- Add 77 missing [/DEF:] closers in 5 unbalanced test files
- Update assistant_chat.integration.test.js for #region format
- Apply molecular-cot-logging markers (REASON/REFLECT/EXPLORE) via logger.* methods
This commit is contained in:
@@ -1,11 +1,6 @@
|
||||
# #region MigrationApi [C:5] [TYPE Module] [SEMANTICS api, migration, dashboards, sync, dry-run]
|
||||
# @BRIEF HTTP contract layer for migration orchestration, settings, dry-run, and mapping sync endpoints.
|
||||
# @LAYER Infra
|
||||
# @PRE Backend core services initialized and Database session available.
|
||||
# @POST Migration tasks are enqueued or dry-run results are computed and returned.
|
||||
# @SIDE_EFFECT Enqueues long-running tasks, potentially mutates ResourceMapping table, and performs remote Superset API calls.
|
||||
# @DATA_CONTRACT [DashboardSelection | QueryParams] -> [TaskResponse | DryRunResult | MappingSummary]
|
||||
# @INVARIANT Migration endpoints never execute with invalid environment references and always return explicit HTTP errors on guard failures.
|
||||
# @LAYER: Infra
|
||||
# @RELATION DEPENDS_ON -> [AppDependencies]
|
||||
# @RELATION DEPENDS_ON -> [DatabaseModule]
|
||||
# @RELATION DEPENDS_ON -> [DashboardSelection]
|
||||
@@ -13,6 +8,11 @@
|
||||
# @RELATION DEPENDS_ON -> [MigrationDryRunService]
|
||||
# @RELATION DEPENDS_ON -> [IdMappingService]
|
||||
# @RELATION DEPENDS_ON -> [ResourceMapping]
|
||||
# @INVARIANT: Migration endpoints never execute with invalid environment references and always return explicit HTTP errors on guard failures.
|
||||
# @PRE: Backend core services initialized and Database session available.
|
||||
# @POST: Migration tasks are enqueued or dry-run results are computed and returned.
|
||||
# @SIDE_EFFECT: Enqueues long-running tasks, potentially mutates ResourceMapping table, and performs remote Superset API calls.
|
||||
# @DATA_CONTRACT: [DashboardSelection | QueryParams] -> [TaskResponse | DryRunResult | MappingSummary]
|
||||
# @TEST_CONTRACT: [DashboardSelection + configured envs] -> [task_id | dry-run result | sync summary]
|
||||
# @TEST_SCENARIO: [invalid_environment] -> [HTTP_400_or_404]
|
||||
# @TEST_SCENARIO: [valid_execution] -> [success_payload_with_required_fields]
|
||||
@@ -40,10 +40,10 @@ router = APIRouter(prefix="/api", tags=["migration"])
|
||||
|
||||
# #region get_dashboards [C:3] [TYPE Function]
|
||||
# @BRIEF Fetch dashboard metadata from a requested environment for migration selection UI.
|
||||
# @PRE env_id is provided and exists in configured environments.
|
||||
# @POST Returns List[DashboardMetadata] for the resolved environment; emits HTTP_404 when environment is absent.
|
||||
# @SIDE_EFFECT Reads environment configuration and performs remote Superset metadata retrieval over network.
|
||||
# @DATA_CONTRACT Input[str env_id] -> Output[List[DashboardMetadata]]
|
||||
# @PRE: env_id is provided and exists in configured environments.
|
||||
# @POST: Returns List[DashboardMetadata] for the resolved environment; emits HTTP_404 when environment is absent.
|
||||
# @SIDE_EFFECT: Reads environment configuration and performs remote Superset metadata retrieval over network.
|
||||
# @DATA_CONTRACT: Input[str env_id] -> Output[List[DashboardMetadata]]
|
||||
# @RELATION CALLS -> [SupersetClient.get_dashboards_summary]
|
||||
@router.get("/environments/{env_id}/dashboards", response_model=List[DashboardMetadata])
|
||||
async def get_dashboards(
|
||||
@@ -71,13 +71,13 @@ async def get_dashboards(
|
||||
|
||||
# #region execute_migration [C:5] [TYPE Function]
|
||||
# @BRIEF Validate migration selection and enqueue asynchronous migration task execution.
|
||||
# @PRE DashboardSelection payload is valid and both source/target environments exist.
|
||||
# @POST Returns {"task_id": str, "message": str} when task creation succeeds; emits HTTP_400/HTTP_500 on failure.
|
||||
# @SIDE_EFFECT Reads configuration, writes task record through task manager, and writes operational logs.
|
||||
# @DATA_CONTRACT Input[DashboardSelection] -> Output[Dict[str, str]]
|
||||
# @INVARIANT Migration task dispatch never occurs before source and target environment ids pass guard validation.
|
||||
# @PRE: DashboardSelection payload is valid and both source/target environments exist.
|
||||
# @POST: Returns {"task_id": str, "message": str} when task creation succeeds; emits HTTP_400/HTTP_500 on failure.
|
||||
# @SIDE_EFFECT: Reads configuration, writes task record through task manager, and writes operational logs.
|
||||
# @DATA_CONTRACT: Input[DashboardSelection] -> Output[Dict[str, str]]
|
||||
# @RELATION CALLS -> [create_task]
|
||||
# @RELATION DEPENDS_ON -> [DashboardSelection]
|
||||
# @INVARIANT: Migration task dispatch never occurs before source and target environment ids pass guard validation.
|
||||
@router.post("/migration/execute")
|
||||
async def execute_migration(
|
||||
selection: DashboardSelection,
|
||||
@@ -134,13 +134,13 @@ async def execute_migration(
|
||||
|
||||
# #region dry_run_migration [C:5] [TYPE Function]
|
||||
# @BRIEF Build pre-flight migration diff and risk summary without mutating target systems.
|
||||
# @PRE DashboardSelection is valid, source and target environments exist, differ, and selected_ids is non-empty.
|
||||
# @POST Returns deterministic dry-run payload; emits HTTP_400 for guard violations and HTTP_500 for orchestrator value errors.
|
||||
# @SIDE_EFFECT Reads local mappings from DB and fetches source/target metadata via Superset API.
|
||||
# @DATA_CONTRACT Input[DashboardSelection] -> Output[Dict[str, Any]]
|
||||
# @INVARIANT Dry-run flow remains read-only and rejects identical source/target environments before service execution.
|
||||
# @PRE: DashboardSelection is valid, source and target environments exist, differ, and selected_ids is non-empty.
|
||||
# @POST: Returns deterministic dry-run payload; emits HTTP_400 for guard violations and HTTP_500 for orchestrator value errors.
|
||||
# @SIDE_EFFECT: Reads local mappings from DB and fetches source/target metadata via Superset API.
|
||||
# @DATA_CONTRACT: Input[DashboardSelection] -> Output[Dict[str, Any]]
|
||||
# @RELATION DEPENDS_ON -> [DashboardSelection]
|
||||
# @RELATION DEPENDS_ON -> [MigrationDryRunService]
|
||||
# @INVARIANT: Dry-run flow remains read-only and rejects identical source/target environments before service execution.
|
||||
@router.post("/migration/dry-run", response_model=Dict[str, Any])
|
||||
async def dry_run_migration(
|
||||
selection: DashboardSelection,
|
||||
@@ -200,10 +200,10 @@ async def dry_run_migration(
|
||||
|
||||
# #region get_migration_settings [C:3] [TYPE Function]
|
||||
# @BRIEF Read and return configured migration synchronization cron expression.
|
||||
# @PRE Configuration store is available and requester has READ permission.
|
||||
# @POST Returns {"cron": str} reflecting current persisted settings value.
|
||||
# @SIDE_EFFECT Reads configuration from config manager.
|
||||
# @DATA_CONTRACT Input[None] -> Output[Dict[str, str]]
|
||||
# @PRE: Configuration store is available and requester has READ permission.
|
||||
# @POST: Returns {"cron": str} reflecting current persisted settings value.
|
||||
# @SIDE_EFFECT: Reads configuration from config manager.
|
||||
# @DATA_CONTRACT: Input[None] -> Output[Dict[str, str]]
|
||||
# @RELATION DEPENDS_ON -> [AppDependencies]
|
||||
@router.get("/migration/settings", response_model=Dict[str, str])
|
||||
async def get_migration_settings(
|
||||
@@ -221,10 +221,10 @@ async def get_migration_settings(
|
||||
|
||||
# #region update_migration_settings [C:3] [TYPE Function]
|
||||
# @BRIEF Validate and persist migration synchronization cron expression update.
|
||||
# @PRE Payload includes "cron" key and requester has WRITE permission.
|
||||
# @POST Returns {"cron": str, "status": "updated"} and persists updated cron value.
|
||||
# @SIDE_EFFECT Mutates configuration and writes persisted config through config manager.
|
||||
# @DATA_CONTRACT Input[Dict[str, str]] -> Output[Dict[str, str]]
|
||||
# @PRE: Payload includes "cron" key and requester has WRITE permission.
|
||||
# @POST: Returns {"cron": str, "status": "updated"} and persists updated cron value.
|
||||
# @SIDE_EFFECT: Mutates configuration and writes persisted config through config manager.
|
||||
# @DATA_CONTRACT: Input[Dict[str, str]] -> Output[Dict[str, str]]
|
||||
# @RELATION DEPENDS_ON -> [AppDependencies]
|
||||
@router.put("/migration/settings", response_model=Dict[str, str])
|
||||
async def update_migration_settings(
|
||||
@@ -252,10 +252,10 @@ async def update_migration_settings(
|
||||
|
||||
# #region get_resource_mappings [C:3] [TYPE Function]
|
||||
# @BRIEF Fetch synchronized resource mappings with optional filters and pagination for migration mappings view.
|
||||
# @PRE skip>=0, 1<=limit<=500, DB session is active, requester has READ permission.
|
||||
# @POST Returns {"items": [...], "total": int} where items reflect applied filters and pagination.
|
||||
# @SIDE_EFFECT Executes database read queries against ResourceMapping table.
|
||||
# @DATA_CONTRACT Input[QueryParams] -> Output[Dict[str, Any]]
|
||||
# @PRE: skip>=0, 1<=limit<=500, DB session is active, requester has READ permission.
|
||||
# @POST: Returns {"items": [...], "total": int} where items reflect applied filters and pagination.
|
||||
# @SIDE_EFFECT: Executes database read queries against ResourceMapping table.
|
||||
# @DATA_CONTRACT: Input[QueryParams] -> Output[Dict[str, Any]]
|
||||
# @RELATION DEPENDS_ON -> [ResourceMapping]
|
||||
@router.get("/migration/mappings-data", response_model=Dict[str, Any])
|
||||
async def get_resource_mappings(
|
||||
@@ -324,10 +324,10 @@ async def get_resource_mappings(
|
||||
|
||||
# #region trigger_sync_now [C:3] [TYPE Function]
|
||||
# @BRIEF Trigger immediate ID synchronization for every configured environment.
|
||||
# @PRE At least one environment is configured and requester has EXECUTE permission.
|
||||
# @POST Returns sync summary with synced/failed counts after attempting all environments.
|
||||
# @SIDE_EFFECT Upserts Environment rows, commits DB transaction, performs network sync calls, and writes logs.
|
||||
# @DATA_CONTRACT Input[None] -> Output[Dict[str, Any]]
|
||||
# @PRE: At least one environment is configured and requester has EXECUTE permission.
|
||||
# @POST: Returns sync summary with synced/failed counts after attempting all environments.
|
||||
# @SIDE_EFFECT: Upserts Environment rows, commits DB transaction, performs network sync calls, and writes logs.
|
||||
# @DATA_CONTRACT: Input[None] -> Output[Dict[str, Any]]
|
||||
# @RELATION DEPENDS_ON -> [IdMappingService]
|
||||
# @RELATION CALLS -> [sync_environment]
|
||||
@router.post("/migration/sync-now", response_model=Dict[str, Any])
|
||||
@@ -337,6 +337,7 @@ async def trigger_sync_now(
|
||||
_=Depends(has_permission("plugin:migration", "EXECUTE")),
|
||||
):
|
||||
with belief_scope("trigger_sync_now"):
|
||||
from ...core.logger import logger
|
||||
from ...models.mapping import Environment as EnvironmentModel
|
||||
|
||||
config = config_manager.get_config()
|
||||
@@ -356,8 +357,8 @@ async def trigger_sync_now(
|
||||
credentials_id=env.id, # Use env.id as credentials reference
|
||||
)
|
||||
db.add(db_env)
|
||||
logger.reason(
|
||||
f"Created environment row for {env.id}"
|
||||
logger.info(
|
||||
f"[trigger_sync_now][Action] Created environment row for {env.id}"
|
||||
)
|
||||
else:
|
||||
existing.name = env.name
|
||||
@@ -372,10 +373,10 @@ async def trigger_sync_now(
|
||||
client = SupersetClient(env)
|
||||
service.sync_environment(env.id, client)
|
||||
results["synced"].append(env.id)
|
||||
logger.reason(f"Synced environment {env.id}")
|
||||
logger.info(f"[trigger_sync_now][Action] Synced environment {env.id}")
|
||||
except Exception as e:
|
||||
results["failed"].append({"env_id": env.id, "error": str(e)})
|
||||
logger.explore(f"Failed to sync {env.id}", error=str(e))
|
||||
logger.error(f"[trigger_sync_now][Error] Failed to sync {env.id}: {e}")
|
||||
|
||||
return {
|
||||
"status": "completed",
|
||||
|
||||
Reference in New Issue
Block a user