Files
FitTrack_GarminSync/specs/004-single-sync-job.md

59 lines
5.0 KiB
Markdown

# 004-single-sync-job: Simplify Sync Job Management with Progress Tracking
## Goal
To simplify the synchronization job management by allowing only one sync job to run at a time, and to provide progress tracking for this single active sync job via a polling API. This aligns with the system's single-user nature while offering better user feedback.
## Motivation
The current system is designed for a single user. While the previous iteration aimed to remove all job management complexity, the need for user feedback on ongoing sync operations necessitates a simplified progress tracking mechanism. This approach avoids a full-fledged job queue and ID system but still provides visibility into the single active sync.
## Proposed Changes
### 1. Reintroduction of a Simplified Sync Job Model
* **Define `SyncJob` Model**: Reintroduce a `Pydantic` model for `SyncJob` (e.g., in a new `backend/src/sync_status.py` file or similar). This model will represent the state of the *single active* sync job and will include fields such as:
* `status: str` (e.g., "idle", "in_progress", "completed", "failed")
* `progress: float` (0.0 to 1.0)
* `start_time: datetime`
* `end_time: Optional[datetime]`
* `error_message: Optional[str]`
* `job_type: Optional[str]` (e.g., "activities", "health", "workouts")
### 2. Introduce `CurrentSyncJobManager`
* **Create `CurrentSyncJobManager`**: Implement a singleton class or a global object (e.g., in `backend/src/sync_manager.py`) to manage the state of the `SyncJob`. This manager will hold the single `SyncJob` instance and provide methods for its lifecycle.
* `start_sync(job_type: str) -> SyncJob`: Initializes a new `SyncJob` with "in_progress" status and the given type. Sets the `start_time`. Returns the `SyncJob` instance.
* `update_progress(progress: float, details: Optional[str] = None)`: Updates the `progress` and optionally `details` of the current `SyncJob`.
* `complete_sync()`: Sets the `status` to "completed" and `end_time` for the current `SyncJob`.
* `fail_sync(error_message: str)`: Sets the `status` to "failed", `error_message`, and `end_time` for the current `SyncJob`.
* `get_current_sync_status() -> SyncJob`: Returns the current `SyncJob` instance.
* `is_sync_active() -> bool`: Returns `True` if a sync is currently "in_progress", `False` otherwise.
### 3. Modification of Sync Service Functions
* The `_in_background` functions in `backend/src/services/garmin_health_service.py`, `backend/src/services/garmin_activity_service.py`, and `backend/src/services/garmin_workout_service.py` will be modified:
* They will no longer accept a `job_id` parameter.
* Instead, they will receive the `SyncJob` instance (or a reference to the `CurrentSyncJobManager`) for the current operation.
* They will use the `CurrentSyncJobManager`'s `update_progress`, `complete_sync`, and `fail_sync` methods to report their status.
### 4. Modification of API Endpoints (`backend/src/api/garmin_sync.py`)
* **Remove `job_store` and `SyncJob` imports from the old system.**
* **Import `CurrentSyncJobManager` and `SyncJob` from the new system.**
* **Remove `/status/{job_id}` endpoint**: This endpoint is no longer needed as there are no individual job IDs to query.
* **Modify sync initiation endpoints (`/garmin/activities`, `/garmin/workouts`, `/garmin/health`)**:
* Before initiating a sync, check `CurrentSyncJobManager.is_sync_active()`. If `True`, return an error response (e.g., `409 Conflict`) indicating that a sync is already in progress.
* Call `CurrentSyncJobManager.start_sync(job_type="...")` to initialize the sync job.
* Pass the `SyncJob` instance (or a reference to the `CurrentSyncJobManager`) to the background task.
* Change the `response_model` to return the initial `SyncJob` status or a simple success message.
* **Add New API Endpoint for Status Polling**:
* `GET /garmin/sync/status`:
* **Response Model**: `SyncJob`
* **Description**: Returns the current status of the single active sync job. If no sync is active, it returns an "idle" status `SyncJob`.
### 5. Update Dependencies and Main Application
* **`backend/src/dependencies.py`**: Remove any references to the old `job_store` and `SyncStatusService`.
* **`backend/src/main.py`**: Ensure the `CurrentSyncJobManager` is properly initialized and accessible (e.g., as a global or via dependency injection if preferred).
## Impact
* **Progress Tracking**: Users can now poll a dedicated API endpoint to get real-time progress updates for the single active sync job.
* **Clearer State**: The system's state regarding sync operations is more transparent.
* **Controlled Concurrency**: Only one sync operation can run at a time, preventing resource contention in a single-user environment.
* **Simplified API**: No need to manage multiple job IDs. The status endpoint always refers to the current operation.
* **Minimal Overhead**: Avoids the complexity of a full-blown job queue and distributed job management system, suitable for a single-user application.