diff --git a/src/bentoml/serving.py b/src/bentoml/serving.py index 09c58fd78d1..f5bc84b58ae 100644 --- a/src/bentoml/serving.py +++ b/src/bentoml/serving.py @@ -590,6 +590,18 @@ def serve_grpc_production( svc = load(bento_identifier, working_dir=working_dir) if not isinstance(svc, Service): + try: + from _bentoml_sdk import Service as NewService + except ImportError: + NewService = None # type: ignore[assignment] + if NewService is not None and isinstance(svc, NewService): + raise BentoMLException( + "gRPC serving is not supported for services defined with the " + "`@bentoml.service` decorator (the bentoml>=1.2 programming " + "model). Use `bentoml serve` to run the service over HTTP, or " + "rewrite it using the legacy `bentoml.Service` API if gRPC is " + "required." + ) raise BentoMLException(f"{type(svc)} type doesn't support gRPC serving") from circus.sockets import CircusSocket # type: ignore diff --git a/tests/unit/test_serve_grpc_new_sdk_error.py b/tests/unit/test_serve_grpc_new_sdk_error.py new file mode 100644 index 00000000000..e5422db8959 --- /dev/null +++ b/tests/unit/test_serve_grpc_new_sdk_error.py @@ -0,0 +1,50 @@ +"""Regression test for bentoml#5607. + +`serve-grpc` used to fail with the unhelpful message:: + + type doesn't support gRPC serving + +when pointed at a service defined with the `@bentoml.service` decorator +(the bentoml>=1.2 programming model). gRPC is only implemented for the +legacy `bentoml.Service` API, so this case should raise a clear error +that tells the user what to do instead. +""" + +from __future__ import annotations + +from pathlib import Path + +import pytest + +from bentoml.exceptions import BentoMLException +from bentoml.serving import serve_grpc_production + +NEW_SDK_SERVICE = """ +from __future__ import annotations + +import bentoml + + +@bentoml.service(name="grpc_smoke") +class Supervisor: + @bentoml.api + def greet(self, name: str = "world") -> str: + return f"hello {name}" +""" + + +def test_serve_grpc_rejects_new_sdk_service_with_clear_message( + tmp_path: Path, +) -> None: + (tmp_path / "service.py").write_text(NEW_SDK_SERVICE) + + with pytest.raises(BentoMLException) as exc_info: + serve_grpc_production( + "service.py:Supervisor", + working_dir=str(tmp_path), + ) + + message = str(exc_info.value) + assert "gRPC serving is not supported" in message + assert "@bentoml.service" in message + assert "bentoml serve" in message