Browse Source

备份时一律加时间戳,如果源文件一直被外部程序占用,日志会提示删除失败,但不会再“越备份越多”。

master
han\hanst 3 weeks ago
parent
commit
91b3bc982e
  1. 64
      client-file-collector/client_file_collector.py
  2. BIN
      client-file-collector/dist/QMSFileCollector.exe

64
client-file-collector/client_file_collector.py

@ -715,22 +715,14 @@ class CollectorApp:
target = self._build_unique_backup_target(backup_dir, file_path) target = self._build_unique_backup_target(backup_dir, file_path)
try:
shutil.move(str(file_path), str(target))
if self._move_file_transactional(file_path, target, row_index):
self.log("%d行源文件已转移至备份: %s -> %s" % (row_index, file_path.name, target)) self.log("%d行源文件已转移至备份: %s -> %s" % (row_index, file_path.name, target))
return True return True
except FileNotFoundError:
self.log("%d行源文件在备份时已被处理,忽略重复备份: %s" % (row_index, file_path.name))
return True
except Exception as e:
self.log("%d行源文件备份转移失败: %s, 原因: %s" % (row_index, file_path.name, e))
self.log("%d行源文件备份转移失败: %s" % (row_index, file_path.name))
return False return False
def _build_unique_backup_target(self, backup_dir, file_path): def _build_unique_backup_target(self, backup_dir, file_path):
target = backup_dir / file_path.name
if not target.exists():
return target
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S_%f") timestamp = datetime.now().strftime("%Y%m%d_%H%M%S_%f")
base_name = file_path.stem base_name = file_path.stem
suffix = file_path.suffix suffix = file_path.suffix
@ -741,6 +733,56 @@ class CollectorApp:
index += 1 index += 1
return candidate return candidate
def _move_file_transactional(self, source_file, target_file, row_index):
try:
source_file.rename(target_file)
return True
except FileNotFoundError:
self.log("%d行源文件在备份时已被处理,忽略重复备份: %s" % (row_index, source_file.name))
return True
except Exception:
pass
temp_target = target_file.parent / ("%s.__tmp__.%d" % (target_file.name, int(time.time() * 1000)))
try:
shutil.copy2(str(source_file), str(temp_target))
if target_file.exists():
target_file = self._build_unique_backup_target(target_file.parent, source_file)
temp_target.replace(target_file)
except Exception as e:
try:
if temp_target.exists():
temp_target.unlink()
except Exception:
pass
self.log("%d行复制到备份目录失败: %s, 原因: %s" % (row_index, source_file.name, e))
return False
if self._delete_source_with_retry(source_file):
return True
try:
if target_file.exists():
target_file.unlink()
except Exception as rollback_error:
self.log("%d行回滚备份文件失败: %s, 原因: %s" % (row_index, target_file, rollback_error))
return False
def _delete_source_with_retry(self, file_path, retry_times=6, retry_interval=0.3):
for idx in range(max(1, retry_times)):
try:
file_path.unlink()
return True
except FileNotFoundError:
return True
except Exception as e:
if idx < retry_times - 1:
time.sleep(retry_interval)
continue
self.log("删除源文件失败: %s, 原因: %s" % (file_path.name, e))
return False
return False
def _upload_file(self, row, file_path): def _upload_file(self, row, file_path):
url = self._base_url() + "/collector/client/upload" url = self._base_url() + "/collector/client/upload"
data = { data = {

BIN
client-file-collector/dist/QMSFileCollector.exe

Loading…
Cancel
Save