032: fix remaining sync→async propagation (17 call sites)

Core fixes:
  - service_datasource.py: fetch_datasource_metadata() → async
  - service.py: create_job(), update_job() → async (callers await)
  - _job_routes.py: await create_job/update_job

Maintenance scanners:
  - _dashboard_scanner.py: 4 functions → async (find_affected, _get_linked,
    _apply_filters, _resolve_title)
  - _chart_manager.py: 3 functions → async
  - _banner_renderer.py: rebuild_banner → async
  - _orchestrators.py: 3 orchestrators → async
  - maintenance_banner.py: await async calls

Migration:
  - dry_run_orchestrator.py: run(), _build_target_signatures() → async
  - risk_assessor.py: build_risks() → async
  - migration.py: await service.run()
  - mapping_service.py: sync_environment() → async

Dead code:
  - _helpers.py: _find_dashboard_id_by_slug marked DEPRECATED
This commit is contained in:
2026-06-05 08:56:37 +03:00
parent a5cd06546f
commit c7d8f4431e
13 changed files with 67 additions and 66 deletions

View File

@@ -73,7 +73,8 @@ class IdMappingService:
for env_id in environments:
client = superset_client_factory(env_id)
if client:
self.sync_environment(env_id, client)
import asyncio
asyncio.run(self.sync_environment(env_id, client))
self._sync_job = self.scheduler.add_job(
sync_all,
CronTrigger.from_crontab(cron_string),
@@ -96,7 +97,7 @@ class IdMappingService:
# @PARAM superset_client - Instance capable of hitting the Superset API.
# @PRE environment_id exists in the database.
# @POST ResourceMapping records for the environment are created or updated.
def sync_environment(
async def sync_environment(
self, environment_id: str, superset_client, incremental: bool = False
) -> None:
"""
@@ -150,7 +151,7 @@ class IdMappingService:
logger.debug(
f"[IdMappingService.sync_environment] Incremental sync since {since_dttm}"
)
resources = superset_client.get_all_resources(
resources = await superset_client.get_all_resources(
endpoint, since_dttm=since_dttm
)
# Track which UUIDs we see in this sync cycle

View File

@@ -54,7 +54,7 @@ class MigrationDryRunService:
# @PRE source/target clients are authenticated and selection validated by caller.
# @POST Returns JSON-serializable pre-flight payload with summary, diff and risk.
# @SIDE_EFFECT Reads source export archives and target metadata via network.
def run(
async def run(
self,
selection: DashboardSelection,
source_client: SupersetClient,
@@ -73,14 +73,14 @@ class MigrationDryRunService:
else {}
)
transformed = {"dashboards": {}, "charts": {}, "datasets": {}}
dashboards_preview = source_client.get_dashboards_summary()
dashboards_preview = await source_client.get_dashboards_summary()
selected_preview = {
item["id"]: item
for item in dashboards_preview
if item.get("id") in selection.selected_ids
}
for dashboard_id in selection.selected_ids:
exported_content, _ = source_client.export_dashboard(int(dashboard_id))
exported_content, _ = await source_client.export_dashboard(int(dashboard_id))
with create_temp_file(
content=exported_content, suffix=".zip"
) as source_zip, create_temp_file(suffix=".zip") as transformed_zip:
@@ -103,7 +103,7 @@ class MigrationDryRunService:
source_objects = {
key: list(value.values()) for key, value in transformed.items()
}
target_objects = self._build_target_signatures(target_client)
target_objects = await self._build_target_signatures(target_client)
diff = {
"dashboards": self._build_object_diff(
source_objects["dashboards"], target_objects["dashboards"]
@@ -115,7 +115,7 @@ class MigrationDryRunService:
source_objects["datasets"], target_objects["datasets"]
),
}
risk = self._build_risks(
risk = await self._build_risks(
source_objects, target_objects, diff, target_client
)
summary = {
@@ -219,10 +219,10 @@ class MigrationDryRunService:
# #endregion _build_object_diff
# #region _build_target_signatures [TYPE Function]
# @PURPOSE: Pull target metadata and normalize it into comparable signatures.
def _build_target_signatures(
async def _build_target_signatures(
self, client: SupersetClient
) -> dict[str, list[dict[str, Any]]]:
_, dashboards = client.get_dashboards(
_, dashboards = await client.get_dashboards(
query={
"columns": [
"uuid",
@@ -235,7 +235,7 @@ class MigrationDryRunService:
],
}
)
_, datasets = client.get_datasets(
_, datasets = await client.get_datasets(
query={
"columns": [
"uuid",
@@ -248,7 +248,7 @@ class MigrationDryRunService:
],
}
)
_, charts = client.get_charts(
_, charts = await client.get_charts(
query={
"columns": [
"uuid",
@@ -330,14 +330,14 @@ class MigrationDryRunService:
# #endregion _build_target_signatures
# #region _build_risks [TYPE Function]
# @PURPOSE: Build risk items for missing datasource, broken refs, overwrite, owner mismatch.
def _build_risks(
async def _build_risks(
self,
source_objects: dict[str, list[dict[str, Any]]],
target_objects: dict[str, list[dict[str, Any]]],
diff: dict[str, dict[str, list[dict[str, Any]]]],
target_client: SupersetClient,
) -> list[dict[str, Any]]:
return build_risks(source_objects, target_objects, diff, target_client)
return await build_risks(source_objects, target_objects, diff, target_client)
# #endregion _build_risks
# #endregion MigrationDryRunService
# #endregion MigrationDryRunOrchestratorModule

View File

@@ -96,7 +96,7 @@ def extract_owner_identifiers(owners: Any) -> list[str]:
# @DATA_CONTRACT Dict[str, Dict[str, List[Dict[str, Any]]]],
# @DATA_CONTRACT SupersetClient
# @DATA_CONTRACT ) -> List[Dict[str, Any]]
def build_risks(
async def build_risks(
source_objects: dict[str, list[dict[str, Any]]],
target_objects: dict[str, list[dict[str, Any]]],
diff: dict[str, dict[str, list[dict[str, Any]]]],
@@ -118,7 +118,7 @@ def build_risks(
)
target_dataset_uuids = set(index_by_uuid(target_objects["datasets"]).keys())
_, target_databases = target_client.get_databases(query={"columns": ["uuid"]})
_, target_databases = await target_client.get_databases(query={"columns": ["uuid"]})
target_database_uuids = {
str(item.get("uuid")) for item in target_databases if item.get("uuid")
}