Files
ray/python/ray/experimental/serve/frontend/http_frontend.py
T
2019-03-08 16:22:05 -08:00

73 lines
1.9 KiB
Python

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import time
import uvicorn
from starlette.applications import Starlette
from starlette.responses import JSONResponse
import ray
def unwrap(future):
"""Unwrap the result from ray.experimental.server router.
Router returns a list of object ids when you call them.
"""
return ray.get(future)[0]
@ray.remote
class HTTPFrontendActor:
"""HTTP API for an Actor. This exposes /{actor_name} endpoint for query.
Request:
GET /{actor_name} or POST /{actor_name}
Content-type: application/json
{
"slo_ms": float,
"input": any
}
Response:
Content-type: application/json
{
"success": bool,
"actor": str,
"result": any
}
"""
def __init__(self, ip="0.0.0.0", port=8080, router="DefaultRouter"):
self.ip = ip
self.port = port
self.router = ray.experimental.named_actors.get_actor(router)
def start(self):
default_app = Starlette()
@default_app.route("/{actor}", methods=["GET", "POST"])
async def dispatch_remote_function(request):
data = await request.json()
actor_name = request.path_params["actor"]
slo_seconds = data.pop("slo_ms") / 1000
deadline = time.perf_counter() + slo_seconds
inp = data.pop("input")
result_future = unwrap(
self.router.call.remote(actor_name, inp, deadline))
# TODO(simon): change to asyncio ray.get
result = ray.get(result_future)
return JSONResponse({
"success": True,
"actor": actor_name,
"result": result
})
uvicorn.run(default_app, host=self.ip, port=self.port)