|
49 | 49 | from polar_flow_server.models.sleepwise_alertness import SleepWiseAlertness |
50 | 50 | from polar_flow_server.models.sleepwise_bedtime import SleepWiseBedtime |
51 | 51 | from polar_flow_server.models.spo2 import SpO2 |
52 | | -from polar_flow_server.models.sync_log import SyncLog |
| 52 | +from polar_flow_server.models.sync_log import SyncLog, SyncTrigger |
53 | 53 | from polar_flow_server.models.temperature import BodyTemperature, SkinTemperature |
54 | 54 | from polar_flow_server.models.user import User |
55 | 55 | from polar_flow_server.services.scheduler import get_scheduler |
56 | | -from polar_flow_server.services.sync import SyncService |
| 56 | +from polar_flow_server.services.sync_orchestrator import SyncOrchestrator |
57 | 57 |
|
58 | 58 | logger = logging.getLogger(__name__) |
59 | 59 |
|
@@ -918,24 +918,55 @@ async def trigger_manual_sync(request: Request[Any, Any, Any], session: AsyncSes |
918 | 918 | polar_token = env_token |
919 | 919 | user_id = "self" |
920 | 920 |
|
921 | | - # Run sync |
922 | | - sync_service = SyncService(session) |
| 921 | + # Run sync via orchestrator (creates SyncLog entry for audit trail) |
| 922 | + orchestrator = SyncOrchestrator(session) |
923 | 923 | try: |
924 | | - results = await sync_service.sync_user( |
| 924 | + sync_log = await orchestrator.sync_user( |
925 | 925 | user_id=user_id, |
926 | 926 | polar_token=polar_token, |
927 | | - days=settings.sync_days_lookback, |
| 927 | + trigger=SyncTrigger.MANUAL, |
928 | 928 | ) |
929 | 929 |
|
930 | 930 | # Get updated counts |
931 | 931 | sleep_count = (await session.execute(select(func.count(Sleep.id)))).scalar() or 0 |
932 | 932 | exercise_count = (await session.execute(select(func.count(Exercise.id)))).scalar() or 0 |
933 | 933 | activity_count = (await session.execute(select(func.count(Activity.id)))).scalar() or 0 |
934 | 934 |
|
| 935 | + # Check sync status |
| 936 | + if sync_log.status == "partial": |
| 937 | + # Partial success - some endpoints worked, some failed |
| 938 | + errors = sync_log.error_details.get("errors", {}) if sync_log.error_details else {} |
| 939 | + return Template( |
| 940 | + template_name="admin/partials/sync_partial.html", |
| 941 | + context={ |
| 942 | + "results": sync_log.records_synced or {}, |
| 943 | + "errors": errors, |
| 944 | + "sleep_count": sleep_count, |
| 945 | + "exercise_count": exercise_count, |
| 946 | + "activity_count": activity_count, |
| 947 | + }, |
| 948 | + ) |
| 949 | + elif sync_log.status == "failed": |
| 950 | + # Total failure - all endpoints failed |
| 951 | + errors_raw = sync_log.error_details.get("errors", {}) if sync_log.error_details else {} |
| 952 | + # errors_raw is dict[str, str] but typed as object, cast for iteration |
| 953 | + errors = errors_raw if isinstance(errors_raw, dict) else {} |
| 954 | + if errors: |
| 955 | + error_messages = "\n".join( |
| 956 | + f"• {endpoint}: {msg}" for endpoint, msg in errors.items() |
| 957 | + ) |
| 958 | + else: |
| 959 | + error_messages = sync_log.error_message or "Sync failed" |
| 960 | + return Template( |
| 961 | + template_name="admin/partials/sync_error.html", |
| 962 | + context={"error": error_messages}, |
| 963 | + ) |
| 964 | + |
| 965 | + # Full success - no errors |
935 | 966 | return Template( |
936 | 967 | template_name="admin/partials/sync_success.html", |
937 | 968 | context={ |
938 | | - "results": results, |
| 969 | + "results": sync_log.records_synced or {}, |
939 | 970 | "sleep_count": sleep_count, |
940 | 971 | "exercise_count": exercise_count, |
941 | 972 | "activity_count": activity_count, |
|
0 commit comments