@@ -1512,7 +1512,42 @@ def create_invitation(self, workspace_id: int, email: str, workspace_role: Works
15121512 ws_inv = self .post (f"v2/workspaces/{ workspace_id } /invitations" , params , json_headers )
15131513 return json .load (ws_inv )
15141514
1515- def sync_project (self , project_directory , upload_progress = False ):
1515+ def _sync_project_generator (self , project_directory ):
1516+ """
1517+ See `sync_project` for details. This method is a generator yielding upload progress as (size_change, job) tuples.
1518+
1519+ :param project_directory: Project's directory
1520+ """
1521+ mp = MerginProject (project_directory )
1522+ has_changes = True
1523+ server_conflict_attempts = 0
1524+ while has_changes :
1525+ self .pull_project (project_directory )
1526+ try :
1527+ job = push_project_async (self , project_directory )
1528+ if not job :
1529+ break
1530+ last_size = 0
1531+ while push_project_is_running (job ):
1532+ sleep (SYNC_CALLBACK_WAIT )
1533+ current_size = job .transferred_size
1534+ yield (current_size - last_size , job ) # Yields the size change and the job object
1535+ last_size = current_size
1536+ push_project_finalize (job )
1537+ _ , has_changes = get_push_changes_batch (self , mp )
1538+ server_conflict_attempts = 0
1539+ except ClientError as e :
1540+ if e .is_retryable_sync () and server_conflict_attempts < PUSH_ATTEMPTS - 1 :
1541+ # retry on conflict, e.g. when server has changes that we do not have yet
1542+ mp .log .info (
1543+ f"Restarting sync process (conflict on server) - { server_conflict_attempts + 1 } /{ PUSH_ATTEMPTS } "
1544+ )
1545+ server_conflict_attempts += 1
1546+ sleep (PUSH_ATTEMPT_WAIT )
1547+ continue
1548+ raise e
1549+
1550+ def sync_project (self , project_directory ):
15161551 """
15171552 Syncs project by loop with these steps:
15181553 1. Pull server version
@@ -1527,24 +1562,12 @@ def sync_project(self, project_directory, upload_progress=False):
15271562 has_changes = True
15281563 server_conflict_attempts = 0
15291564 while has_changes :
1530- pull_job = pull_project_async (self , project_directory )
1531- if pull_job :
1532- pull_project_wait (pull_job )
1533- pull_project_finalize (pull_job )
1534-
1565+ self .pull_project (project_directory )
15351566 try :
15361567 job = push_project_async (self , project_directory )
15371568 if not job :
15381569 break
1539- if not upload_progress :
1540- push_project_wait (job )
1541- else :
1542- last_size = 0
1543- while push_project_is_running (job ):
1544- sleep (SYNC_CALLBACK_WAIT )
1545- current_size = job .transferred_size
1546- yield (current_size - last_size , job ) # Yields the size change and the job object
1547- last_size = current_size
1570+ push_project_wait (job )
15481571 push_project_finalize (job )
15491572 _ , has_changes = get_push_changes_batch (self , mp )
15501573 server_conflict_attempts = 0
0 commit comments