Spaces:
Paused
Paused
File size: 4,958 Bytes
ddac050 e1d36ec ddac050 305d870 ddac050 ed64977 ddac050 1f75665 ddac050 29bfaa9 ddac050 4e6308f ddac050 e1d36ec ddac050 e1d36ec ddac050 1f75665 ddac050 e1d36ec 1f75665 ddac050 e1d36ec ddac050 1f75665 ddac050 1f75665 909eff0 ddac050 909eff0 1f75665 ddac050 1f75665 e1d36ec ddac050 e1d36ec fec291d ddac050 1c5cb1e 5492f08 ddac050 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 | from flask import Flask, jsonify
import threading
import time
import requests
from datetime import datetime
import logging
# Setup logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
app = Flask(__name__)
# ============ CONFIG ============
NUM_SERVERS = 55 # serverclass1 to serverclass55
PING_INTERVAL = 21600 # seconds (5 minutes) - like cron-job.org
REQUEST_TIMEOUT = 30
# Extra fixed URLs
EXTRA_URLS = [
"https://dooratre-backup.hf.space/health",
"https://dooratre-reload-bot.hf.space/health",
"https://corvo-ai-cron.hf.space/health",
]
def build_urls():
urls = []
urls.extend(EXTRA_URLS)
return urls
ALL_URLS = build_urls()
# ============ STATE ============
state = {
"running": False,
"thread": None,
"lock": threading.Lock(),
"stop_event": threading.Event(),
"last_cycle_start": None,
"last_cycle_end": None,
"cycles_completed": 0,
"total_pings": 0,
"success_count": 0,
"fail_count": 0,
"last_results": {},
}
def ping_url(url):
try:
r = requests.get(url, timeout=REQUEST_TIMEOUT)
ok = r.status_code == 200
return ok, r.status_code, None
except Exception as e:
return False, None, str(e)
def cron_worker(stop_event: threading.Event):
logger.info(f"Cron worker started. Total URLs: {len(ALL_URLS)}")
while not stop_event.is_set():
cycle_start = datetime.utcnow().isoformat()
state["last_cycle_start"] = cycle_start
logger.info(f"=== Cycle started at {cycle_start} ===")
for url in ALL_URLS:
if stop_event.is_set():
logger.info("Stop event received, breaking cycle.")
break
ok, status, err = ping_url(url)
state["total_pings"] += 1
if ok:
state["success_count"] += 1
logger.info(f"[OK {status}] {url}")
else:
state["fail_count"] += 1
logger.warning(f"[FAIL {status}] {url} | err={err}")
state["last_results"][url] = {
"ok": ok,
"status": status,
"error": err,
"time": datetime.utcnow().isoformat(),
}
state["cycles_completed"] += 1
state["last_cycle_end"] = datetime.utcnow().isoformat()
logger.info(f"=== Cycle done. Sleeping {PING_INTERVAL}s ===")
# Sleep but be responsive to stop_event
stop_event.wait(PING_INTERVAL)
logger.info("Cron worker stopped.")
@app.route("/")
def index():
return jsonify({
"service": "Cron-like pinger",
"running": state["running"],
"total_urls": len(ALL_URLS),
"endpoints": ["/start", "/end", "/status", "/urls"],
})
@app.route("/start", methods=["GET", "POST"])
def start():
with state["lock"]:
if state["running"]:
return jsonify({"status": "already_running"}), 200
state["stop_event"] = threading.Event()
t = threading.Thread(target=cron_worker, args=(state["stop_event"],), daemon=True)
state["thread"] = t
state["running"] = True
t.start()
logger.info("Cron started via /start")
return jsonify({
"status": "started",
"total_urls": len(ALL_URLS),
"interval_seconds": PING_INTERVAL,
})
@app.route("/end", methods=["GET", "POST"])
def end():
with state["lock"]:
if not state["running"]:
return jsonify({"status": "not_running"}), 200
state["stop_event"].set()
state["running"] = False
logger.info("Cron stop requested via /end")
return jsonify({"status": "stopping"})
@app.route("/status")
def status():
return jsonify({
"running": state["running"],
"total_urls": len(ALL_URLS),
"cycles_completed": state["cycles_completed"],
"total_pings": state["total_pings"],
"success_count": state["success_count"],
"fail_count": state["fail_count"],
"last_cycle_start": state["last_cycle_start"],
"last_cycle_end": state["last_cycle_end"],
"interval_seconds": PING_INTERVAL,
})
@app.route("/urls")
def urls():
return jsonify({"count": len(ALL_URLS), "urls": ALL_URLS})
@app.route("/results")
def results():
return jsonify(state["last_results"])
@app.route("/health")
def health():
return jsonify({"status": "ok"})
if __name__ == "__main__":
# Auto-start cron on boot (optional - comment out if you only want manual /start)
# Uncomment below if you want it to auto-run:
# state["stop_event"] = threading.Event()
# t = threading.Thread(target=cron_worker, args=(state["stop_event"],), daemon=True)
# state["thread"] = t
# state["running"] = True
# t.start()
app.run(host="0.0.0.0", port=7860, debug=False, threaded=True) |