lockbot 2.7.0__tar.gz → 2.7.1__tar.gz
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.
- {lockbot-2.7.0/python/lockbot.egg-info → lockbot-2.7.1}/PKG-INFO +1 -1
- {lockbot-2.7.0 → lockbot-2.7.1}/pyproject.toml +1 -1
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/backup/scheduler.py +33 -9
- {lockbot-2.7.0 → lockbot-2.7.1/python/lockbot.egg-info}/PKG-INFO +1 -1
- {lockbot-2.7.0 → lockbot-2.7.1}/LICENSE +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/MANIFEST.in +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/README.md +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/__init__.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/__init__.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/__init__.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/admin/__init__.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/admin/router.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/audit/__init__.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/audit/models.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/audit/router.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/audit/service.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/auth/__init__.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/auth/dependencies.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/auth/models.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/auth/router.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/auth/schemas.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/backup/__init__.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/backup/router.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/backup/service.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/bots/__init__.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/bots/encryption.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/bots/manager.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/bots/models.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/bots/router.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/bots/schemas.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/bots/webhook_handler.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/config.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/database.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/logs/__init__.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/main.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/rate_limit.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/settings/__init__.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/settings/models.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/settings/router.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/core/__init__.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/core/base_bot.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/core/bot_instance.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/core/config.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/core/device_bot.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/core/device_usage_alert.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/core/device_usage_utils.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/core/entry.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/core/env.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/core/handler.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/core/i18n/__init__.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/core/i18n/en.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/core/i18n/zh.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/core/io.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/core/message_adapter.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/core/msg_utils.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/core/node_bot.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/core/platforms/__init__.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/core/platforms/infoflow.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/core/queue_bot.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/core/request.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/core/scheduler.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/core/utils.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot.egg-info/SOURCES.txt +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot.egg-info/dependency_links.txt +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot.egg-info/requires.txt +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot.egg-info/top_level.txt +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/setup.cfg +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/tools/create_super_admin.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/tools/gen_keys.py +0 -0
- {lockbot-2.7.0 → lockbot-2.7.1}/tools/reset_super_admin_password.py +0 -0
|
@@ -4,7 +4,7 @@ Backup scheduler — daemon thread for periodic BOS backups.
|
|
|
4
4
|
|
|
5
5
|
import logging
|
|
6
6
|
import threading
|
|
7
|
-
from datetime import datetime, timedelta
|
|
7
|
+
from datetime import datetime, timedelta
|
|
8
8
|
|
|
9
9
|
logger = logging.getLogger(__name__)
|
|
10
10
|
|
|
@@ -25,7 +25,7 @@ class BackupScheduler:
|
|
|
25
25
|
if self._thread and self._thread.is_alive():
|
|
26
26
|
return
|
|
27
27
|
self._stop_event.clear()
|
|
28
|
-
self._started_at = datetime.now(
|
|
28
|
+
self._started_at = datetime.now()
|
|
29
29
|
self._last_error = ""
|
|
30
30
|
self._thread = threading.Thread(target=self._run, daemon=True, name="backup-scheduler")
|
|
31
31
|
self._thread.start()
|
|
@@ -56,11 +56,11 @@ class BackupScheduler:
|
|
|
56
56
|
|
|
57
57
|
def _run(self):
|
|
58
58
|
while not self._stop_event.is_set():
|
|
59
|
-
self._last_heartbeat = datetime.now(
|
|
59
|
+
self._last_heartbeat = datetime.now()
|
|
60
60
|
try:
|
|
61
61
|
seconds = self._seconds_until_next()
|
|
62
62
|
if seconds is not None:
|
|
63
|
-
self._next_run_at = datetime.now(
|
|
63
|
+
self._next_run_at = datetime.now() + timedelta(seconds=seconds)
|
|
64
64
|
else:
|
|
65
65
|
self._next_run_at = None
|
|
66
66
|
if seconds is None:
|
|
@@ -76,7 +76,9 @@ class BackupScheduler:
|
|
|
76
76
|
if triggered or self._stop_event.is_set():
|
|
77
77
|
continue # Config changed or shutting down, recalculate
|
|
78
78
|
|
|
79
|
-
# Time to backup
|
|
79
|
+
# Time to backup — skip if last successful backup was recent
|
|
80
|
+
if self._should_skip():
|
|
81
|
+
continue
|
|
80
82
|
self._do_backup()
|
|
81
83
|
except Exception as exc:
|
|
82
84
|
self._last_error = str(exc)
|
|
@@ -84,6 +86,30 @@ class BackupScheduler:
|
|
|
84
86
|
# Sleep a bit before retry
|
|
85
87
|
self._stop_event.wait(timeout=60)
|
|
86
88
|
|
|
89
|
+
def _should_skip(self) -> bool:
|
|
90
|
+
"""Skip if last successful backup was less than 20 hours ago (prevents duplicates on restart)."""
|
|
91
|
+
from lockbot.backend.app.backup.service import get_backup_config
|
|
92
|
+
from lockbot.backend.app.database import SessionLocal
|
|
93
|
+
|
|
94
|
+
db = SessionLocal()
|
|
95
|
+
try:
|
|
96
|
+
config = get_backup_config(db)
|
|
97
|
+
finally:
|
|
98
|
+
db.close()
|
|
99
|
+
|
|
100
|
+
last_time = config.get("backup_last_time", "")
|
|
101
|
+
last_status = config.get("backup_last_status", "")
|
|
102
|
+
if not last_time or last_status != "success":
|
|
103
|
+
return False
|
|
104
|
+
try:
|
|
105
|
+
last_dt = datetime.strptime(last_time, "%Y-%m-%d %H:%M:%S")
|
|
106
|
+
if (datetime.now() - last_dt).total_seconds() < 20 * 3600:
|
|
107
|
+
logger.info("Skipping backup — last success was %s (< 20h ago)", last_time)
|
|
108
|
+
return True
|
|
109
|
+
except ValueError:
|
|
110
|
+
pass
|
|
111
|
+
return False
|
|
112
|
+
|
|
87
113
|
def _seconds_until_next(self) -> int | None:
|
|
88
114
|
"""Calculate seconds until next backup. Returns None if disabled."""
|
|
89
115
|
from lockbot.backend.app.backup.service import get_backup_config
|
|
@@ -110,12 +136,10 @@ class BackupScheduler:
|
|
|
110
136
|
except (ValueError, IndexError):
|
|
111
137
|
return None
|
|
112
138
|
|
|
113
|
-
|
|
139
|
+
# Use local time (server timezone) for scheduling
|
|
140
|
+
now = datetime.now()
|
|
114
141
|
target = now.replace(hour=hour, minute=minute, second=0, microsecond=0)
|
|
115
142
|
if target <= now:
|
|
116
|
-
# Next day
|
|
117
|
-
from datetime import timedelta
|
|
118
|
-
|
|
119
143
|
target += timedelta(days=1)
|
|
120
144
|
|
|
121
145
|
return int((target - now).total_seconds())
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|