Files
dify/api/services/knowledge_fs/text_search_deadline.py
fd2db63184 feat: KnowledgeFS and New Knowledge (#44165)
Co-authored-by: Jyong <76649700+JohnJyong@users.noreply.github.com>
Co-authored-by: hjlarry <hjlarry@163.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: zhaohao1004 <zhaohao1004@gmail.com>
Co-authored-by: yyh <yuanyouhuilyz@gmail.com>
Co-authored-by: FFXN <lizy@dify.ai>
2026-10-23 03:34:59 +00:00

40 lines
1.4 KiB
Python

"""One bounded budget for a full-text search, including connection setup and cleanup."""
import time
from collections.abc import Generator
from contextlib import contextmanager
from dataclasses import dataclass
from gevent import Timeout
class TextSearchTimeoutError(RuntimeError):
"""The search must stop without returning a successful empty result."""
@dataclass(frozen=True)
class TextSearchDeadline:
expires_at: float
@classmethod
def from_epoch_ms(cls, deadline_ms: int | None) -> "TextSearchDeadline":
# Old KFS callers have no header. They still must finish before the 60s bridge/client.
seconds = 50.0 if deadline_ms is None else min(50.0, deadline_ms / 1000 - time.time())
deadline = cls(time.monotonic() + seconds)
deadline.remaining()
return deadline
def remaining(self) -> float:
seconds = self.expires_at - time.monotonic()
if seconds <= 0:
raise TextSearchTimeoutError("KnowledgeFS full-text search deadline exceeded")
return seconds
@contextmanager
def enforce(self) -> Generator[None]:
# Dify's gevent workers can interrupt cooperative I/O, including endpoint discovery.
# Socket timeouts and SQL execution hints additionally bound TiDB-side work.
with Timeout(self.remaining(), TextSearchTimeoutError("KnowledgeFS full-text search deadline exceeded")):
yield
self.remaining()