Spaces:
Running
Running
File size: 6,953 Bytes
042d8bf 84c65b6 042d8bf 84c65b6 042d8bf 84c65b6 042d8bf 84c65b6 042d8bf 84c65b6 042d8bf 84c65b6 042d8bf 84c65b6 042d8bf 84c65b6 042d8bf 84c65b6 042d8bf 84c65b6 042d8bf 84c65b6 042d8bf 84c65b6 042d8bf 84c65b6 042d8bf 84c65b6 042d8bf 84c65b6 042d8bf 84c65b6 042d8bf 84c65b6 042d8bf 84c65b6 042d8bf 84c65b6 |
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 |
#!/usr/bin/env python3
"""
external_server.py โ ุณูุฑูุฑ ู
ุฑูุฒู ูุชูุฒูุน ุงูู
ูุงู
+ Dashboard ุชูุงุนูู
"""
import logging
import requests
import socket
from flask import Flask, request, jsonify, render_template
from flask_cors import CORS
from flask_socketio import SocketIO, emit
from peer_discovery import PEERS
from peer_discovery import PORT
logging.basicConfig(level=logging.INFO)
app = Flask(__name__)
CORS(app, resources={r"/*": {"origins": "*"}})
socketio = SocketIO(app, cors_allowed_origins="*")
connected_peers = {} # {node_id: {"cpu":%, "ram":%, "gpu":%}}
# โโโโโโโโโโโโโโโ ุงูุชุญูู ู
ู ุชููุฑ ุงูู
ููุฐ โโโโโโโโโโโโโโโ
def is_port_available(port):
try:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind(('0.0.0.0', port))
return True
except OSError:
return False
# โโโโโโโโโโโโโโโ ุงุฎุชูุงุฑ ุฃูุถู Peer โโโโโโโโโโโโโโโ
def select_best_peer():
if not PEERS:
logging.warning("โ ๏ธ ูุง ุชูุฌุฏ ุฃุฌูุฒุฉ ู
ุณุฌูุฉ ุญุงููุงู.")
return None
try:
peer_loads = []
for peer_url in PEERS:
try:
# ุจูุงุก URL ููุญุต ุงูุญุงูุฉ
status_url = peer_url.replace('/run_task', '/health')
if '/run_task' not in peer_url:
status_url = f"{peer_url}/health"
resp = requests.get(status_url, timeout=2)
if resp.ok:
data = resp.json()
# ุงูุชุฑุงุถ ุฃู ุงูุฎุงุฏู
ูุนูุฏ cpu_load ุฃู ุงุณุชุฎุฏุงู
ููู
ุฉ ุงูุชุฑุงุถูุฉ
cpu_load = data.get("cpu_load", 50)
peer_loads.append((peer_url, cpu_load))
logging.info(f"โ
{peer_url} - ุงูุญู
ู: {cpu_load}%")
except Exception as e:
logging.warning(f"โ ูุง ูู
ูู ุงููุตูู ุฅูู {peer_url}: {e}")
continue
if not peer_loads:
return None
# ุงุฎุชูุงุฑ ุงูุฃูู ุญู
ููุง
best_peer = min(peer_loads, key=lambda x: x[1])
logging.info(f"๐ฏ ุฃูุถู ุฌูุงุฒ: {best_peer[0]} ู
ุน ุญู
ู {best_peer[1]}%")
return best_peer[0]
except Exception as e:
logging.error(f"โ ุฎุทุฃ ูู ุงุฎุชูุงุฑ ุงูู Peer: {e}")
return None
# โโโโโโโโโโโโโโโ API ุชูุฒูุน ุงูู
ูุงู
โโโโโโโโโโโโโโโ
@app.route("/submit_task", methods=["POST"])
def submit_task():
data = request.get_json()
if not data or "func" not in data:
return jsonify({"error": "ูุฌุจ ุชุญุฏูุฏ ุงุณู
ุงูุฏุงูุฉ (func)"}), 400
peer = select_best_peer()
if not peer:
return jsonify({"error": "ูุง ุชูุฌุฏ ุฃุฌูุฒุฉ ู
ุชุงุญุฉ ุญุงููุงู"}), 503
try:
# ุชุฃูุฏ ู
ู ุฃู ุนููุงู ุงูู Peer ุตุญูุญ
if not peer.startswith('http'):
peer = f"http://{peer}"
logging.info(f"๐ค ุฅุฑุณุงู ุงูู
ูู
ุฉ ุฅูู: {peer}")
resp = requests.post(peer, json=data, timeout=30)
if resp.ok:
result = resp.json()
logging.info(f"โ
ุชู
ุชูููุฐ ุงูู
ูู
ุฉ ุจูุฌุงุญ ุนูู {peer}")
return jsonify({"status": "success", "result": result, "executed_on": peer})
else:
logging.error(f"โ ูุดู ุชูููุฐ ุงูู
ูู
ุฉ ุนูู {peer}: {resp.status_code}")
return jsonify({"error": f"ูุดู ุฅุฑุณุงู ุงูู
ูู
ุฉ: {resp.text}"}), 500
except requests.exceptions.Timeout:
logging.error(f"โฐ ุงูุชูุช ุงูู
ููุฉ ุฃุซูุงุก ุงูุงุชุตุงู ุจู {peer}")
return jsonify({"error": "ุงูุชูุช ู
ููุฉ ุงูุงุชุตุงู"}), 408
except Exception as e:
logging.error(f"โ ุฎุทุฃ ูู ุฅุฑุณุงู ุงูู
ูู
ุฉ ุฅูู {peer}: {e}")
return jsonify({"error": str(e)}), 500
# โโโโโโโโโโโโโโโ API ุชุญุฏูุซ ุญุงูุฉ ุงูุฃุฌูุฒุฉ โโโโโโโโโโโโโโโ
@app.route("/update_status", methods=["POST"])
def update_status():
data = request.json
node_id = data.get("node_id")
if not node_id:
return jsonify({"error": "node_id ู
ุทููุจ"}), 400
connected_peers[node_id] = {
"cpu": data.get("cpu", 0),
"ram": data.get("ram", 0),
"gpu": data.get("gpu", 0),
"last_update": "now" # ูู
ูู ุฅุถุงูุฉ timestamp
}
socketio.emit("update_peers", connected_peers, broadcast=True)
logging.info(f"๐ ุชู
ุชุญุฏูุซ ุญุงูุฉ {node_id}")
return jsonify({"status": "ok"})
# โโโโโโโโโโโโโโโ ุตูุญุฉ ุงูุญุงูุฉ โโโโโโโโโโโโโโโ
@app.route("/status")
def status():
return jsonify({
"connected_peers": connected_peers,
"available_peers": list(PEERS),
"total_peers": len(PEERS)
})
# โโโโโโโโโโโโโโโ ุตูุญุฉ Dashboard โโโโโโโโโโโโโโโ
@app.route("/")
def index():
return render_template("dashboard.html", peers=connected_peers)
# โโโโโโโโโโโโโโโ ุงุณุชูุจุงู ุชุญุฏูุซุงุช ุงูุญุงูุฉ ุนุจุฑ WebSocket โโโโโโโโโโโโโโโ
@socketio.on("status_update")
def handle_status_update(data):
connected_peers.update(data)
emit("update_peers", connected_peers, broadcast=True)
# โโโโโโโโโโโโโโโ ุฏุฑุฏุดุฉ โโโโโโโโโโโโโโโ
@socketio.on("send_message")
def handle_message(data):
emit("receive_message", data, broadcast=True)
# โโโโโโโโโโโโโโโ ุชุดุบูู ุงูุณูุฑูุฑ โโโโโโโโโโโโโโโ
if __name__ == "__main__":
# ู
ุญุงููุฉ ู
ูุงูุฐ ู
ุฎุชููุฉ
ports_to_try = [5005, 5006, 5007, 5008, 5009]
selected_port = None
for port in ports_to_try:
if is_port_available(port):
selected_port = port
break
if selected_port is None:
logging.error("โ ูุง ุชูุฌุฏ ู
ูุงูุฐ ู
ุชุงุญุฉ. ุญุงูู ุฅุบูุงู ุงูุชุทุจููุงุช ุงูุฃุฎุฑู.")
exit(1)
logging.info(f"๐ ุจุฏุก ุงูุณูุฑูุฑ ุงูู
ุฑูุฒู ู
ุน Dashboard ุนูู ุงูู
ููุฐ {selected_port}")
try:
socketio.run(app, host="0.0.0.0", port=selected_port, debug=False)
except OSError as e:
logging.error(f"โ ูุดู ุชุดุบูู ุงูุณูุฑูุฑ ุนูู ุงูู
ููุฐ {selected_port}: {e}")
except KeyboardInterrupt:
logging.info("โน๏ธ ุฅููุงู ุงูุณูุฑูุฑ...")
except Exception as e:
logging.error(f"โ ุฎุทุฃ ุบูุฑ ู
ุชููุน: {e}")
|