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.
Files changed (70) hide show
  1. {lockbot-2.7.0/python/lockbot.egg-info → lockbot-2.7.1}/PKG-INFO +1 -1
  2. {lockbot-2.7.0 → lockbot-2.7.1}/pyproject.toml +1 -1
  3. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/backup/scheduler.py +33 -9
  4. {lockbot-2.7.0 → lockbot-2.7.1/python/lockbot.egg-info}/PKG-INFO +1 -1
  5. {lockbot-2.7.0 → lockbot-2.7.1}/LICENSE +0 -0
  6. {lockbot-2.7.0 → lockbot-2.7.1}/MANIFEST.in +0 -0
  7. {lockbot-2.7.0 → lockbot-2.7.1}/README.md +0 -0
  8. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/__init__.py +0 -0
  9. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/__init__.py +0 -0
  10. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/__init__.py +0 -0
  11. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/admin/__init__.py +0 -0
  12. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/admin/router.py +0 -0
  13. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/audit/__init__.py +0 -0
  14. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/audit/models.py +0 -0
  15. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/audit/router.py +0 -0
  16. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/audit/service.py +0 -0
  17. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/auth/__init__.py +0 -0
  18. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/auth/dependencies.py +0 -0
  19. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/auth/models.py +0 -0
  20. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/auth/router.py +0 -0
  21. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/auth/schemas.py +0 -0
  22. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/backup/__init__.py +0 -0
  23. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/backup/router.py +0 -0
  24. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/backup/service.py +0 -0
  25. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/bots/__init__.py +0 -0
  26. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/bots/encryption.py +0 -0
  27. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/bots/manager.py +0 -0
  28. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/bots/models.py +0 -0
  29. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/bots/router.py +0 -0
  30. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/bots/schemas.py +0 -0
  31. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/bots/webhook_handler.py +0 -0
  32. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/config.py +0 -0
  33. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/database.py +0 -0
  34. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/logs/__init__.py +0 -0
  35. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/main.py +0 -0
  36. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/rate_limit.py +0 -0
  37. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/settings/__init__.py +0 -0
  38. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/settings/models.py +0 -0
  39. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/backend/app/settings/router.py +0 -0
  40. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/core/__init__.py +0 -0
  41. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/core/base_bot.py +0 -0
  42. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/core/bot_instance.py +0 -0
  43. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/core/config.py +0 -0
  44. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/core/device_bot.py +0 -0
  45. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/core/device_usage_alert.py +0 -0
  46. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/core/device_usage_utils.py +0 -0
  47. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/core/entry.py +0 -0
  48. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/core/env.py +0 -0
  49. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/core/handler.py +0 -0
  50. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/core/i18n/__init__.py +0 -0
  51. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/core/i18n/en.py +0 -0
  52. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/core/i18n/zh.py +0 -0
  53. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/core/io.py +0 -0
  54. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/core/message_adapter.py +0 -0
  55. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/core/msg_utils.py +0 -0
  56. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/core/node_bot.py +0 -0
  57. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/core/platforms/__init__.py +0 -0
  58. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/core/platforms/infoflow.py +0 -0
  59. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/core/queue_bot.py +0 -0
  60. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/core/request.py +0 -0
  61. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/core/scheduler.py +0 -0
  62. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot/core/utils.py +0 -0
  63. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot.egg-info/SOURCES.txt +0 -0
  64. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot.egg-info/dependency_links.txt +0 -0
  65. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot.egg-info/requires.txt +0 -0
  66. {lockbot-2.7.0 → lockbot-2.7.1}/python/lockbot.egg-info/top_level.txt +0 -0
  67. {lockbot-2.7.0 → lockbot-2.7.1}/setup.cfg +0 -0
  68. {lockbot-2.7.0 → lockbot-2.7.1}/tools/create_super_admin.py +0 -0
  69. {lockbot-2.7.0 → lockbot-2.7.1}/tools/gen_keys.py +0 -0
  70. {lockbot-2.7.0 → lockbot-2.7.1}/tools/reset_super_admin_password.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lockbot
3
- Version: 2.7.0
3
+ Version: 2.7.1
4
4
  Summary: Cluster resource management bot for IM platforms
5
5
  Author-email: Jianbang Yang <yangjianbang112@gmail.com>
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "lockbot"
7
- version = "2.7.0"
7
+ version = "2.7.1"
8
8
  description = "Cluster resource management bot for IM platforms"
9
9
  readme = "README.md"
10
10
  license = {text = "MIT"}
@@ -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, timezone
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(timezone.utc)
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(timezone.utc)
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(timezone.utc) + timedelta(seconds=seconds)
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
- now = datetime.now(timezone.utc)
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())
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lockbot
3
- Version: 2.7.0
3
+ Version: 2.7.1
4
4
  Summary: Cluster resource management bot for IM platforms
5
5
  Author-email: Jianbang Yang <yangjianbang112@gmail.com>
6
6
  License: MIT
File without changes
File without changes
File without changes
File without changes
File without changes