Keep TTS and STT workers resident between requests

This commit is contained in:
Mikei386
2026-09-29 20:37:29 +02:00
parent 3dcf2d3f76
commit 90a97567f3
11 changed files with 197 additions and 80 deletions
+20 -7
View File
@@ -19,9 +19,9 @@ class InferenceError(ValueError):
class Scheduler:
"""FIFO admission; same-profile requests share configured slots, switches drain."""
def __init__(self, worker):
self.worker=worker;self.cv=threading.Condition();self.queue=[];self.key=None;self.active=0;self.transition=False;self.gpu_mode="llm"
self.worker=worker;self.evict_tts=lambda:None;self.cv=threading.Condition();self.queue=[];self.key=None;self.active=0;self.tts_active=0;self.transition=False;self.gpu_mode="llm"
def status(self):
with self.cv:return dict(active_requests=self.active,waiting_requests=len(self.queue),switching=self.transition)
with self.cv:return dict(active_requests=self.active+self.tts_active,waiting_requests=len(self.queue),switching=self.transition)
@contextlib.contextmanager
def lease(self, key, slots=1, prepare=None, timeout=600, allowed=lambda:True):
ticket=object();deadline=time.monotonic()+timeout;claimed=False
@@ -32,7 +32,7 @@ class Scheduler:
while True:
if self.gpu_mode!="llm":raise InferenceError("Video-Modus aktiv oder Moduswechsel läuft; GPU-Aufträge sind gesperrt.")
if not allowed():raise InferenceError('Endpunkt wird gestoppt oder Profil ist nicht mehr aktiviert.')
if self.queue[0] is ticket and not self.transition and (not self.active or (self.key==key and self.active<slots)):
if self.queue[0] is ticket and not self.transition and (not self.active or (self.key==key and self.active<slots)) and (not self.tts_active or self.key==key and key!=('image',)):
self.queue.pop(0);self.active+=1;claimed=True
switch=self.key!=key;self.key=key
# Also verifies/restarts a crashed worker when there are no other leases.
@@ -47,6 +47,7 @@ class Scheduler:
if self.transition:
try:
if switch:self.worker.stop()
if key==('image',) or switch:self.evict_tts()
if prepare:prepare()
except Exception:
self.worker.stop()
@@ -58,15 +59,27 @@ class Scheduler:
finally:
if claimed:
with self.cv:self.active-=1;self.cv.notify_all()
def image_reservation(self, wait=False):
lease=self.lease(('image',),timeout=600 if wait else 0)
def image_reservation(self, wait=False,kind='image'):
lease=self.lease((kind,),timeout=600 if wait else 0)
lease.__enter__()
return lambda:lease.__exit__(None,None,None)
def tts_reservation(self,wait=False):
deadline=time.monotonic()+(600 if wait else 0)
with self.cv:
while True:
if self.gpu_mode!='llm':raise InferenceError('Video-Modus aktiv; TTS ist nicht verfügbar.')
if not self.transition and not (self.key==('image',) and self.active) and not self.queue:
self.tts_active+=1;break
if time.monotonic()>=deadline:raise InferenceError('GPU-Auftrag läuft; TTS später erneut versuchen.')
self.cv.wait(min(1,max(.01,deadline-time.monotonic())))
def release():
with self.cv:self.tts_active-=1;self.cv.notify_all()
return release
def unload_idle(self):
with self.cv:
if self.active:return False
if self.active or self.tts_active:return False
self.transition=True
try:self.worker.stop();self.key=None
try:self.worker.stop();self.evict_tts();self.key=None
finally:self.transition=False;self.cv.notify_all()
return True