StockEx / frontend /frontend.py
RayMelius's picture
Fix Order Entry connect + back arrows
e9af92b
import sys
sys.path.insert(0, "/app")
from flask import Flask, request, jsonify, render_template
import json, time, os
from shared.config import Config
from shared.kafka_utils import create_producer
app = Flask(__name__, template_folder=os.getenv("TEMPLATE_FOLDER", "templates"))
producer = create_producer(component_name="Frontend")
@app.route('/')
def index():
return render_template('index.html')
@app.route('/health')
def health():
"""Health check endpoint."""
import requests
status = {
"status": "healthy",
"service": "frontend",
"timestamp": time.time()
}
# Check Kafka producer
try:
producer.flush(timeout=1)
status["kafka"] = "connected"
except Exception as e:
status["kafka"] = f"error: {e}"
status["status"] = "degraded"
# Check matcher connectivity
try:
r = requests.get(f"{Config.MATCHER_URL}/health", timeout=2)
if r.status_code == 200:
status["matcher"] = "connected"
else:
status["matcher"] = f"error: status {r.status_code}"
except Exception as e:
status["matcher"] = f"error: {e}"
return jsonify(status)
@app.route('/order', methods=['POST'])
def send_order():
if request.is_json:
data = request.json
else:
data = {
'order_id': request.form.get('order_id') or str(time.time_ns()),
'symbol': request.form.get('symbol'),
'type': request.form.get('type'),
'quantity': int(request.form.get('quantity')),
'price': float(request.form.get('price')),
'timestamp': time.time()
}
producer.send(Config.ORDERS_TOPIC, value=data)
producer.flush()
return jsonify({'status':'sent','data':data})
@app.route('/securities')
def securities():
symbols = []
try:
with open(Config.SECURITIES_FILE) as f:
for line in f:
line = line.strip()
if line and not line.startswith('#'):
symbols.append(line.split('\t')[0])
except Exception:
pass
return jsonify(symbols)
@app.route('/book')
def book():
import requests
symbol = request.args.get('symbol', '')
if not symbol:
return jsonify({"bids": [], "asks": []})
r = requests.get(f"{Config.MATCHER_URL}/orderbook/{symbol}", timeout=3)
return (r.text, r.status_code, {'Content-Type': 'application/json'})
@app.route('/trades')
def trades():
import requests
r = requests.get(f"{Config.MATCHER_URL}/trades", timeout=2)
return (r.text, r.status_code, {'Content-Type': 'application/json'})
if __name__ == '__main__':
port = int(os.getenv('PORT', '5000'))
app.run(host='0.0.0.0', port=port)
@app.route('/submit', methods=['POST'])
def submit_order():
from flask import request
data = None
try:
data = request.get_json(force=True)
except Exception as e:
return jsonify({'status':'badjson','error': str(e)}), 400
if not data:
return jsonify({'status':'no_data'}), 400
try:
fut = producer.send(Config.ORDERS_TOPIC, value=data)
meta = fut.get(timeout=10)
producer.flush()
app.logger.info("Produced order %s -> topic=%s partition=%s offset=%s", data.get('order_id'), meta.topic, meta.partition, meta.offset)
return jsonify({'status':'sent','data':data})
except Exception as e:
app.logger.exception("Failed producing order: %s", e)
return jsonify({'status':'failed','error':str(e)}), 500