Skip to content

Commit

Permalink
130 model results loading improvements
Browse files Browse the repository at this point in the history
130 model results loading improvements
  • Loading branch information
upnico9 committed Sep 7, 2023
2 parents 494e084 + bdfa2ed commit 6f22970
Show file tree
Hide file tree
Showing 14 changed files with 324 additions and 49 deletions.
7 changes: 5 additions & 2 deletions backend/config/config.env
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,12 @@ DEBIAI_DATA_PROVIDERS_DELETION_ENABLED=True
; Python module data provider configuration
DEBIAI_PYTHON_MODULE_DATA_PROVIDER_ENABLED=True

; Web data provider configuration
DEBIAI_WEB_DATA_PROVIDERS_CACHE_ENABLED=True
DEBIAI_WEB_DATA_PROVIDERS_CACHE_DURATION=120

; Web data provider list
; Env vaAr format: DEBIAI_WEB_DATA_PROVIDER_<name>=<url>
; Env var format: DEBIAI_WEB_DATA_PROVIDER_<name>=<url>, '_' are forbidden in <name>
DEBIAI_WEB_DATA_PROVIDER_my-web-provider1=http://localhost:3010/debiai
DEBIAI_WEB_DATA_PROVIDER_my-web-provider2=http://localhost:3011/

Expand All @@ -24,7 +28,6 @@ DEBIAI_ALGO_PROVIDERS_DELETION_ENABLED=True
DEBIAI_ALGO_PROVIDER_my-algo-provider1=http://localhost:3020/
DEBIAI_ALGO_PROVIDER_my-algo-provider2=http://localhost:3021/algo_provider


; ==== Export method ====
; Export methods configuration
DEBIAI_EXPORT_METHODS_CREATION_ENABLED=True
Expand Down
6 changes: 6 additions & 0 deletions backend/config/config.ini
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ creation = true
# (true/false), default is true
deletion = true

# Configure the Web data provider cache
# Enable or disable the cache
web_data_provider_cache = true
# Configure the cache duration in seconds
web_data_provider_cache_duration = 120

[PYTHON_MODULE_DATA_PROVIDER]
# Options for the integrated Python module data provider
# Enable or disable the module data provider
Expand Down
49 changes: 47 additions & 2 deletions backend/config/init_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,12 @@ def init_config():

