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:
@@ -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,28 +468,31 @@ class MLFlowRepository:
|
|||||||
|
|
||||||
model_key = f'{model_name}_{model_type}'
|
model_key = f'{model_name}_{model_type}'
|
||||||
|
|
||||||
if model_key in self.model_cache:
|
# Acquire lock to check cache
|
||||||
cache = self.model_cache[model_key]
|
with self._cache_lock:
|
||||||
|
if model_key in self.model_cache:
|
||||||
|
cache = self.model_cache[model_key]
|
||||||
|
|
||||||
# Check if config has changed or is outdated
|
# Check if config has changed or is outdated
|
||||||
if self.check_cache_retention(cache, retention):
|
if self.check_cache_retention(cache, retention):
|
||||||
return self.handle_valid_model(model_name=model_name, cache=cache)
|
return self.handle_valid_model(model_name=model_name, cache=cache)
|
||||||
|
else:
|
||||||
|
# Model is outdated, delete old model files
|
||||||
|
self.handle_outdated_model(model_name=model_name, model_key=model_key)
|
||||||
else:
|
else:
|
||||||
# Model is outdated, delete old model files
|
self.logger.debug(
|
||||||
self.handle_outdated_model(model_name=model_name, model_key=model_key)
|
f'Model {model_name} is not in {model_type} cache, downloading a new one'
|
||||||
else:
|
)
|
||||||
self.logger.debug(
|
|
||||||
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
|
||||||
)
|
)
|
||||||
|
|
||||||
cache = {'target': model, 'timestamp': datetime.now()}
|
# Update cache with lock
|
||||||
|
with self._cache_lock:
|
||||||
self.model_cache[model_key] = cache
|
cache = {'target': model, 'timestamp': datetime.now()}
|
||||||
|
self.model_cache[model_key] = cache
|
||||||
|
|
||||||
return model
|
return model
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user