diff --git a/backend/modules/sync/controller/sync_routes.py b/backend/modules/sync/controller/sync_routes.py index 3528a51eb..54b1df504 100644 --- a/backend/modules/sync/controller/sync_routes.py +++ b/backend/modules/sync/controller/sync_routes.py @@ -4,6 +4,9 @@ from typing import List from fastapi import APIRouter, Depends, status from logger import get_logger from middlewares.auth import AuthBearer, get_current_user +from modules.notification.dto.inputs import CreateNotification +from modules.notification.entity.notification import NotificationsStatusEnum +from modules.notification.service.notification_service import NotificationService from modules.sync.controller.azure_sync_routes import azure_sync_router from modules.sync.controller.google_sync_routes import google_sync_router from modules.sync.dto import SyncsDescription @@ -13,6 +16,8 @@ from modules.sync.entity.sync import SyncsActive from modules.sync.service.sync_service import SyncService, SyncUserService from modules.user.entity.user_identity import UserIdentity +notification_service = NotificationService() + # Set environment variable for OAuthlib os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "1" @@ -83,6 +88,7 @@ async def get_user_syncs(current_user: UserIdentity = Depends(get_current_user)) logger.debug(f"Fetching user syncs for user: {current_user.id}") return sync_user_service.get_syncs_user(str(current_user.id)) + @sync_router.delete( "/sync/{sync_id}", status_code=status.HTTP_204_NO_CONTENT, @@ -102,7 +108,9 @@ async def delete_user_sync( Returns: None """ - logger.debug(f"Deleting user sync for user: {current_user.id} with sync ID: {sync_id}") + logger.debug( + f"Deleting user sync for user: {current_user.id} with sync ID: {sync_id}" + ) sync_user_service.delete_sync_user(sync_id, str(current_user.id)) return None @@ -130,6 +138,14 @@ async def create_sync_active( logger.debug( f"Creating active sync for user: {current_user.id} with data: {sync_active_input}" ) + notification_service.add_notification( + CreateNotification( + user_id=current_user.id, + status=NotificationsStatusEnum.SUCCESS, + title="Sync created! Synchronization takes a few minutes to complete", + description="Syncing your files...", + ) + ) return sync_service.create_sync_active(sync_active_input, str(current_user.id)) @@ -158,6 +174,15 @@ async def update_sync_active( logger.debug( f"Updating active sync for user: {current_user.id} with data: {sync_active_input}" ) + notification_service.add_notification( + CreateNotification( + user_id=current_user.id, + status=NotificationsStatusEnum.SUCCESS, + title="Sync updated! Synchronization takes a few minutes to complete", + description="Syncing your files...", + ) + ) + sync_active_input.force_sync = True return sync_service.update_sync_active(sync_id, sync_active_input) @@ -183,6 +208,14 @@ async def delete_sync_active( logger.debug( f"Deleting active sync for user: {current_user.id} with sync ID: {sync_id}" ) + notification_service.add_notification( + CreateNotification( + user_id=current_user.id, + status=NotificationsStatusEnum.SUCCESS, + title="Sync deleted!", + description="Sync deleted!", + ) + ) sync_service.delete_sync_active(sync_id, str(current_user.id)) return None diff --git a/backend/modules/sync/dto/inputs.py b/backend/modules/sync/dto/inputs.py index 1d6a0f9af..db103c9eb 100644 --- a/backend/modules/sync/dto/inputs.py +++ b/backend/modules/sync/dto/inputs.py @@ -78,6 +78,7 @@ class SyncsActiveUpdateInput(BaseModel): name: Optional[str] = None settings: Optional[SyncActiveSettings] = None last_synced: Optional[str] = None + force_sync: Optional[bool] = False class SyncFileInput(BaseModel): diff --git a/backend/modules/sync/repository/sync.py b/backend/modules/sync/repository/sync.py index 8fcab62f5..f87ef092a 100644 --- a/backend/modules/sync/repository/sync.py +++ b/backend/modules/sync/repository/sync.py @@ -93,6 +93,7 @@ class Sync(SyncInterface): sync_id, sync_active_input, ) + response = ( self.db.from_("syncs_active") .update(sync_active_input.model_dump(exclude_unset=True)) @@ -185,12 +186,13 @@ class Sync(SyncInterface): .lt("last_synced", (current_time - timedelta(minutes=360)).isoformat()) .execute() ) - if response.data: - logger.info("Active syncs retrieved successfully: %s", response.data) - for sync in response.data: - # Now we can call the sync_google_drive_if_not_synced method to sync the Google Drive files - logger.info("Syncing Google Drive for sync_active_id: %s", sync["id"]) - return [SyncsActive(**sync) for sync in response.data] - logger.warning("No active syncs found due for synchronization") + force_sync = ( + self.db.table("syncs_active").select("*").eq("force_sync", True).execute() + ) + merge_data = response.data + force_sync.data + if merge_data: + logger.info("Active syncs retrieved successfully: %s", merge_data) + return [SyncsActive(**sync) for sync in merge_data] + logger.info("No active syncs found due for synchronization") return [] diff --git a/backend/modules/sync/utils/googleutils.py b/backend/modules/sync/utils/googleutils.py index f0acf5c63..e1ce89910 100644 --- a/backend/modules/sync/utils/googleutils.py +++ b/backend/modules/sync/utils/googleutils.py @@ -216,8 +216,9 @@ class GoogleSyncUtils(BaseModel): # Check if the sync is due last_synced = sync_active.get("last_synced") + force_sync = sync_active.get("force_sync", False) sync_interval_minutes = sync_active.get("sync_interval_minutes", 0) - if last_synced: + if last_synced and not force_sync: last_synced_time = datetime.fromisoformat(last_synced).astimezone( timezone.utc ) @@ -318,7 +319,10 @@ class GoogleSyncUtils(BaseModel): # Update the last_synced timestamp self.sync_active_service.update_sync_active( sync_active_id, - SyncsActiveUpdateInput(last_synced=datetime.now().astimezone().isoformat()), + SyncsActiveUpdateInput( + last_synced=datetime.now().astimezone().isoformat(), + force_sync=False, + ), ) logger.info( "Google Drive sync completed for sync_active_id: %s", sync_active_id diff --git a/backend/modules/sync/utils/sharepointutils.py b/backend/modules/sync/utils/sharepointutils.py index 997c5aec1..d3ba896b4 100644 --- a/backend/modules/sync/utils/sharepointutils.py +++ b/backend/modules/sync/utils/sharepointutils.py @@ -209,8 +209,9 @@ class AzureSyncUtils(BaseModel): # Check if the sync is due last_synced = sync_active.get("last_synced") + force_sync = sync_active.get("force_sync", False) sync_interval_minutes = sync_active.get("sync_interval_minutes", 0) - if last_synced: + if last_synced and not force_sync: last_synced_time = datetime.fromisoformat(last_synced).astimezone( timezone.utc ) @@ -326,7 +327,9 @@ class AzureSyncUtils(BaseModel): # Update the last_synced timestamp self.sync_active_service.update_sync_active( sync_active_id, - SyncsActiveUpdateInput(last_synced=datetime.now().astimezone().isoformat()), + SyncsActiveUpdateInput( + last_synced=datetime.now().astimezone().isoformat(), force_sync=False + ), ) logger.info("Azure sync completed for sync_active_id: %s", sync_active_id) return downloaded_files diff --git a/backend/supabase/migrations/20240610141546_force-sync.sql b/backend/supabase/migrations/20240610141546_force-sync.sql new file mode 100644 index 000000000..251750fcb --- /dev/null +++ b/backend/supabase/migrations/20240610141546_force-sync.sql @@ -0,0 +1 @@ +alter table "public"."syncs_active" add column "force_sync" boolean not null default false;