# Default config
config = {
"DATA_PROVIDERS_CONFIG": {"creation": True, "deletion": True},
"DATA_PROVIDERS_CONFIG": {
"creation": True,
"deletion": True,
"web_data_provider_cache": True,
"web_data_provider_cache_duration": 120,
},
"PYTHON_MODULE_DATA_PROVIDER": {"enabled": True},
"WEB_DATA_PROVIDERS": {},
"ALGO_PROVIDERS_CONFIG": {
Expand All @@ -39,7 +44,7 @@ def init_config():
config_parser.read(config_path)

for section in config_parser.sections():
# Data providers
# Data providers config
if section == "DATA_PROVIDERS_CONFIG":
if "creation" in config_parser[section]:
if str.lower(config_parser[section]["creation"]) == "false":
Expand All @@ -50,6 +55,26 @@ def init_config():
if str.lower(config_parser[section]["deletion"]) == "false":
print("Config file: Data Providers deletion disabled")
config["DATA_PROVIDERS_CONFIG"]["deletion"] = False

if "web_data_provider_cache" in config_parser[section]:
if (
str.lower(config_parser[section]["web_data_provider_cache"])
== "false"
):
print("Config file: Web Data Provider cache disabled")
config["DATA_PROVIDERS_CONFIG"]["web_data_provider_cache"] = False

if "web_data_provider_cache_duration" in config_parser[section]:
try:
config["DATA_PROVIDERS_CONFIG"][
"web_data_provider_cache_duration"
] = int(config_parser[section]["web_data_provider_cache_duration"])
except ValueError:
print(
"Config file: Invalid Web Data Provider cache duration,",
"defaulting to 120 seconds",
)

continue

if section == "PYTHON_MODULE_DATA_PROVIDER":
Expand Down Expand Up @@ -160,6 +185,26 @@ def init_config():
continue

# Deal with Data Providers in env variables
if env_var == "DEBIAI_WEB_DATA_PROVIDERS_CACHE_ENABLED":
# Env var format: DEBIAI_WEB_DATA_PROVIDERS_CACHE_ENABLED=<True|False>
if str.lower(os.environ[env_var]) == "false":
print("Environment variables: Web Data Provider cache disabled")
config["DATA_PROVIDERS_CONFIG"]["web_data_provider_cache"] = False
continue

if env_var == "DEBIAI_WEB_DATA_PROVIDERS_CACHE_DURATION":
# Env var format: DEBIAI_WEB_DATA_PROVIDERS_CACHE_DURATION=<duration>
try:
config["DATA_PROVIDERS_CONFIG"][
"web_data_provider_cache_duration"
] = int(os.environ[env_var])
except ValueError:
print(
"Environment variables: Invalid Web Data Provider cache duration,",
"defaulting to 120 seconds",
)
continue

if "DEBIAI_WEB_DATA_PROVIDER" in env_var:
# Env var format: DEBIAI_WEB_DATA_PROVIDER_<name>=<url>
if len(env_var.split("_")) != 5:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ def get_info(self):
# Projects
def get_projects(self):
# Request method to get projects overview
# Return Arr[object{ id, name, nb_samples, nb_models, nb_selections, update_time, creation_time}]
# Return Arr[object{ id, name, nb_samples, nb_models, nb_selections,
# update_time, creation_time}]
return projects.get_projects()

def create_project(self, name):
Expand All @@ -83,7 +84,8 @@ def create_project(self, name):
@project_must_exist
def get_project(self, project_id):
# Request method to get projects overview
# Return object{ id, name, nb_samples, nb_models, nb_selections, update_time, creation_time}
# Return object{ id, name, nb_samples, nb_models, nb_selections,
# update_time, creation_time}

project_base_info = projects.get_project(project_id)
project_base_info["selections"] = selections.get_selections(project_id)
Expand Down
27 changes: 15 additions & 12 deletions backend/modules/dataProviders/webDataProvider/WebDataProvider.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,19 @@
)
import modules.dataProviders.webDataProvider.useCases.selections as useCaseSelections
from modules.dataProviders.webDataProvider.http.api import get_info, get_status
from modules.dataProviders.webDataProvider.cache.cache import Cache

from modules.dataProviders.DataProviderException import DataProviderException


#
# Class role is supposed to expose methods for every data Providers
#
#
# WebDataProvider class, allow to get data from a web data-provider
class WebDataProvider(DataProvider):
def __init__(self, url, name):
self.url = url
self._name = name
self.alive = None

# Init cache
self.cache = Cache()

@property
def name(self):
return self._name
Expand All @@ -38,7 +37,7 @@ def name(self):
def type(self):
return "Web"

## Todo api call Info (new info)
# Todo api call Info (new info)
def is_alive(self):
self.alive = True if get_status(self.url) is True else False
return self.alive
Expand All @@ -49,12 +48,14 @@ def get_info(self):
# ==== Projects ====
def get_projects(self):
# Request method to get projects overview
# Return Arr[object{ id, name, nb_samples, nb_models, nb_selections, update_time, creation_time}]
# Return Arr[object{ id, name, nb_samples, nb_models, nb_selections,
# update_time, creation_time}]
return get_all_projects_from_data_provider(self.url, self.name)

def get_project(self, id_project):
# Request method to get projects overview
# Return object{ id, name, nb_samples, nb_models, nb_selections, update_time, creation_time}
# Return object{ id, name, nb_samples, nb_models, nb_selections,
# update_time, creation_time}
return get_single_project_from_data_provider(self.url, self.name, id_project)

def delete_project(self, project_id):
Expand All @@ -63,7 +64,9 @@ def delete_project(self, project_id):
def get_id_list(self, project_id, analysis, _from=None, _to=None):
# http Request on dp to get id list
# Return Arr[id]
return get_project_id_list(self.url, project_id, analysis, _from, _to)
return get_project_id_list(
self.url, self.cache, project_id, analysis, _from, _to
)

def get_samples(self, project_id, analysis, id_list):
# http Request get full sample
Expand All @@ -78,7 +81,7 @@ def get_selections(self, project_id):

def get_selection_id_list(self, project_id, selection_id):
return useCaseSelections.get_id_list_from_selection(
self.url, project_id, selection_id
self.url, self.cache, project_id, selection_id
)

def create_selection(self, project_id, name, id_list, request_id=None):
Expand All @@ -94,7 +97,7 @@ def get_models(self, project_id):
return get_models_info(self.url, project_id)

def get_model_results_id_list(self, project_id, model_id):
return get_model_result_id(self.url, project_id, model_id)
return get_model_result_id(self.url, self.cache, project_id, model_id)

def get_model_results(self, project_id, model_id, sample_list):
return get_model_results(self.url, project_id, model_id, sample_list)
Expand Down
184 changes: 184 additions & 0 deletions backend/modules/dataProviders/webDataProvider/cache/cache.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
# This service is used to cache data from the web data provider
# It's used to avoid multiple requests to the web data provider
# It will mainly save the id list of samples, selections and models results
# The ability to cache and the time to live are configurable in the config file

import time
from config.init_config import get_config


class Cache:
def __init__(self):
self.cache = {
"project_id_list": {
# <id_project>: {
# <from>_<to>: {
# id_list: [...],
# timestamp: <timestamp>
# },
# total: {
# id_list: [...],
# timestamp: <timestamp>
# }
# }
},
"selection_id_list": {
# <id_project>: {
# <id_selection>: {
# id_list: [...],
# timestamp: <timestamp>
# }
# }
},
"model_result_id_list": {
# <id_project>: {
# <id_model>: {
# id_list: [...],
# timestamp: <timestamp>
# }
# }
},
}
self.config = get_config()

self.cache_enabled = self.config["DATA_PROVIDERS_CONFIG"][
"web_data_provider_cache"
]
self.cache_ttl = self.config["DATA_PROVIDERS_CONFIG"][
"web_data_provider_cache_duration"
]

# Project id list
def get_id_list(self, id_project, _from=None, _to=None):
if not self.cache_enabled:
return None

if id_project not in self.cache["project_id_list"]:
return None

project_cache = self.cache["project_id_list"][id_project]

if _from is None or _to is None:
if "total" not in project_cache:
return None

# Check if cache is still valid
timestamp = project_cache["total"]["timestamp"]
if time.time() - timestamp > self.cache_ttl:
# Cache is not valid anymore
# Delete cache
del project_cache["total"]
return None

return project_cache["total"]["id_list"]

else:
key = "{}_{}".format(_from, _to)
if key not in project_cache:
return None

# Check if cache is still valid
timestamp = project_cache[key]["timestamp"]
if time.time() - timestamp > self.cache_ttl:
# Cache is not valid anymore
# Delete cache
del project_cache[key]
return None

return project_cache[key]["id_list"]

def set_id_list(self, id_project, id_list, _from=None, _to=None):
if not self.cache_enabled:
return

if id_project not in self.cache["project_id_list"]:
self.cache["project_id_list"][id_project] = {}

project_cache = self.cache["project_id_list"][id_project]

if _from is None or _to is None:
project_cache["total"] = {
"id_list": id_list,
"timestamp": time.time(),
}
else:
key = "{}_{}".format(_from, _to)
project_cache[key] = {
"id_list": id_list,
"timestamp": time.time(),
}

# Selection id list
def get_selection_id_list(self, id_project, id_selection):
if not self.cache_enabled:
return None

if id_project not in self.cache["selection_id_list"]:
return None

project_cache = self.cache["selection_id_list"][id_project]

if id_selection not in project_cache:
return None

# Check if cache is still valid
timestamp = project_cache[id_selection]["timestamp"]

if time.time() - timestamp > self.cache_ttl:
# Cache is not valid anymore
# Delete cache
del project_cache[id_selection]
return None

return project_cache[id_selection]["id_list"]

def set_selection_id_list(self, id_project, id_selection, id_list):
if not self.cache_enabled:
return

if id_project not in self.cache["selection_id_list"]:
self.cache["selection_id_list"][id_project] = {}

project_cache = self.cache["selection_id_list"][id_project]

project_cache[id_selection] = {
"id_list": id_list,
"timestamp": time.time(),
}

# Model result id list
def get_model_result_id_list(self, id_project, id_model):
if not self.cache_enabled:
return None

if id_project not in self.cache["model_result_id_list"]:
return None

project_cache = self.cache["model_result_id_list"][id_project]

if id_model not in project_cache:
return None

# Check if cache is still valid
timestamp = project_cache[id_model]["timestamp"]
if time.time() - timestamp > self.cache_ttl:
# Cache is not valid anymore
# Delete cache
del project_cache[id_model]
return None

return project_cache[id_model]["id_list"]

def set_model_result_id_list(self, id_project, id_model, id_list):
if not self.cache_enabled:
return

if id_project not in self.cache["model_result_id_list"]:
self.cache["model_result_id_list"][id_project] = {}

project_cache = self.cache["model_result_id_list"][id_project]

project_cache[id_model] = {
"id_list": id_list,
"timestamp": time.time(),
}
Loading

0 comments on commit 6f22970

Please sign in to comment.