nexo-brain 2.3.1 → 2.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/server.py CHANGED
@@ -55,7 +55,71 @@ def _server_init():
55
55
  with open(_pid_file, "w") as f:
56
56
  f.write(str(os.getpid()))
57
57
 
58
- init_db()
58
+ # ── Database initialization with recovery ─────────────────────
59
+ import sqlite3
60
+ try:
61
+ init_db()
62
+ except sqlite3.DatabaseError as exc:
63
+ # Corruption or unreadable DB — attempt restore from backup
64
+ print(f"[NEXO] DB init failed: {exc}", file=sys.stderr)
65
+ _recovered = False
66
+ try:
67
+ from db._core import DB_PATH as _db_path
68
+ import glob as _glob
69
+ _backup_dir = os.path.join(
70
+ os.environ.get("NEXO_HOME", os.path.join(os.path.expanduser("~"), ".nexo")),
71
+ "backups",
72
+ )
73
+ _backups = sorted(_glob.glob(os.path.join(_backup_dir, "nexo-*.db")), reverse=True)
74
+ for _bk in _backups:
75
+ try:
76
+ _test = sqlite3.connect(_bk)
77
+ _result = _test.execute("PRAGMA integrity_check").fetchone()
78
+ _test.close()
79
+ if _result and _result[0] == "ok":
80
+ # Valid backup found — replace corrupt DB
81
+ import shutil
82
+ # Close any open connection before replacing
83
+ try:
84
+ close_db()
85
+ except Exception:
86
+ pass
87
+ shutil.copy2(_bk, _db_path)
88
+ print(f"[NEXO] Restored DB from backup: {os.path.basename(_bk)}", file=sys.stderr)
89
+ init_db()
90
+ _recovered = True
91
+ break
92
+ except Exception:
93
+ continue
94
+ except Exception as restore_exc:
95
+ print(f"[NEXO] Backup restore failed: {restore_exc}", file=sys.stderr)
96
+
97
+ if not _recovered:
98
+ # No valid backup — nuke corrupt file and start fresh
99
+ try:
100
+ close_db()
101
+ except Exception:
102
+ pass
103
+ try:
104
+ from db._core import DB_PATH as _db_path
105
+ if os.path.exists(_db_path):
106
+ _corrupt_path = _db_path + ".corrupt"
107
+ os.rename(_db_path, _corrupt_path)
108
+ print(f"[NEXO] Corrupt DB moved to {os.path.basename(_corrupt_path)}", file=sys.stderr)
109
+ # Remove WAL/SHM files too
110
+ for _ext in (".db-wal", ".db-shm"):
111
+ _wal = _db_path.replace(".db", _ext)
112
+ if os.path.exists(_wal):
113
+ os.remove(_wal)
114
+ except Exception:
115
+ pass
116
+ try:
117
+ init_db()
118
+ print("[NEXO] Fresh database created.", file=sys.stderr)
119
+ except Exception as fresh_exc:
120
+ print(f"[NEXO] FATAL: Cannot initialize database: {fresh_exc}", file=sys.stderr)
121
+ print("[NEXO] Check permissions on NEXO_HOME/data/ and disk space.", file=sys.stderr)
122
+ sys.exit(1)
59
123
 
60
124
  # ── Auto-update check (non-blocking, max 5s) ──────────────────
61
125
  try: