# Feature Specification: Simplify Sync Job Management with Progress Tracking **Feature Branch**: `004-home-sstent-projects` **Created**: Saturday, October 11, 2025 **Status**: Draft **Input**: User description: "since this is a single user system can we simplify the sync jobs even further - i.e. just one sync job at a time, no queue, no job id? can we add progress tracking for the sync - with an API I can poll for updates" ## User Scenarios & Testing ### User Story 1 - Initiate a Sync and Monitor Progress (Priority: P1) As a user, I want to initiate a data synchronization (activities, health, or workouts) and be able to monitor its progress in real-time, so I know the system is working and when it's complete or if it has failed. **Why this priority**: This is core functionality for providing user feedback and ensuring a transparent experience during data synchronization, which is a primary function of the system. **Independent Test**: This can be fully tested by initiating any type of sync (e.g., activity sync) and repeatedly querying the status API until the sync completes or fails. It delivers immediate value by informing the user about the state of their data synchronization. **Acceptance Scenarios**: 1. **Given** no sync is currently in progress, **When** the user initiates an activity sync via the API, **Then** the system returns an immediate success confirmation, and subsequent calls to the `/garmin/sync/status` API show the sync as "in_progress" with increasing `progress` and `job_type` set to "activities". 2. **Given** a sync is currently in progress, **When** the user attempts to initiate another sync (e.g., health sync), **Then** the system returns a "409 Conflict" error, indicating that another sync is already running. 3. **Given** a sync is in progress, **When** the user repeatedly polls the `/garmin/sync/status` API, **Then** the API consistently returns the current `status` as "in_progress", the `progress` value reflecting the ongoing work, and the correct `job_type`. 4. **Given** a sync completes successfully, **When** the user polls the `/garmin/sync/status` API, **Then** the API returns the `status` as "completed", `progress` as 1.0, and the `end_time` is set. 5. **Given** a sync encounters an error and fails, **When** the user polls the `/garmin/sync/status` API, **Then** the API returns the `status` as "failed", `progress` reflecting the point of failure, an `error_message`, and the `end_time` is set. 6. **Given** no sync is active, **When** the user polls the `/garmin/sync/status` API, **Then** the API returns the `status` as "idle" and `progress` as 0.0. --- ### Edge Cases - **Server Restart During Sync**: If the server restarts while a sync is in progress, the sync state will be lost, and the system will revert to an "idle" state upon restart. The user would need to re-initiate the sync. - **Network Interruption During Sync**: If a network interruption occurs during a sync operation, the sync will likely fail and report an appropriate error message via the status API. - **Rapid Polling**: The system should gracefully handle frequent polling requests to the status API without performance degradation. ## Requirements ### Functional Requirements - **FR-001**: System MUST allow initiation of a single sync operation (activities, health, or workouts) at a time. - **FR-002**: System MUST prevent initiation of a new sync if one is already in progress, returning a "409 Conflict" error. - **FR-003**: System MUST provide a `GET /garmin/sync/status` API endpoint to retrieve the current status of the active sync job. - **FR-004**: The `GET /garmin/sync/status` API MUST return a `SyncJob` object containing `status` (idle, in_progress, completed, failed), `progress` (0.0-1.0), `job_type` (activities, health, workouts), `start_time`, `end_time` (optional), and `error_message` (optional). - **FR-005**: System MUST update the `progress` of the active sync job as it proceeds through its various stages. - **FR-006**: System MUST mark the active sync job as "completed" and set its `end_time` upon successful completion. - **FR-007**: System MUST mark the active sync job as "failed", record an `error_message`, and set its `end_time` upon failure. - **FR-008**: System MUST initialize the `SyncJob` status to "idle" and `progress` to 0.0 when no sync is active. ### Key Entities - **SyncJob**: Represents the state and progress of the single active synchronization process. * `status`: String indicating the current state of the sync (e.g., "idle", "in_progress", "completed", "failed"). * `progress`: Float value from 0.0 to 1.0 representing the completion percentage of the sync. * `start_time`: Datetime object indicating when the sync operation began. * `end_time`: Optional Datetime object indicating when the sync operation concluded (either completed or failed). * `error_message`: Optional string containing details if the sync operation failed. * `job_type`: String indicating the type of data being synchronized (e.g., "activities", "health", "workouts"). ## Success Criteria ### Measurable Outcomes - **SC-001**: Users can successfully initiate any sync operation and receive an initial confirmation within 2 seconds. - **SC-002**: The `GET /garmin/sync/status` API endpoint responds with the current sync status within 500ms, even under moderate load (e.g., 10 requests per second). - **SC-003**: Sync progress updates are reflected in the `GET /garmin/sync/status` API with a granularity that provides meaningful feedback to the user (e.g., progress updates at least every 10% completion or every 30 seconds for long-running syncs). - **SC-004**: The system accurately reports sync completion or failure, including relevant error messages, for 100% of sync attempts. - **SC-005**: The system successfully prevents concurrent sync initiations, returning a 409 Conflict error in 100% of such attempts.