File size: 2,864 Bytes
09e32d2
 
 
 
 
 
 
 
 
d100658
09e32d2
 
d100658
09e32d2
 
 
 
 
d100658
09e32d2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d100658
 
 
09e32d2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d100658
09e32d2
d100658
 
 
 
 
 
 
 
 
 
 
09e32d2
 
 
 
d100658
09e32d2
 
 
 
 
d100658
 
 
 
 
 
 
09e32d2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d100658
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
"""
FastAPI server exposing OpenEnv interface over HTTP.
Endpoints: POST /reset, POST /step, GET /state, GET /health, GET /tasks
"""

import sys
import os
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

from fastapi import FastAPI, Request, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from typing import Optional
import uvicorn

from env.cache import CDNCacheEnv, TASK_CONFIGS
from env.models import Action, StepResult

app = FastAPI(title="CDN Cache Optimizer - OpenEnv", version="1.0.0")

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_methods=["*"],
    allow_headers=["*"],
)

_env: Optional[CDNCacheEnv] = None


@app.get("/health")
def health():
    return {"status": "ok", "env": "cdn-cache-optimizer"}

@app.post("/health")
def health_post():
    return {"status": "ok", "env": "cdn-cache-optimizer"}

@app.get("/tasks")
def list_tasks():
    return {
        task_id: {
            "name": cfg.name,
            "difficulty": cfg.difficulty,
            "description": cfg.description,
            "cache_capacity_mb": cfg.cache_capacity_mb,
            "episode_length": cfg.episode_length,
        }
        for task_id, cfg in TASK_CONFIGS.items()
    }

@app.post("/reset")
async def reset(request: Request):
    global _env
    task_id = "task_easy"
    seed = 42
    try:
        body = await request.json()
        task_id = body.get("task_id", "task_easy")
        seed = body.get("seed", 42)
    except Exception:
        pass
    if task_id not in TASK_CONFIGS:
        raise HTTPException(status_code=400, detail=f"Unknown task_id '{task_id}'.")
    _env = CDNCacheEnv(task_id=task_id, seed=seed)
    obs = _env.reset()
    return {"observation": obs.dict(), "task": _env.config.dict()}

@app.post("/step")
async def step(request: Request):
    global _env
    if _env is None:
        raise HTTPException(status_code=400, detail="Call /reset first.")
    if _env._done:
        raise HTTPException(status_code=400, detail="Episode done. Call /reset.")
    evict_file_id = None
    try:
        body = await request.json()
        evict_file_id = body.get("evict_file_id", None)
    except Exception:
        pass
    action = Action(evict_file_id=evict_file_id)
    result: StepResult = _env.step(action)
    return result.dict()

@app.get("/state")
def state():
    global _env
    if _env is None:
        raise HTTPException(status_code=400, detail="Call /reset first.")
    return _env.state()

@app.get("/")
def root():
    return {
        "name": "CDN Cache Optimizer",
        "spec": "OpenEnv v1",
        "endpoints": ["/reset", "/step", "/state", "/health", "/tasks"],
        "tasks": list(TASK_CONFIGS.keys()),
    }

if __name__ == "__main__":
    uvicorn.run("api.main:app", host="0.0.0.0", port=7860, reload=False)