Skip to content

Commit ac9e44b

Browse files
committed
wait until ready
1 parent 111007f commit ac9e44b

File tree

1 file changed

+64
-5
lines changed

1 file changed

+64
-5
lines changed

whispercpppy/server.py

Lines changed: 64 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from __future__ import annotations
22

33
import subprocess
4+
import time
45
from pathlib import Path
56
from typing import Literal
67

@@ -116,12 +117,25 @@ def __init__(
116117
vad_options: VoiceActivityDetectionOptions | None,
117118
binary: str = "whisper-server",
118119
autostart: bool = True,
120+
ready_timeout_s: float | None = 30.0,
121+
ready_check_interval_s: float = 0.25,
122+
ready_probe_timeout_s: float = 1.0,
119123
) -> None:
124+
if ready_check_interval_s <= 0:
125+
raise ValueError("'ready_check_interval_s' must be positive")
126+
if ready_probe_timeout_s <= 0:
127+
raise ValueError("'ready_probe_timeout_s' must be positive")
128+
if ready_timeout_s is not None and ready_timeout_s < 0:
129+
raise ValueError("'ready_timeout_s' must be non-negative or None")
130+
120131
self._server_options = server_options
121132
self._vad_options = vad_options
122133
self._binary = binary
123134
self._process: subprocess.Popen[str] | None = None
124135
self._base_url = f"http://{server_options.host}:{server_options.port}"
136+
self._ready_timeout = ready_timeout_s
137+
self._ready_interval = ready_check_interval_s
138+
self._ready_probe_timeout = ready_probe_timeout_s
125139
if autostart:
126140
self.start()
127141

@@ -133,7 +147,7 @@ def start(self) -> None:
133147
self._vad_options,
134148
self._binary,
135149
)
136-
self._process = subprocess.Popen(command)
150+
self._process = subprocess.Popen(command) # type:ignore
137151

138152
def __del__(self) -> None:
139153
try:
@@ -170,14 +184,60 @@ def is_running(self) -> bool:
170184
return False
171185
return self._process.poll() is None
172186

187+
def is_ready(self) -> bool:
188+
if not self.is_running():
189+
return False
190+
url = self._get_url("")
191+
try:
192+
response = requests.head(url, timeout=self._ready_probe_timeout)
193+
except requests.RequestException:
194+
return False
195+
if response.status_code < 500:
196+
return True
197+
if response.status_code in (405, 501):
198+
try:
199+
response = requests.get(url, timeout=self._ready_probe_timeout)
200+
except requests.RequestException:
201+
return False
202+
return response.status_code < 500
203+
return False
204+
205+
def _wait_until_ready(
206+
self,
207+
timeout_s: float | None = None,
208+
poll_interval_s: float | None = None,
209+
) -> None:
210+
if poll_interval_s is None:
211+
poll_interval_s = self._ready_interval
212+
if poll_interval_s is None or poll_interval_s <= 0:
213+
raise ValueError("'poll_interval_s' must be positive")
214+
215+
deadline: float | None
216+
if timeout_s is None:
217+
timeout_s = self._ready_timeout
218+
if timeout_s is None:
219+
deadline = None
220+
else:
221+
if timeout_s < 0:
222+
raise ValueError("'timeout_s' must be non-negative or None")
223+
deadline = time.monotonic() + timeout_s
224+
225+
while True:
226+
if self.is_ready():
227+
return
228+
if not self.is_running():
229+
raise RuntimeError("WhisperCPP server process exited before it became ready")
230+
if deadline is not None and time.monotonic() >= deadline:
231+
raise TimeoutError("Timed out waiting for WhisperCPP server to become ready")
232+
time.sleep(poll_interval_s)
233+
173234
def inference(
174235
self,
175236
file: Path,
176237
temperature: float = 0.0,
177238
temperature_inc: float = 0.2,
178239
) -> InferenceJSONVerbose:
179-
if not self.is_running():
180-
raise RuntimeError("WhisperCPP server is not running")
240+
self._wait_until_ready()
181241
url = self._get_url(self._server_options.inference_path)
182242
with file.open("rb") as file_handle:
183243
response = requests.post(
@@ -194,8 +254,7 @@ def inference(
194254
return InferenceJSONVerbose(**response_json)
195255

196256
def load(self, model: Path) -> requests.Response:
197-
if not self.is_running():
198-
raise RuntimeError("WhisperCPP server is not running")
257+
self._wait_until_ready()
199258
url = self._get_url("load")
200259
response = requests.post(
201260
url,

0 commit comments

Comments
 (0)