diff --git a/Sources/pyOpenRPA/Orchestrator/Server.py b/Sources/pyOpenRPA/Orchestrator/Server.py index 5102b1fb..68ee1e4c 100644 --- a/Sources/pyOpenRPA/Orchestrator/Server.py +++ b/Sources/pyOpenRPA/Orchestrator/Server.py @@ -43,6 +43,20 @@ def __ComplexDictMerge2to1__(in1Dict, in2Dict): in1Dict[lKeyStr] = in2Dict[lKeyStr] return in1Dict +# Tool to merge complex dictionaries - no exceptions, just overwrite dict 2 in dict 1 +def __ComplexDictMerge2to1Overwrite__(in1Dict, in2Dict): + lPathList=None + if lPathList is None: lPathList = [] + for lKeyStr in in2Dict: + if lKeyStr in in1Dict: + if isinstance(in1Dict[lKeyStr], dict) and isinstance(in2Dict[lKeyStr], dict): + __ComplexDictMerge2to1__(in1Dict[lKeyStr], in2Dict[lKeyStr]) + else: + in1Dict[lKeyStr] = in2Dict[lKeyStr] + else: + in1Dict[lKeyStr] = in2Dict[lKeyStr] + return in1Dict + #Authenticate function () # return dict # { diff --git a/Sources/pyOpenRPA/Orchestrator/__Orchestrator__.py b/Sources/pyOpenRPA/Orchestrator/__Orchestrator__.py index 1281f6b3..f3994454 100644 --- a/Sources/pyOpenRPA/Orchestrator/__Orchestrator__.py +++ b/Sources/pyOpenRPA/Orchestrator/__Orchestrator__.py @@ -1,4 +1,8 @@ import subprocess, json, psutil, time, os, win32security, sys, base64, logging, ctypes, copy #Get input argument +import pickle + +from partd import Server + from . import Server from . import Timer from . import Processor @@ -323,19 +327,30 @@ def OrchestratorRestart(inGSettings=None): def OrchestratorSessionSave(inGSettings=None): """ - Orchestrator session save in file _SessionLast_RDPList.json (encoding = "utf-8") + Orchestrator session save in file + _SessionLast_RDPList.json (encoding = "utf-8") + _SessionLast_StorageDict.pickle (binary) :param inGSettings: Global settings dict (singleton) :return: True every time """ - # Dump RDP List in file json - lFile = open("_SessionLast_RDPList.json", "w", encoding="utf-8") - lFile.write(json.dumps(inGSettings["RobotRDPActive"]["RDPList"])) # dump json to file - lFile.close() # Close the file - if inGSettings is not None: - lL = inGSettings["Logger"] - if lL: lL.info( - f"Orchestrator has dump the RDP list before the restart.") + lL = inGSettings["Logger"] + try: + # Dump RDP List in file json + lFile = open("_SessionLast_RDPList.json", "w", encoding="utf-8") + lFile.write(json.dumps(inGSettings["RobotRDPActive"]["RDPList"])) # dump json to file + lFile.close() # Close the file + if inGSettings is not None: + if lL: lL.info( + f"Orchestrator has dump the RDP list before the restart.") + # _SessionLast_StorageDict.pickle (binary) + if "StorageDict" in inGSettings: + with open('_SessionLast_StorageDict.pickle', 'wb') as lFile: + pickle.dump(inGSettings["StorageDict"], lFile) + if lL: lL.info( + f"Orchestrator has dump the StorageDict before the restart.") + except Exception as e: + if lL: lL.exception(f"Exception when dump data before restart the Orchestrator") return True def UACKeyListCheck(inRequest, inRoleKeyList) -> bool: @@ -1872,6 +1887,16 @@ def Orchestrator(inGSettings): gSettingsDict["RobotRDPActive"]["RDPList"]=lSessionLastRDPList # Set the last session dict if lL: lL.warning(f"RDP Session List was restored from previous Orchestrator session") + # _SessionLast_StorageDict.pickle (binary) + if os.path.exists("_SessionLast_StorageDict.pickle"): + if "StorageDict" not in inGSettings: + inGSettings["StorageDict"] = {} + with open('_SessionLast_StorageDict.pickle', 'rb') as lFile: + lStorageDictDumpDict = pickle.load(lFile) + Server.__ComplexDictMerge2to1Overwrite__(in1Dict=inGSettings["StorageDict"], in2Dict=lStorageDictDumpDict) # Merge dict 2 into dict 1 + if lL: lL.warning(f"StorageDict was restored from previous Orchestrator session") + os.remove("_SessionLast_StorageDict.pickle") # remove the temp file + # Init SettingsUpdate defs from file list (after RDP restore) lSettingsUpdateFilePathList = gSettingsDict.get("OrchestratorStart", {}).get("DefSettingsUpdatePathList",[]) lSubmoduleFunctionName = "SettingsUpdate"