1+ import logging
12from typing import List , Dict , Optional , Any
23
4+ from llm_router_api .base .constants import REDIS_HOST , REDIS_PORT
35from llm_router_api .core .lb .strategies .first_available import FirstAvailableStrategy
46
57
@@ -24,10 +26,34 @@ class FirstAvailableOptimStrategy(FirstAvailableStrategy):
2426 used host for the model and update the bookkeeping structures.
2527 """
2628
29+ def __init__ (
30+ self ,
31+ models_config_path : str ,
32+ redis_host : str = REDIS_HOST ,
33+ redis_port : int = REDIS_PORT ,
34+ redis_db : int = 0 ,
35+ timeout : int = 60 ,
36+ check_interval : float = 0.1 ,
37+ clear_buffers : bool = True ,
38+ logger : Optional [logging .Logger ] = None ,
39+ ) -> None :
40+ super ().__init__ (
41+ models_config_path = models_config_path ,
42+ redis_host = redis_host ,
43+ redis_port = redis_port ,
44+ redis_db = redis_db ,
45+ timeout = timeout ,
46+ check_interval = check_interval ,
47+ clear_buffers = clear_buffers ,
48+ logger = logger ,
49+ strategy_prefix = "fa_optim_" ,
50+ )
51+ if clear_buffers :
52+ self ._clear_buffer ()
53+
2754 # -------------------------------------------------------------------------
2855 # Helper utilities
2956 # -------------------------------------------------------------------------
30-
3157 def _host_from_provider (self , provider : Dict ) -> Optional [str ]:
3258 """Extract the host identifier from a provider configuration."""
3359 # Most providers expose the host under ``api_host`` or ``host``.
@@ -189,6 +215,30 @@ def _record_selection(self, model_name: str, provider: Dict) -> None:
189215 occ_key = self ._host_occupancy_key (host )
190216 self .redis_client .hset (occ_key , "model" , model_name )
191217
218+ # -------------------------------------------------------
219+ # Ensure buffers are cleared on construction (delegated to parent)
220+ # -------------------------------------------------------
221+
222+ def _clear_buffer (self ) -> None :
223+ """
224+ Remove all Redis keys that are used by this optimisation strategy.
225+ The keys have the following suffixes:
226+
227+ * ``:last_host`` – stores the last host used for a model.
228+ * ``:hosts`` – set of hosts where a model is loaded.
229+ * ``:occupancy`` – hash that records which model currently occupies a host.
230+
231+ The method scans Redis for keys ending with any of these suffixes and
232+ deletes them. It is safe to run on start‑up because the strategy will
233+ recreate the necessary keys on the first request.
234+ """
235+ suffixes = (":last_host" , ":hosts" , ":occupancy" )
236+ for suffix in suffixes :
237+ # ``scan_iter`` yields matching keys without loading them all into memory.
238+ for key in self .redis_client .scan_iter (match = f"*{ suffix } " ):
239+ self .logger .debug (f"Removing { self } => { key } from redis" )
240+ self .redis_client .delete (key )
241+
192242 # -------------------------------------------------------------------------
193243 # Overridden public API
194244 # -------------------------------------------------------------------------
@@ -254,12 +304,3 @@ def get_provider(
254304 if provider :
255305 self ._record_selection (model_name , provider )
256306 return provider
257-
258- # -------------------------------------------------------------------------
259- # Ensure buffers are cleared on construction (delegated to parent)
260- # -------------------------------------------------------------------------
261-
262- def __init__ (self , * args , ** kwargs ):
263- super ().__init__ (* args , ** kwargs )
264- # Parent already calls ``_clear_buffers`` when ``clear_buffers=True``.
265- # No additional initialisation required here.
0 commit comments