Skip to content

Commit 6eea834

Browse files
authored
fix: race condition issue initializing result db (#5369)
* fix: race condition issue initializing result db Signed-off-by: Frost Ming <me@frostming.com> * fix: only init db when needed Signed-off-by: Frost Ming <me@frostming.com>
1 parent 7da959d commit 6eea834

File tree

4 files changed

+38
-22
lines changed

4 files changed

+38
-22
lines changed

src/_bentoml_impl/server/app.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -306,9 +306,10 @@ async def create_instance(self, app: Starlette) -> None:
306306
self._service_instance.to_async = proxy.to_async # type: ignore[attr-defined]
307307
self._service_instance.to_sync = proxy.to_sync # type: ignore[attr-defined]
308308
set_current_service(self._service_instance)
309-
store_path = BentoMLContainer.result_store_file.get()
310-
self._result_store = Sqlite3Store(store_path)
311-
await self._result_store.__aenter__()
309+
if self.service.needs_task_db():
310+
store_path = BentoMLContainer.result_store_file.get()
311+
self._result_store = Sqlite3Store(store_path)
312+
await self._result_store.__aenter__()
312313

313314
@inject
314315
def _add_response_headers(
@@ -356,7 +357,8 @@ async def destroy_instance(self, _: Starlette) -> None:
356357
logger.info("Service instance cleanup finalized")
357358
self._service_instance = None
358359
set_current_service(None)
359-
await self._result_store.__aexit__(None, None, None)
360+
if hasattr(self, "_result_store"):
361+
await self._result_store.__aexit__(None, None, None)
360362

361363
async def livez(self, _: Request) -> Response:
362364
from starlette.exceptions import HTTPException

src/_bentoml_impl/server/serving.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,8 @@ def server_on_deployment(
140140
svc: AnyService, result_file: str = Provide[BentoMLContainer.result_store_file]
141141
) -> None:
142142
# Resolve models before server starts.
143+
from ..tasks.result import Sqlite3Store
144+
143145
if bento := svc.bento:
144146
for model in bento.info.all_models:
145147
model.to_model().resolve()
@@ -150,8 +152,10 @@ def server_on_deployment(
150152
member = getattr(svc.inner, name)
151153
if callable(member) and getattr(member, "__bentoml_deployment_hook__", False):
152154
member()
153-
if os.path.exists(result_file):
154-
os.remove(result_file)
155+
if svc.needs_task_db():
156+
if os.path.exists(result_file):
157+
os.remove(result_file)
158+
Sqlite3Store.init_db(result_file)
155159

156160

157161
@inject(squeeze_none=True)

src/_bentoml_impl/tasks/result.py

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -109,28 +109,33 @@ def _connect(self, db_file: str) -> Connection:
109109

110110
async def __aenter__(self) -> "t.Self":
111111
self._conn = await self._conn
112-
await self._init_db()
113112
return self
114113

115114
async def __aexit__(self, *_: t.Any) -> None:
116115
await self._conn.close()
117116

118-
async def _init_db(self) -> None:
119-
await self._conn.execute(
120-
textwrap.dedent("""\
121-
CREATE TABLE IF NOT EXISTS result (
122-
task_id TEXT PRIMARY KEY,
123-
name TEXT,
124-
input BLOB,
125-
status TEXT,
126-
result BLOB,
127-
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
128-
executed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
129-
completed_at TIMESTAMP DEFAULT NULL
117+
@classmethod
118+
def init_db(cls, db_file: str) -> None:
119+
import sqlite3
120+
121+
with sqlite3.connect(
122+
db_file, detect_types=sqlite3.PARSE_DECLTYPES | sqlite3.PARSE_COLNAMES
123+
) as conn:
124+
conn.execute(
125+
textwrap.dedent("""\
126+
CREATE TABLE IF NOT EXISTS result (
127+
task_id TEXT PRIMARY KEY,
128+
name TEXT,
129+
input BLOB,
130+
status TEXT,
131+
result BLOB,
132+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
133+
executed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
134+
completed_at TIMESTAMP DEFAULT NULL
135+
)
136+
""")
130137
)
131-
""")
132-
)
133-
await self._conn.commit()
138+
conn.commit()
134139

135140
async def new_entry(self, name: str, input: Request) -> str:
136141
task_id = uuid.uuid4().hex

src/_bentoml_sdk/service/factory.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,11 @@ def on_load_bento(self, bento: Bento) -> None:
473473
model.revision = revision
474474
svc.bento = bento
475475

476+
def needs_task_db(self) -> bool:
477+
if "BENTOCLOUD_DEPLOYMENT_URL" in os.environ:
478+
return False
479+
return any(method.is_task for method in self.apis.values())
480+
476481

477482
@t.overload
478483
def service(inner: type[T], /) -> Service[T]: ...

0 commit comments

Comments
 (0)