Powerman9x commited on
Commit
f375c0a
Β·
verified Β·
1 Parent(s): c0d511a

Upload sync_hf.py

Browse files
Files changed (1) hide show
  1. scripts/sync_hf.py +118 -0
scripts/sync_hf.py CHANGED
@@ -85,6 +85,7 @@ HF_TOKEN = os.environ.get("HF_TOKEN")
85
  OPENCLAW_HOME = Path.home() / ".openclaw"
86
  APP_DIR = Path(os.environ.get("OPENCLAW_APP_DIR", "/app/openclaw"))
87
  DATASET_PATH = ".openclaw"
 
88
 
89
  # Z.AI API key (optional)
90
  ZAI_API_KEY = os.environ.get("ZAI_API_KEY", "")
@@ -584,6 +585,7 @@ class OpenClawFullSync:
584
  dest.parent.mkdir(parents=True, exist_ok=True)
585
  shutil.copy2(str(item), str(dest))
586
  print("[SYNC] βœ“ Restore completed.")
 
587
  else:
588
  print("[SYNC] Downloaded snapshot but dir not found. Starting fresh.")
589
 
@@ -715,12 +717,128 @@ class OpenClawFullSync:
715
  except Exception:
716
  pass
717
 
 
 
718
  except Exception as e:
719
  print(f"[SYNC] βœ— Upload failed: {str(e)[:500]}")
720
  if "429" in str(e) or "rate limit" in str(e).lower():
721
  self._cooldown_until = time.time() + 65 * 60
722
  print("[SYNC] Hub rate limit hit β€” pausing uploads for 65 min")
723
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
724
  # ── Pre-gateway legacy cleanup (CRITICAL) ─────────────────────────
725
 
726
  def _retire_workspace_markers(self):
 
85
  OPENCLAW_HOME = Path.home() / ".openclaw"
86
  APP_DIR = Path(os.environ.get("OPENCLAW_APP_DIR", "/app/openclaw"))
87
  DATASET_PATH = ".openclaw"
88
+ SQLITE_SNAPSHOT_PATH = "sqlite-snapshots"
89
 
90
  # Z.AI API key (optional)
91
  ZAI_API_KEY = os.environ.get("ZAI_API_KEY", "")
 
585
  dest.parent.mkdir(parents=True, exist_ok=True)
586
  shutil.copy2(str(item), str(dest))
587
  print("[SYNC] βœ“ Restore completed.")
588
+ self._restore_sqlite_snapshots()
589
  else:
590
  print("[SYNC] Downloaded snapshot but dir not found. Starting fresh.")
591
 
 
717
  except Exception:
718
  pass
719
 
720
+ self._upload_sqlite_snapshots()
721
+
722
  except Exception as e:
723
  print(f"[SYNC] βœ— Upload failed: {str(e)[:500]}")
724
  if "429" in str(e) or "rate limit" in str(e).lower():
725
  self._cooldown_until = time.time() + 65 * 60
726
  print("[SYNC] Hub rate limit hit β€” pausing uploads for 65 min")
727
 
