ritvikv03 Claude Sonnet 4.6 commited on
Commit Β·
ee79fe2
1
Parent(s): 6fa571d
fix: start scheduler at module load so gunicorn workers run the scout
Browse filesPreviously _scheduler_engine.start() was inside if __name__ == '__main__':
which gunicorn never enters (it imports the module as 'app', not '__main__').
The scheduler was dead on every HuggingFace deployment β no new signals.
Changes:
- app.py: move _scheduler_engine.start() + atexit.register(stop) to
module level, immediately after app.layout = _layout(). Runs under
both gunicorn and direct python execution. Remove duplicate start()
from __main__ block.
- core/scheduler.py: set next_run_time=datetime.now(timezone.utc) so
the first scout cycle fires immediately on startup instead of waiting
6 hours. Subsequent runs still follow the 6-hour interval.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- app.py +10 -2
- core/scheduler.py +4 -2
app.py
CHANGED
|
@@ -19,6 +19,7 @@ Sponsor requirements implemented:
|
|
| 19 |
|
| 20 |
from __future__ import annotations
|
| 21 |
|
|
|
|
| 22 |
import hashlib
|
| 23 |
import os
|
| 24 |
import sys
|
|
@@ -1644,6 +1645,14 @@ def _layout() -> html.Div:
|
|
| 1644 |
|
| 1645 |
app.layout = _layout()
|
| 1646 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1647 |
|
| 1648 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 1649 |
# Callbacks
|
|
@@ -2082,7 +2091,7 @@ def lens_search(topic: str | None, custom: str | None, _ns: int) -> html.Div:
|
|
| 2082 |
if __name__ == "__main__":
|
| 2083 |
_preflight()
|
| 2084 |
|
| 2085 |
-
|
| 2086 |
stats = _db_stats_cached()
|
| 2087 |
log.info("App starting β Astra DB: %d signals, HuggingFace: %s",
|
| 2088 |
stats["total"], "OK" if _HF_OK else "NO KEY")
|
|
@@ -2096,4 +2105,3 @@ if __name__ == "__main__":
|
|
| 2096 |
# Use PORT env var (Hugging Face / Render) or default to 7860
|
| 2097 |
port = int(os.environ.get("PORT", 7860))
|
| 2098 |
app.run(debug=False, host="0.0.0.0", port=port)
|
| 2099 |
-
_scheduler_engine.stop()
|
|
|
|
| 19 |
|
| 20 |
from __future__ import annotations
|
| 21 |
|
| 22 |
+
import atexit
|
| 23 |
import hashlib
|
| 24 |
import os
|
| 25 |
import sys
|
|
|
|
| 1645 |
|
| 1646 |
app.layout = _layout()
|
| 1647 |
|
| 1648 |
+
# ββ Start scheduler at module load (works under gunicorn and __main__) ββ
|
| 1649 |
+
# Must be AFTER app.layout so Dash is fully initialised.
|
| 1650 |
+
# gunicorn imports this module directly β __main__ guard would skip it.
|
| 1651 |
+
_scheduler_engine.start()
|
| 1652 |
+
atexit.register(_scheduler_engine.stop)
|
| 1653 |
+
log.info("SchedulerEngine started at module load. Next scout: %s",
|
| 1654 |
+
HEALTH.get("next_run_utc"))
|
| 1655 |
+
|
| 1656 |
|
| 1657 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 1658 |
# Callbacks
|
|
|
|
| 2091 |
if __name__ == "__main__":
|
| 2092 |
_preflight()
|
| 2093 |
|
| 2094 |
+
# Scheduler already started at module load β just log status
|
| 2095 |
stats = _db_stats_cached()
|
| 2096 |
log.info("App starting β Astra DB: %d signals, HuggingFace: %s",
|
| 2097 |
stats["total"], "OK" if _HF_OK else "NO KEY")
|
|
|
|
| 2105 |
# Use PORT env var (Hugging Face / Render) or default to 7860
|
| 2106 |
port = int(os.environ.get("PORT", 7860))
|
| 2107 |
app.run(debug=False, host="0.0.0.0", port=port)
|
|
|
core/scheduler.py
CHANGED
|
@@ -186,14 +186,16 @@ class SchedulerEngine:
|
|
| 186 |
timezone="UTC",
|
| 187 |
)
|
| 188 |
|
| 189 |
-
# Scout job β
|
|
|
|
|
|
|
| 190 |
self._scheduler.add_job(
|
| 191 |
_run_scout_cycle,
|
| 192 |
trigger=IntervalTrigger(hours=self._interval_hours),
|
| 193 |
id="scout",
|
| 194 |
name="PESTEL Scout Cycle",
|
| 195 |
replace_existing=True,
|
| 196 |
-
next_run_time=
|
| 197 |
)
|
| 198 |
|
| 199 |
# Heartbeat β every 30 s
|
|
|
|
| 186 |
timezone="UTC",
|
| 187 |
)
|
| 188 |
|
| 189 |
+
# Scout job β fires immediately on first start, then every N hours.
|
| 190 |
+
# next_run_time=now() ensures the first cycle runs right away so the
|
| 191 |
+
# dashboard is populated without waiting 6 hours after deployment.
|
| 192 |
self._scheduler.add_job(
|
| 193 |
_run_scout_cycle,
|
| 194 |
trigger=IntervalTrigger(hours=self._interval_hours),
|
| 195 |
id="scout",
|
| 196 |
name="PESTEL Scout Cycle",
|
| 197 |
replace_existing=True,
|
| 198 |
+
next_run_time=datetime.now(timezone.utc),
|
| 199 |
)
|
| 200 |
|
| 201 |
# Heartbeat β every 30 s
|