refactor(typing): update handler signatures to use Dict and Any for improved type hinting

This commit is contained in:
bsiggel
2026-03-08 21:24:12 +00:00
parent 2532bd89ee
commit f392ec0f06
11 changed files with 79 additions and 36 deletions

View File

@@ -17,7 +17,7 @@ from calendar_sync_utils import (
import math import math
import time import time
from datetime import datetime from datetime import datetime
from typing import Any from typing import Any, Dict
from motia import queue, FlowContext from motia import queue, FlowContext
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
from services.advoware_service import AdvowareService from services.advoware_service import AdvowareService
@@ -33,7 +33,7 @@ config = {
} }
async def handler(input_data: dict, ctx: FlowContext): async def handler(input_data: Dict[str, Any], ctx: FlowContext) -> None:
""" """
Handler that fetches all employees, sorts by last sync time, Handler that fetches all employees, sorts by last sync time,
and emits calendar_sync_employee events for the oldest ones. and emits calendar_sync_employee events for the oldest ones.

View File

@@ -9,6 +9,7 @@ from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent)) sys.path.insert(0, str(Path(__file__).parent))
from calendar_sync_utils import log_operation from calendar_sync_utils import log_operation
from typing import Dict, Any
from motia import cron, FlowContext from motia import cron, FlowContext
@@ -23,7 +24,7 @@ config = {
} }
async def handler(input_data: dict, ctx: FlowContext): async def handler(input_data: Dict[str, Any], ctx: FlowContext) -> None:
"""Cron handler that triggers the calendar sync cascade.""" """Cron handler that triggers the calendar sync cascade."""
try: try:
log_operation('info', "Calendar Sync Cron: Starting to emit sync-all event", context=ctx) log_operation('info', "Calendar Sync Cron: Starting to emit sync-all event", context=ctx)
@@ -37,14 +38,6 @@ async def handler(input_data: dict, ctx: FlowContext):
}) })
log_operation('info', "Calendar Sync Cron: Emitted sync-all event", context=ctx) log_operation('info', "Calendar Sync Cron: Emitted sync-all event", context=ctx)
return {
'status': 'completed',
'triggered_by': 'cron'
}
except Exception as e: except Exception as e:
log_operation('error', f"Fehler beim Cron-Job: {e}", context=ctx) log_operation('error', f"Fehler beim Cron-Job: {e}", context=ctx)
return {
'status': 'error',
'error': str(e)
}

View File

@@ -14,6 +14,7 @@ import asyncio
import os import os
import datetime import datetime
from datetime import timedelta from datetime import timedelta
from typing import Dict, Any
import pytz import pytz
import backoff import backoff
import time import time
@@ -945,14 +946,14 @@ config = {
} }
async def handler(input_data: dict, ctx: FlowContext): async def handler(input_data: Dict[str, Any], ctx: FlowContext) -> None:
"""Main event handler for calendar sync.""" """Main event handler for calendar sync."""
start_time = time.time() start_time = time.time()
kuerzel = input_data.get('kuerzel') kuerzel = input_data.get('kuerzel')
if not kuerzel: if not kuerzel:
log_operation('error', "No kuerzel provided in event", context=ctx) log_operation('error', "No kuerzel provided in event", context=ctx)
return {'status': 400, 'body': {'error': 'No kuerzel provided'}} return
log_operation('info', f"Starting calendar sync for employee {kuerzel}", context=ctx) log_operation('info', f"Starting calendar sync for employee {kuerzel}", context=ctx)

View File

@@ -34,7 +34,7 @@ config = {
} }
async def handler(event_data: Dict[str, Any], ctx: FlowContext[Any]): async def handler(event_data: Dict[str, Any], ctx: FlowContext[Any]) -> None:
"""Zentraler Sync-Handler für Bankverbindungen""" """Zentraler Sync-Handler für Bankverbindungen"""
entity_id = event_data.get('entity_id') entity_id = event_data.get('entity_id')

View File

@@ -25,7 +25,7 @@ config = {
} }
async def handler(input_data: Dict[str, Any], ctx: FlowContext): async def handler(input_data: Dict[str, Any], ctx: FlowContext) -> None:
""" """
Cron-Handler: Findet alle Beteiligte die Sync benötigen und emittiert Events Cron-Handler: Findet alle Beteiligte die Sync benötigen und emittiert Events
""" """

View File