728
+ # ── SQLite snapshots (live .sqlite files are never uploaded directly) ──
729
+
730
+ def _iter_persistable_sqlites(self):
731
+ for root, dirs, files in os.walk(OPENCLAW_HOME):
732
+ for fn in files:
733
+ if not fn.endswith(".sqlite"):
734
+ continue
735
+ fp = Path(os.path.join(root, fn))
736
+ try:
737
+ rel = fp.relative_to(OPENCLAW_HOME)
738
+ except ValueError:
739
+ continue
740
+ if rel.as_posix().startswith("state/"):
741
+ continue
742
+ yield rel, fp
743
+
744
+ def _stage_sqlite_snapshots(self, staging_dir):
745
+ staged = []
746
+ for rel, fp in self._iter_persistable_sqlites():
747
+ try:
748
+ if fp.stat().st_size == 0:
749
+ continue
750
+ dest = Path(staging_dir) / rel
751
+ dest.parent.mkdir(parents=True, exist_ok=True)
752
+ src = sqlite3.connect(str(fp))
753
+ dst = sqlite3.connect(str(dest))
754
+ try:
755
+ src.backup(dst)
756
+ finally:
757
+ dst.close()
758
+ src.close()
759
+ staged.append(rel)
760
+ except Exception as e:
761
+ print(f"[SYNC] sqlite snapshot skipped for {rel}: {str(e)[:120]}")
762
+ return staged
763
+
764
+ def _upload_sqlite_snapshots(self):
765
+ staging = tempfile.mkdtemp(prefix="oc-sqlite-snap-")
766
+ try:
767
+ staged = self._stage_sqlite_snapshots(staging)
768
+ if not staged:
769
+ print("[SYNC] No sqlite snapshots to upload")
770
+ return
771
+ print(f"[SYNC] β–Ά Uploading {len(staged)} sqlite snapshot(s) β†’ "
772
+ f"{SQLITE_SNAPSHOT_PATH}/ ...")
773
+ self.api.upload_folder(
774
+ folder_path=staging,
775
+ path_in_repo=SQLITE_SNAPSHOT_PATH,
776
+ repo_id=HF_REPO_ID,
777
+ repo_type="dataset",
778
+ token=HF_TOKEN,
779
+ commit_message=f"Sync sqlite snapshots β€” {datetime.now().isoformat()}",
780
+ )
781
+ print("[SYNC] βœ“ Sqlite snapshots uploaded")
782
+ except Exception as e:
783
+ print(f"[SYNC] βœ— Sqlite snapshot upload failed: {str(e)[:300]}")
784
+ if "429" in str(e) or "rate limit" in str(e).lower():
785
+ self._cooldown_until = time.time() + 65 * 60
786
+ print("[SYNC] Hub rate limit hit β€” pausing uploads for 65 min")
787
+ finally:
788
+ shutil.rmtree(staging, ignore_errors=True)
789
+
790
+ def _restore_sqlite_snapshots(self):
791
+ try:
792
+ files = self.api.list_repo_files(repo_id=HF_REPO_ID, repo_type="dataset")
793
+ snap_files = [f for f in files if f.startswith(f"{SQLITE_SNAPSHOT_PATH}/")]
794
+ if not snap_files:
795
+ return
796
+ print(f"[SYNC] Found {len(snap_files)} sqlite snapshot(s) in dataset")
797
+ with tempfile.TemporaryDirectory() as tmpdir:
798
+ snapshot_download(
799
+ repo_id=HF_REPO_ID,
800
+ repo_type="dataset",
801
+ allow_patterns=f"{SQLITE_SNAPSHOT_PATH}/**",
802
+ local_dir=tmpdir,
803
+ token=HF_TOKEN,
804
+ )
805
+ snap_root = Path(tmpdir) / SQLITE_SNAPSHOT_PATH
806
+ if not snap_root.exists():
807
+ return
808
+ restored = 0
809
+ for item in snap_root.rglob("*"):
810
+ if not item.is_file():
811
+ continue
812
+ rel = item.relative_to(snap_root)
813
+ dest = OPENCLAW_HOME / rel
814
+ try:
815
+ conn = sqlite3.connect(str(item))
816
+ try:
817
+ ok = conn.execute("PRAGMA quick_check").fetchone()
818
+ finally:
819
+ conn.close()
820
+ except Exception as e:
821
+ print(f"[SYNC] Snapshot integrity check failed, skipped: "
822
+ f"{rel} ({str(e)[:80]})")
823
+ continue
824
+ if not ok or ok[0] != "ok":
825
+ print(f"[SYNC] Snapshot corrupt, skipped: {rel}")
826
+ continue
827
+ dest.parent.mkdir(parents=True, exist_ok=True)
828
+ for suf in ("", "-wal", "-shm", "-journal"):
829
+ old = Path(str(dest) + suf)
830
+ if old.exists():
831
+ try:
832
+ old.unlink()
833
+ except OSError:
834
+ pass
835
+ shutil.copy2(str(item), str(dest))
836
+ restored += 1
837
+ if restored:
838
+ print(f"[SYNC] βœ“ Restored {restored} sqlite snapshot(s)")
839
+ except Exception as e:
840
+ print(f"[SYNC] sqlite snapshot restore failed: {str(e)[:300]}")
841
+
842
  # ── Pre-gateway legacy cleanup (CRITICAL) ─────────────────────────
843
 
844
  def _retire_workspace_markers(self):