From 0b1a14a2e953540ea78142251ce8c240048d2549 Mon Sep 17 00:00:00 2001 From: Sauyon Lee Date: Thu, 27 Oct 2022 04:28:54 -0700 Subject: [PATCH 1/4] fix: async bento client methods --- src/bentoml/client.py | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/src/bentoml/client.py b/src/bentoml/client.py index cef67a1eac..d6942ab8a5 100644 --- a/src/bentoml/client.py +++ b/src/bentoml/client.py @@ -1,12 +1,16 @@ from __future__ import annotations +import asyncio import typing as t import functools from abc import ABC from abc import abstractmethod +from http.client import HTTPConnection +from urllib.parse import urlparse import aiohttp import starlette.requests +import json import starlette.datastructures import bentoml @@ -27,15 +31,19 @@ def __init__(self, svc: Service, server_url: str): for name, api in self._svc.apis.items(): if not hasattr(self, name): - setattr(self, name, functools.partial(self._call, _bentoml_api=api)) + setattr(self, name, functools.partial(self._sync_call, _bentoml_api=api)) + setattr(self, f"async_{name}", functools.partial(self._call, _bentoml_api=api)) - def call(self, api_name: str, inp: t.Any = None, **kwargs: t.Any) -> t.Any: - asyncio.run(self.async_call(api_name, inp)) + def call(self, bentoml_api_name: str, inp: t.Any = None, **kwargs: t.Any) -> t.Any: + return asyncio.run(self.async_call(bentoml_api_name, inp)) async def async_call( - self, api_name: str, inp: t.Any = None, **kwargs: t.Any + self, bentoml_api_name: str, inp: t.Any = None, **kwargs: t.Any ) -> t.Any: - return self._call(inp, _bentoml_api=self._svc.apis[api_name]) + return await self._call(inp, _bentoml_api=self._svc.apis[bentoml_api_name]) + + def _sync_call(self, inp: t.Any = None, *, _bentoml_api: InferenceAPI, **kwagrs: t.Any): + return asyncio.run(self._call(inp, _bentoml_api=_bentoml_api)) @abstractmethod async def _call( @@ -44,12 +52,16 @@ async def _call( raise NotImplementedError @staticmethod - async def from_url(server_url: str) -> Client: + def from_url(server_url: str) -> Client: + server_url = server_url if "://" in server_url else "http://" + server_url + url_parts = urlparse(server_url) + # TODO: SSL and grpc support - # connection is passed off to the client, and so is not closed - async with aiohttp.ClientSession(server_url) as conn: - async with conn.get("/docs.json") as resp: - openapi_spec = await resp.json() + conn = HTTPConnection(url_parts.netloc) + conn.request("GET", "/docs.json") + resp = conn.getresponse() + openapi_spec = json.load(resp) + conn.close() dummy_service = Service(openapi_spec["info"]["title"]) From 9a6d66ec69e3e2565c46f622b1eaae8b1e167c5d Mon Sep 17 00:00:00 2001 From: sauyon <2347889+sauyon@users.noreply.github.com> Date: Thu, 27 Oct 2022 20:24:33 -0700 Subject: [PATCH 2/4] format? --- src/bentoml/client.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/bentoml/client.py b/src/bentoml/client.py index d6942ab8a5..322cb448e3 100644 --- a/src/bentoml/client.py +++ b/src/bentoml/client.py @@ -31,8 +31,14 @@ def __init__(self, svc: Service, server_url: str): for name, api in self._svc.apis.items(): if not hasattr(self, name): - setattr(self, name, functools.partial(self._sync_call, _bentoml_api=api)) - setattr(self, f"async_{name}", functools.partial(self._call, _bentoml_api=api)) + setattr( + self, name, functools.partial(self._sync_call, _bentoml_api=api) + ) + setattr( + self, + f"async_{name}", + functools.partial(self._call, _bentoml_api=api), + ) def call(self, bentoml_api_name: str, inp: t.Any = None, **kwargs: t.Any) -> t.Any: return asyncio.run(self.async_call(bentoml_api_name, inp)) @@ -42,7 +48,9 @@ async def async_call( ) -> t.Any: return await self._call(inp, _bentoml_api=self._svc.apis[bentoml_api_name]) - def _sync_call(self, inp: t.Any = None, *, _bentoml_api: InferenceAPI, **kwagrs: t.Any): + def _sync_call( + self, inp: t.Any = None, *, _bentoml_api: InferenceAPI, **kwagrs: t.Any + ): return asyncio.run(self._call(inp, _bentoml_api=_bentoml_api)) @abstractmethod From 8d475aa5ca6e2a7af794ff38c65d00aee37daeaa Mon Sep 17 00:00:00 2001 From: Sauyon Lee Date: Thu, 27 Oct 2022 13:14:55 -0700 Subject: [PATCH 3/4] format --- src/bentoml/client.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bentoml/client.py b/src/bentoml/client.py index 322cb448e3..65fb5772c6 100644 --- a/src/bentoml/client.py +++ b/src/bentoml/client.py @@ -1,7 +1,8 @@ from __future__ import annotations -import asyncio +import json import typing as t +import asyncio import functools from abc import ABC from abc import abstractmethod @@ -10,7 +11,6 @@ import aiohttp import starlette.requests -import json import starlette.datastructures import bentoml From 8fdf5cc5cc842908c9b8ec1453017c1b9b94b50f Mon Sep 17 00:00:00 2001 From: Sauyon Lee Date: Fri, 28 Oct 2022 03:47:31 -0700 Subject: [PATCH 4/4] address review comment --- src/bentoml/client.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/bentoml/client.py b/src/bentoml/client.py index 65fb5772c6..4b08fd4514 100644 --- a/src/bentoml/client.py +++ b/src/bentoml/client.py @@ -34,6 +34,9 @@ def __init__(self, svc: Service, server_url: str): setattr( self, name, functools.partial(self._sync_call, _bentoml_api=api) ) + + for name, api in self._svc.apis.items(): + if not hasattr(self, f"async_{name}"): setattr( self, f"async_{name}",