Spaces:
Sleeping
Sleeping
File size: 2,426 Bytes
56833ee d88b60b 56833ee d88b60b 56833ee d88b60b 56833ee d88b60b 56833ee d88b60b 56833ee d88b60b 56833ee d88b60b 56833ee d88b60b 56833ee d88b60b 56833ee d88b60b 56833ee d88b60b 56833ee d88b60b 56833ee d88b60b 56833ee d88b60b 56833ee d88b60b | 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 | from fastapi import FastAPI, Request, HTTPException
from fastapi.responses import StreamingResponse, HTMLResponse
import subprocess
import httpx
app = FastAPI(title="Market-Data Observatory")
# Async HTTP client for proxying to ClickHouse's internal HTTP interface
ch_client = httpx.AsyncClient(base_url="http://127.0.0.1:8123", timeout=60.0)
# ββ Refresh endpoint (git pull) ββ
@app.post("/refresh")
def refresh():
try:
result = subprocess.check_output(
"cd /app/data/ohlc_data && git pull",
shell=True, stderr=subprocess.STDOUT
)
return {"status": "updated", "details": result.decode().strip()}
except subprocess.CalledProcessError as e:
msg = e.output.decode() if e.output else str(e)
raise HTTPException(status_code=500, detail={"error": "Refresh failed", "message": msg})
# ββ Health check ββ
@app.get("/health")
async def health():
try:
r = await ch_client.get("/ping")
return {"clickhouse": r.text.strip(), "status": "ok"}
except Exception as e:
raise HTTPException(status_code=503, detail={"status": "unhealthy", "error": str(e)})
# ββ Catch-all reverse proxy to ClickHouse ββ
# This gives you /play, /dashboard, native HTTP API, everything.
@app.api_route("/{path:path}", methods=["GET", "POST", "PUT", "DELETE", "OPTIONS", "HEAD", "PATCH"])
async def proxy_to_clickhouse(request: Request, path: str):
url = httpx.URL(path=f"/{path}", query=request.url.query.encode("utf-8"))
# Forward headers, strip hop-by-hop
headers = dict(request.headers)
for h in ("host", "content-length", "transfer-encoding"):
headers.pop(h, None)
try:
body = await request.body()
req = ch_client.build_request(
method=request.method,
url=url,
headers=headers,
content=body,
)
r = await ch_client.send(req, stream=True)
# Pass through ClickHouse response headers
resp_headers = dict(r.headers)
for h in ("content-length", "content-encoding", "transfer-encoding"):
resp_headers.pop(h, None)
return StreamingResponse(
r.aiter_raw(),
status_code=r.status_code,
headers=resp_headers,
)
except httpx.RequestError as exc:
raise HTTPException(status_code=502, detail=f"ClickHouse proxy error: {exc}")
|