@@ -23,8 +23,11 @@ async def handler(request: ApiRequest, ctx: FlowContext[Any]) -> ApiResponse:
try: try:
payload = request.body or [] payload = request.body or []
ctx.logger.info("VMH Webhook Bankverbindungen Create empfangen") ctx.logger.info("=" * 80)
ctx.logger.info("📥 VMH WEBHOOK: BANKVERBINDUNGEN CREATE")
ctx.logger.info("=" * 80)
ctx.logger.info(f"Payload: {json.dumps(payload, indent=2, ensure_ascii=False)}") ctx.logger.info(f"Payload: {json.dumps(payload, indent=2, ensure_ascii=False)}")
ctx.logger.info("=" * 80)
# Sammle alle IDs aus dem Batch # Sammle alle IDs aus dem Batch
entity_ids = set() entity_ids = set()
@@ -50,7 +53,8 @@ async def handler(request: ApiRequest, ctx: FlowContext[Any]) -> ApiResponse:
} }
}) })
ctx.logger.info(f"VMH Create Webhook verarbeitet: {len(entity_ids)} Events emittiert") ctx.logger.info("VMH Create Webhook verarbeitet: "
f"{len(entity_ids)} Events emittiert")
return ApiResponse( return ApiResponse(
status=200, status=200,
@@ -62,7 +66,10 @@ async def handler(request: ApiRequest, ctx: FlowContext[Any]) -> ApiResponse:
) )
except Exception as e: except Exception as e:
ctx.logger.error(f"Fehler beim Verarbeiten des VMH Create Webhooks: {e}") ctx.logger.error("=" * 80)
ctx.logger.error("❌ FEHLER: BANKVERBINDUNGEN CREATE WEBHOOK")
ctx.logger.error(f"Error: {e}")
ctx.logger.error("=" * 80)
return ApiResponse( return ApiResponse(
status=500, status=500,
body={'error': 'Internal server error', 'details': str(e)} body={'error': 'Internal server error', 'details': str(e)}

View File

@@ -23,8 +23,11 @@ async def handler(request: ApiRequest, ctx: FlowContext[Any]) -> ApiResponse:
try: try:
payload = request.body or [] payload = request.body or []
ctx.logger.info("VMH Webhook Bankverbindungen Delete empfangen") ctx.logger.info("=" * 80)
ctx.logger.info("📥 VMH WEBHOOK: BANKVERBINDUNGEN DELETE")
ctx.logger.info("=" * 80)
ctx.logger.info(f"Payload: {json.dumps(payload, indent=2, ensure_ascii=False)}") ctx.logger.info(f"Payload: {json.dumps(payload, indent=2, ensure_ascii=False)}")
ctx.logger.info("=" * 80)
# Sammle alle IDs # Sammle alle IDs
entity_ids = set() entity_ids = set()
@@ -50,7 +53,8 @@ async def handler(request: ApiRequest, ctx: FlowContext[Any]) -> ApiResponse:
} }
}) })
ctx.logger.info(f"VMH Delete Webhook verarbeitet: {len(entity_ids)} Events emittiert") ctx.logger.info("VMH Delete Webhook verarbeitet: "
f"{len(entity_ids)} Events emittiert")
return ApiResponse( return ApiResponse(
status=200, status=200,
@@ -62,7 +66,10 @@ async def handler(request: ApiRequest, ctx: FlowContext[Any]) -> ApiResponse:
) )
except Exception as e: except Exception as e:
ctx.logger.error(f"Fehler beim Verarbeiten des VMH Delete Webhooks: {e}") ctx.logger.error("=" * 80)
ctx.logger.error("❌ FEHLER: BANKVERBINDUNGEN DELETE WEBHOOK")
ctx.logger.error(f"Error: {e}")
ctx.logger.error("=" * 80)
return ApiResponse( return ApiResponse(
status=500, status=500,
body={'error': 'Internal server error', 'details': str(e)} body={'error': 'Internal server error', 'details': str(e)}

View File

@@ -23,8 +23,11 @@ async def handler(request: ApiRequest, ctx: FlowContext[Any]) -> ApiResponse:
try: try:
payload = request.body or [] payload = request.body or []
ctx.logger.info("VMH Webhook Bankverbindungen Update empfangen") ctx.logger.info("=" * 80)
ctx.logger.info("📥 VMH WEBHOOK: BANKVERBINDUNGEN UPDATE")
ctx.logger.info("=" * 80)
ctx.logger.info(f"Payload: {json.dumps(payload, indent=2, ensure_ascii=False)}") ctx.logger.info(f"Payload: {json.dumps(payload, indent=2, ensure_ascii=False)}")
ctx.logger.info("=" * 80)
# Sammle alle IDs # Sammle alle IDs
entity_ids = set() entity_ids = set()
@@ -50,7 +53,8 @@ async def handler(request: ApiRequest, ctx: FlowContext[Any]) -> ApiResponse:
} }
}) })
ctx.logger.info(f"VMH Update Webhook verarbeitet: {len(entity_ids)} Events emittiert") ctx.logger.info("VMH Update Webhook verarbeitet: "
f"{len(entity_ids)} Events emittiert")
return ApiResponse( return ApiResponse(
status=200, status=200,
@@ -62,7 +66,10 @@ async def handler(request: ApiRequest, ctx: FlowContext[Any]) -> ApiResponse:
) )
except Exception as e: except Exception as e:
ctx.logger.error(f"Fehler beim Verarbeiten des VMH Update Webhooks: {e}") ctx.logger.error("=" * 80)
ctx.logger.error("❌ FEHLER: BANKVERBINDUNGEN UPDATE WEBHOOK")
ctx.logger.error(f"Error: {e}")
ctx.logger.error("=" * 80)
return ApiResponse( return ApiResponse(
status=500, status=500,
body={'error': 'Internal server error', 'details': str(e)} body={'error': 'Internal server error', 'details': str(e)}

View File

@@ -23,8 +23,11 @@ async def handler(request: ApiRequest, ctx: FlowContext[Any]) -> ApiResponse:
try: try:
payload = request.body or [] payload = request.body or []
ctx.logger.info("VMH Webhook Beteiligte Delete empfangen") ctx.logger.info("=" * 80)
ctx.logger.info("📥 VMH WEBHOOK: BETEILIGTE DELETE")
ctx.logger.info("=" * 80)
ctx.logger.info(f"Payload: {json.dumps(payload, indent=2, ensure_ascii=False)}") ctx.logger.info(f"Payload: {json.dumps(payload, indent=2, ensure_ascii=False)}")
ctx.logger.info("=" * 80)
# Sammle alle IDs aus dem Batch # Sammle alle IDs aus dem Batch
entity_ids = set() entity_ids = set()
@@ -50,7 +53,8 @@ async def handler(request: ApiRequest, ctx: FlowContext[Any]) -> ApiResponse:
} }
}) })
ctx.logger.info(f"VMH Delete Webhook verarbeitet: {len(entity_ids)} Events emittiert") ctx.logger.info("VMH Delete Webhook verarbeitet: "
f"{len(entity_ids)} Events emittiert")
return ApiResponse( return ApiResponse(
status=200, status=200,
@@ -62,7 +66,10 @@ async def handler(request: ApiRequest, ctx: FlowContext[Any]) -> ApiResponse:
) )
except Exception as e: except Exception as e:
ctx.logger.error(f"Fehler beim Delete-Webhook: {e}") ctx.logger.error("=" * 80)
ctx.logger.error("❌ FEHLER: BETEILIGTE DELETE WEBHOOK")
ctx.logger.error(f"Error: {e}")
ctx.logger.error("=" * 80)
return ApiResponse( return ApiResponse(
status=500, status=500,
body={'error': 'Internal server error', 'details': str(e)} body={'error': 'Internal server error', 'details': str(e)}

View File

@@ -25,17 +25,21 @@ async def handler(request: ApiRequest, ctx: FlowContext[Any]) -> ApiResponse:
try: try:
payload = request.body or [] payload = request.body or []
ctx.logger.info("VMH Webhook Document Create empfangen") ctx.logger.info("=" * 80)
ctx.logger.info("📥 VMH WEBHOOK: DOCUMENT CREATE")
ctx.logger.info("=" * 80)
ctx.logger.debug(f"Payload: {json.dumps(payload, indent=2, ensure_ascii=False)}") ctx.logger.debug(f"Payload: {json.dumps(payload, indent=2, ensure_ascii=False)}")
# Sammle alle IDs aus dem Batch # Sammle alle IDs aus dem Batch
entity_ids = set() entity_ids = set()
entity_type = 'CDokumente' # Default
if isinstance(payload, list): if isinstance(payload, list):
for entity in payload: for entity in payload:
if isinstance(entity, dict) and 'id' in entity: if isinstance(entity, dict) and 'id' in entity:
entity_ids.add(entity['id']) entity_ids.add(entity['id'])
# Extrahiere entityType falls vorhanden # Take entityType from first entity if present
if entity_type == 'CDokumente':
entity_type = entity.get('entityType', 'CDokumente') entity_type = entity.get('entityType', 'CDokumente')
elif isinstance(payload, dict) and 'id' in payload: elif isinstance(payload, dict) and 'id' in payload:
entity_ids.add(payload['id']) entity_ids.add(payload['id'])
@@ -49,12 +53,15 @@ async def handler(request: ApiRequest, ctx: FlowContext[Any]) -> ApiResponse:
'topic': 'vmh.document.create', 'topic': 'vmh.document.create',
'data': { 'data': {
'entity_id': entity_id, 'entity_id': entity_id,
'entity_type': entity_type if 'entity_type' in locals() else 'CDokumente', 'entity_type': entity_type,
'action': 'create', 'action': 'create',
'timestamp': payload[0].get('modifiedAt') if isinstance(payload, list) and payload else None 'timestamp': payload[0].get('modifiedAt') if isinstance(payload, list) and payload else None
} }
}) })
ctx.logger.info("✅ Document Create Webhook verarbeitet: "
f"{len(entity_ids)} Events emittiert")
return ApiResponse( return ApiResponse(
status=200, status=200,
body={ body={
@@ -65,8 +72,11 @@ async def handler(request: ApiRequest, ctx: FlowContext[Any]) -> ApiResponse:
) )
except Exception as e: except Exception as e:
ctx.logger.error(f"Fehler im Document Create Webhook: {e}") ctx.logger.error("=" * 80)
ctx.logger.error("❌ FEHLER: DOCUMENT CREATE WEBHOOK")
ctx.logger.error(f"Error: {e}")
ctx.logger.error(f"Payload: {request.body}") ctx.logger.error(f"Payload: {request.body}")
ctx.logger.error("=" * 80)
return ApiResponse( return ApiResponse(
status=500, status=500,

View File

@@ -25,16 +25,21 @@ async def handler(request: ApiRequest, ctx: FlowContext[Any]) -> ApiResponse:
try: try:
payload = request.body or [] payload = request.body or []
ctx.logger.info("VMH Webhook Document Delete empfangen") ctx.logger.info("=" * 80)
ctx.logger.info("📥 VMH WEBHOOK: DOCUMENT DELETE")
ctx.logger.info("=" * 80)
ctx.logger.debug(f"Payload: {json.dumps(payload, indent=2, ensure_ascii=False)}") ctx.logger.debug(f"Payload: {json.dumps(payload, indent=2, ensure_ascii=False)}")
# Sammle alle IDs aus dem Batch # Sammle alle IDs aus dem Batch
entity_ids = set() entity_ids = set()
entity_type = 'CDokumente' # Default
if isinstance(payload, list): if isinstance(payload, list):
for entity in payload: for entity in payload:
if isinstance(entity, dict) and 'id' in entity: if isinstance(entity, dict) and 'id' in entity:
entity_ids.add(entity['id']) entity_ids.add(entity['id'])
# Take entityType from first entity if present
if entity_type == 'CDokumente':
entity_type = entity.get('entityType', 'CDokumente') entity_type = entity.get('entityType', 'CDokumente')
elif isinstance(payload, dict) and 'id' in payload: elif isinstance(payload, dict) and 'id' in payload:
entity_ids.add(payload['id']) entity_ids.add(payload['id'])
@@ -48,12 +53,15 @@ async def handler(request: ApiRequest, ctx: FlowContext[Any]) -> ApiResponse:
'topic': 'vmh.document.delete', 'topic': 'vmh.document.delete',
'data': { 'data': {
'entity_id': entity_id, 'entity_id': entity_id,
'entity_type': entity_type if 'entity_type' in locals() else 'CDokumente', 'entity_type': entity_type,
'action': 'delete', 'action': 'delete',
'timestamp': payload[0].get('deletedAt') if isinstance(payload, list) and payload else None 'timestamp': payload[0].get('deletedAt') if isinstance(payload, list) and payload else None
} }
}) })
ctx.logger.info("✅ Document Delete Webhook verarbeitet: "
f"{len(entity_ids)} Events emittiert")
return ApiResponse( return ApiResponse(
status=200, status=200,
body={ body={
@@ -64,8 +72,11 @@ async def handler(request: ApiRequest, ctx: FlowContext[Any]) -> ApiResponse:
) )
except Exception as e: except Exception as e:
ctx.logger.error(f"Fehler im Document Delete Webhook: {e}") ctx.logger.error("=" * 80)
ctx.logger.error("❌ FEHLER: DOCUMENT DELETE WEBHOOK")
ctx.logger.error(f"Error: {e}")
ctx.logger.error(f"Payload: {request.body}") ctx.logger.error(f"Payload: {request.body}")
ctx.logger.error("=" * 80)
return ApiResponse( return ApiResponse(
status=500, status=500,