SyncServer GUI - added reset site for whole representation

Updated saving to DB with better approach
This commit is contained in:
Petr Kalis 2021-02-03 16:19:09 +01:00
parent ff8a8347f7
commit e66e661c38
2 changed files with 122 additions and 65 deletions

View file

@ -557,34 +557,32 @@ class SyncServer(PypeModule, ITrayModule):
representation_id = representation.get("_id")
file_id = file.get("_id")
query = {
"_id": representation_id,
"files._id": file_id
"_id": representation_id
}
file_index, _ = self._get_file_info(representation.get('files', []),
file_id)
site_index, _ = self._get_provider_rec(file.get('sites', []),
site)
update = {}
if new_file_id:
update["$set"] = self._get_success_dict(file_index, site_index,
new_file_id)
update["$set"] = self._get_success_dict(new_file_id)
# reset previous errors if any
update["$unset"] = self._get_error_dict(file_index, site_index,
"", "", "")
update["$unset"] = self._get_error_dict("", "", "")
elif progress is not None:
update["$set"] = self._get_progress_dict(file_index, site_index,
progress)
update["$set"] = self._get_progress_dict(progress)
else:
tries = self._get_tries_count(file, site)
tries += 1
update["$set"] = self._get_error_dict(file_index, site_index,
error, tries)
update["$set"] = self._get_error_dict(error, tries)
self.connection.Session["AVALON_PROJECT"] = collection
self.connection.update_one(
arr_filter = [
{'s.name': site},
{'f._id': ObjectId(file_id)}
]
self.connection.database[collection].update_one(
query,
update
update,
upsert=True,
array_filters=arr_filter
)
if progress is not None:
@ -642,7 +640,7 @@ class SyncServer(PypeModule, ITrayModule):
return -1, None
def reset_provider_for_file(self, collection, representation_id,
file_id, side):
side, file_id=None):
"""
Reset information about synchronization for particular 'file_id'
and provider.
@ -671,24 +669,32 @@ class SyncServer(PypeModule, ITrayModule):
else:
site_name = remote_site
files = representation[0].get('files', [])
file_index, _ = self._get_file_info(files,
file_id)
site_index, _ = self._get_provider_rec(files[file_index].
get('sites', []),
site_name)
if file_index >= 0 and site_index >= 0:
elem = {"name": site_name}
elem = {"name": site_name}
if file_id:
update = {
"$set": {"files.{}.sites.{}".format(file_index, site_index):
elem
}
"$set": {"files.$[f].sites.$[s]": elem}
}
self.connection.database[collection].update_one(
query,
update
)
arr_filter = [
{'s.name': site_name},
{'f._id': ObjectId(file_id)}
]
else:
update = {
"$set": {"files.$[].sites.$[s]": elem}
}
arr_filter = [
{'s.name': site_name}
]
self.connection.database[collection].update_one(
query,
update,
upsert=True,
array_filters=arr_filter
)
def get_loop_delay(self, project_name):
"""
@ -703,44 +709,35 @@ class SyncServer(PypeModule, ITrayModule):
"""Show dialog to enter credentials"""
self.widget.show()
def _get_success_dict(self, file_index, site_index, new_file_id):
def _get_success_dict(self, new_file_id):
"""
Provide success metadata ("id", "created_dt") to be stored in Db.
Used in $set: "DICT" part of query.
Sites are array inside of array(file), so real indexes for both
file and site are needed for upgrade in DB.
Args:
file_index: (int) - index of modified file
site_index: (int) - index of modified site of modified file
new_file_id: id of created file
Returns:
(dictionary)
"""
val = {"files.{}.sites.{}.id".format(file_index, site_index):
new_file_id,
"files.{}.sites.{}.created_dt".format(file_index, site_index):
datetime.utcnow()}
val = {"files.$[f].sites.$[s].id": new_file_id,
"files.$[f].sites.$[s].created_dt": datetime.utcnow()}
return val
def _get_error_dict(self, file_index, site_index,
error="", tries="", progress=""):
def _get_error_dict(self, error="", tries="", progress=""):
"""
Provide error metadata to be stored in Db.
Used for set (error and tries provided) or unset mode.
Args:
file_index: (int) - index of modified file
site_index: (int) - index of modified site of modified file
error: (string) - message
tries: how many times failed
Returns:
(dictionary)
"""
val = {"files.{}.sites.{}.last_failed_dt".
format(file_index, site_index): datetime.utcnow(),
"files.{}.sites.{}.error".format(file_index, site_index): error,
"files.{}.sites.{}.tries".format(file_index, site_index): tries,
"files.{}.sites.{}.progress".format(file_index, site_index):
progress
val = {"files.$[f].sites.$[s].last_failed_dt": datetime.utcnow(),
"files.$[f].sites.$[s].error": error,
"files.$[f].sites.$[s].tries": tries,
"files.$[f].sites.$[s].progress": progress
}
return val
@ -768,20 +765,16 @@ class SyncServer(PypeModule, ITrayModule):
_, rec = self._get_provider_rec(file.get("sites", []), provider)
return rec.get("tries", 0)
def _get_progress_dict(self, file_index, site_index, progress):
def _get_progress_dict(self, progress):
"""
Provide progress metadata to be stored in Db.
Used during upload/download for GUI to show.
Args:
file_index: (int) - index of modified file
site_index: (int) - index of modified site of modified file
progress: (float) - 0-1 progress of upload/download
Returns:
(dictionary)
"""
val = {"files.{}.sites.{}.progress".
format(file_index, site_index): progress
}
val = {"files.$[f].sites.$[s].progress": progress}
return val
def _get_local_file_path(self, file, local_root):

View file

@ -139,6 +139,7 @@ class SyncRepresentationWidget(QtWidgets.QWidget):
self.sync_server = sync_server
self._selected_id = None # keep last selected _id
self.representation_id = None
self.filter = QtWidgets.QLineEdit()
self.filter.setPlaceholderText("Filter representations..")
@ -202,7 +203,8 @@ class SyncRepresentationWidget(QtWidgets.QWidget):
def _selection_changed(self, new_selection):
index = self.selection_model.currentIndex()
self._selected_id = self.table_view.model().data(index, Qt.UserRole)
self.representation_id = \
self.table_view.model().data(index, Qt.UserRole)
def _set_selection(self):
"""
@ -236,6 +238,66 @@ class SyncRepresentationWidget(QtWidgets.QWidget):
if not point_index.isValid():
return
self.item = self.table_view.model()._data[point_index.row()]
self.representation_id = self.item._id
log.debug("menu representation _id:: {}".
format(self.representation_id))
menu = QtWidgets.QMenu()
actions_mapping = {}
if self.item.state == STATUS[1]:
action = QtWidgets.QAction("Open error detail")
actions_mapping[action] = self._show_detail
menu.addAction(action)
remote_site, remote_progress = self.item.remote_site.split()
if float(remote_progress) == 1.0:
action = QtWidgets.QAction("Reset local site")
actions_mapping[action] = self._reset_local_site
menu.addAction(action)
local_site, local_progress = self.item.local_site.split()
if float(local_progress) == 1.0:
action = QtWidgets.QAction("Reset remote site")
actions_mapping[action] = self._reset_remote_site
menu.addAction(action)
if not actions_mapping:
action = QtWidgets.QAction("< No action >")
actions_mapping[action] = None
menu.addAction(action)
result = menu.exec_(QtGui.QCursor.pos())
if result:
to_run = actions_mapping[result]
if to_run:
to_run()
def _reset_local_site(self):
"""
Removes errors or success metadata for particular file >> forces
redo of upload/download
"""
self.sync_server.reset_provider_for_file(
self.table_view.model()._project,
self.representation_id,
'local'
)
self.table_view.model().refresh()
def _reset_remote_site(self):
"""
Removes errors or success metadata for particular file >> forces
redo of upload/download
"""
self.sync_server.reset_provider_for_file(
self.table_view.model()._project,
self.representation_id,
'remote'
)
self.table_view.model().refresh()
class SyncRepresentationModel(QtCore.QAbstractTableModel):
PAGE_SIZE = 20
@ -517,7 +579,7 @@ class SyncRepresentationModel(QtCore.QAbstractTableModel):
value = self.data(index, Qt.UserRole)
if value == id:
return index
return index
return None
def get_default_query(self, limit=0):
"""
@ -916,13 +978,13 @@ class SyncRepresentationDetailWidget(QtWidgets.QWidget):
menu.addAction(action)
remote_site, remote_progress = self.item.remote_site.split()
if remote_progress == '1':
if float(remote_progress) == 1.0:
action = QtWidgets.QAction("Reset local site")
actions_mapping[action] = self._reset_local_site
menu.addAction(action)
local_site, local_progress = self.item.local_site.split()
if local_progress == '1':
if float(local_progress) == 1.0:
action = QtWidgets.QAction("Reset remote site")
actions_mapping[action] = self._reset_remote_site
menu.addAction(action)
@ -946,8 +1008,9 @@ class SyncRepresentationDetailWidget(QtWidgets.QWidget):
self.sync_server.reset_provider_for_file(
self.table_view.model()._project,
self.representation_id,
self.item._id,
'local')
'local',
self.item._id)
self.table_view.model().refresh()
def _reset_remote_site(self):
"""
@ -957,8 +1020,9 @@ class SyncRepresentationDetailWidget(QtWidgets.QWidget):
self.sync_server.reset_provider_for_file(
self.table_view.model()._project,
self.representation_id,
self.item._id,
'remote')
'remote',
self.item._id)
self.table_view.model().refresh()
class SyncRepresentationDetailModel(QtCore.QAbstractTableModel):
@ -1208,7 +1272,7 @@ class SyncRepresentationDetailModel(QtCore.QAbstractTableModel):
value = self.data(index, Qt.UserRole)
if value == id:
return index
return index
return None
def get_default_query(self, limit=0):
"""