GGSheng commited on
Commit
783de55
·
verified ·
1 Parent(s): 059c42b

Update openclaw_hf/backup.py

Browse files
Files changed (1) hide show
  1. openclaw_hf/backup.py +60 -3
openclaw_hf/backup.py CHANGED
@@ -1757,6 +1757,8 @@ class OpenClawBackup:
1757
  print("[PRUNE] Starting old backup cleanup...")
1758
  print(f"[PRUNE] Retention policy: keep_count={self.config.keep_count}")
1759
 
 
 
1760
  if not hasattr(self.api, "delete_file"):
1761
  print("[PRUNE] API does not support delete_file, skipping cleanup")
1762
  return []
@@ -1815,12 +1817,67 @@ class OpenClawBackup:
1815
 
1816
  sorted_timestamps = sorted(backups_by_time.keys(), reverse=True)
1817
 
1818
- if len(sorted_timestamps) <= keep_count:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1819
  print(f"[PRUNE] Total backups ({len(sorted_timestamps)}) <= keep_count ({keep_count}), no pruning needed")
1820
  return []
1821
 
1822
- timestamps_to_delete = sorted_timestamps[keep_count:]
1823
- print(f"[PRUNE] Will delete {len(timestamps_to_delete)} backup(s) older than {sorted_timestamps[keep_count-1]}")
 
1824
 
1825
  # Limit batch size to avoid rate limiting (max 50 files per cleanup)
1826
  max_files_per_cleanup = 50
 
1757
  print("[PRUNE] Starting old backup cleanup...")
1758
  print(f"[PRUNE] Retention policy: keep_count={self.config.keep_count}")
1759
 
1760
+ MIN_FULL_BACKUPS = 12
1761
+
1762
  if not hasattr(self.api, "delete_file"):
1763
  print("[PRUNE] API does not support delete_file, skipping cleanup")
1764
  return []
 
1817
 
1818
  sorted_timestamps = sorted(backups_by_time.keys(), reverse=True)
1819
 
1820
+ full_backup_timestamps = []
1821
+ incremental_backup_timestamps = []
1822
+ for ts in sorted_timestamps:
1823
+ archive_name = Path(backups_by_time[ts][0]).name
1824
+ if ".part-" in archive_name:
1825
+ base_name = archive_name.rsplit(".part-", 1)[0]
1826
+ else:
1827
+ base_name = archive_name
1828
+ if base_name.endswith(".tar.gz"):
1829
+ meta_name = base_name[:-7] + ".meta.json"
1830
+ else:
1831
+ meta_name = base_name + ".meta.json"
1832
+ if path_prefix_slash:
1833
+ meta_path = f"{path_prefix_slash}{meta_name}"
1834
+ else:
1835
+ meta_path = meta_name
1836
+ if meta_path in files:
1837
+ try:
1838
+ cached_meta = self._get_cached_meta(meta_path)
1839
+ if cached_meta is not None:
1840
+ meta = cached_meta
1841
+ else:
1842
+ local_meta = self._download_backup(meta_path, self.config.work_dir, repo_id=self.config.dataset_repo)
1843
+ with open(local_meta, "r") as f:
1844
+ meta = json.load(f)
1845
+ self._set_cached_meta(meta_path, meta)
1846
+ if meta.get("backup_type") == "full":
1847
+ full_backup_timestamps.append(ts)
1848
+ else:
1849
+ incremental_backup_timestamps.append(ts)
1850
+ except Exception:
1851
+ pass
1852
+
1853
+ print(f"[PRUNE] Full backup timestamps identified: {len(full_backup_timestamps)}")
1854
+ print(f"[PRUNE] Incremental backup timestamps identified: {len(incremental_backup_timestamps)}")
1855
+
1856
+ MIN_FULL_BACKUPS = 12
1857
+
1858
+ cutoff_timestamp = None
1859
+ if len(full_backup_timestamps) >= MIN_FULL_BACKUPS:
1860
+ cutoff_timestamp = full_backup_timestamps[MIN_FULL_BACKUPS - 1]
1861
+ print(f"[PRUNE] Minimum {MIN_FULL_BACKUPS} full backups required, cutoff at: {cutoff_timestamp}")
1862
+ elif full_backup_timestamps:
1863
+ cutoff_timestamp = full_backup_timestamps[-1]
1864
+ print(f"[PRUNE] Only {len(full_backup_timestamps)} full backups exist, oldest full backup: {cutoff_timestamp}")
1865
+
1866
+ timestamps_to_delete = []
1867
+ if cutoff_timestamp is not None:
1868
+ for ts in sorted_timestamps:
1869
+ if ts < cutoff_timestamp:
1870
+ timestamps_to_delete.append(ts)
1871
+ else:
1872
+ timestamps_to_delete = sorted_timestamps[keep_count:]
1873
+
1874
+ if len(sorted_timestamps) <= keep_count and not timestamps_to_delete:
1875
  print(f"[PRUNE] Total backups ({len(sorted_timestamps)}) <= keep_count ({keep_count}), no pruning needed")
1876
  return []
1877
 
1878
+ if not timestamps_to_delete:
1879
+ print(f"[PRUNE] All older backups are protected (minimum {MIN_FULL_BACKUPS} full backups required)")
1880
+ return []
1881
 
1882
  # Limit batch size to avoid rate limiting (max 50 files per cleanup)
1883
  max_files_per_cleanup = 50