SIENTIAPDE-1314

Enhance thread safety in MLFlowRepository model caching

- Introduced a reentrant lock to synchronize access to the model cache, ensuring thread safety during cache checks and updates.
- Updated the cache management logic to acquire the lock when checking for existing models and when updating the cache after downloading a new model.
- Reduced the maximum cached workflows in the worker configuration for improved resource management.
This commit is contained in:
vitor-aignosi
2025-10-27 13:29:01 -03:00
parent 1cbf356d0c
commit 67af03ee94
2 changed files with 21 additions and 17 deletions

View File

@@ -16,6 +16,7 @@ Capabilities:
import ctypes import ctypes
import gc import gc
import threading
import traceback import traceback
from datetime import datetime, timedelta from datetime import datetime, timedelta
from os import environ, makedirs, path from os import environ, makedirs, path
@@ -74,6 +75,7 @@ class MLFlowRepository:
self.client = mlflow.tracking.MlflowClient() self.client = mlflow.tracking.MlflowClient()
self.model_cache: dict[str, Any] = {} self.model_cache: dict[str, Any] = {}
self._cache_lock = threading.RLock()
self.logger = logger self.logger = logger
""" """
@@ -466,6 +468,8 @@ class MLFlowRepository:
model_key = f'{model_name}_{model_type}' model_key = f'{model_name}_{model_type}'
# Acquire lock to check cache
with self._cache_lock:
if model_key in self.model_cache: if model_key in self.model_cache:
cache = self.model_cache[model_key] cache = self.model_cache[model_key]
@@ -480,13 +484,14 @@ class MLFlowRepository:
f'Model {model_name} is not in {model_type} cache, downloading a new one' f'Model {model_name} is not in {model_type} cache, downloading a new one'
) )
# Donwload new model # Donwload new model (without lock to avoid blocking other threads)
model, _artifact_path = self.download_model( model, _artifact_path = self.download_model(
model_name=model_name, model_type=model_type, flavor=flavor, load_wrapper=False model_name=model_name, model_type=model_type, flavor=flavor, load_wrapper=False
) )
# Update cache with lock
with self._cache_lock:
cache = {'target': model, 'timestamp': datetime.now()} cache = {'target': model, 'timestamp': datetime.now()}
self.model_cache[model_key] = cache self.model_cache[model_key] = cache
return model return model

View File

@@ -152,7 +152,7 @@ async def main():
max_concurrent_workflow_tasks=50, max_concurrent_workflow_tasks=50,
max_concurrent_activities=50, max_concurrent_activities=50,
max_concurrent_local_activities=50, max_concurrent_local_activities=50,
max_cached_workflows=200, max_cached_workflows=2,
workflow_task_poller_behavior=PollerBehaviorAutoscaling(), workflow_task_poller_behavior=PollerBehaviorAutoscaling(),
activity_task_poller_behavior=PollerBehaviorAutoscaling(), activity_task_poller_behavior=PollerBehaviorAutoscaling(),
), ),
@@ -164,7 +164,6 @@ async def main():
# MLFlow # MLFlow
activities.request_predict, activities.request_predict,
activities.request_transform, activities.request_transform,
activities.query_to_minio,
# Gates # Gates
activities.input_gate, activities.input_gate,
activities.mlflow_response_gate, activities.mlflow_response_gate,