Improvements to the matrix cache (#1340)

* Improvements to the matrix cache

- Add a timelimit for the matrix in the cache.
Once the timelimit is reached, the matrix can be removed.

- If a DatasetAccessError occurs, then remove the dataset
from the matrix cache.

Fixes #1322
This commit is contained in:
bmccandless
2020-04-02 13:44:11 -07:00
committed by GitHub
parent fa0164fdf6
commit 308ee64f30
9 changed files with 260 additions and 61 deletions
+19 -8
View File
@@ -72,6 +72,7 @@ class AppConfig(object):
self.multi_dataset__index = dc["multi_dataset"]["index"]
self.multi_dataset__allowed_matrix_types = dc["multi_dataset"]["allowed_matrix_types"]
self.multi_dataset__matrix_cache__max_datasets = dc["multi_dataset"]["matrix_cache"]["max_datasets"]
self.multi_dataset__matrix_cache__timelimit_s = dc["multi_dataset"]["matrix_cache"]["timelimit_s"]
self.single_dataset__datapath = dc["single_dataset"]["datapath"]
self.single_dataset__obs_names = dc["single_dataset"]["obs_names"]
@@ -108,6 +109,9 @@ class AppConfig(object):
# The annotation object is created during complete_config and stored here.
self.user_annotations = None
# The matrix data cache manager is created during the complete_config and stored here.
self.matrix_data_cache_manager = None
# Set to true when config_completed is called
self.is_completed = False
@@ -146,12 +150,10 @@ class AppConfig(object):
self.is_completed = False
def complete_config(self, matrix_data_cache_manager=None, messagefn=None):
def complete_config(self, messagefn=None):
"""The configure options are checked, and any additional setup based on the config
parameters is done"""
if matrix_data_cache_manager is None:
matrix_data_cache_manager = MatrixDataCacheManager()
if messagefn is None:
def noop(message):
@@ -162,7 +164,7 @@ class AppConfig(object):
# TODO: to give better error messages we can add a mapping between where each config
# attribute originated (e.g. command line argument or config file), then in the error
# messages we can give correct context for attributes with bad value.
context = dict(matrix_cache=matrix_data_cache_manager, messagefn=messagefn)
context = dict(messagefn=messagefn)
self.handle_server(context)
self.handle_single_dataset(context)
@@ -242,6 +244,10 @@ class AppConfig(object):
if self.multi_dataset__dataroot is not None:
raise ConfigurationError("must supply only one of datapath or dataroot")
# create the matrix data cache manager:
if self.matrix_data_cache_manager is None:
self.matrix_data_cache_manager = MatrixDataCacheManager(max_cached=1, timelimit_s=None)
# preload this data set
matrix_data_loader = MatrixDataLoader(self.single_dataset__datapath)
try:
@@ -278,6 +284,7 @@ class AppConfig(object):
self.__check_attr("multi_dataset__index", (type(None), bool, str))
self.__check_attr("multi_dataset__allowed_matrix_types", (tuple, list))
self.__check_attr("multi_dataset__matrix_cache__max_datasets", int)
self.__check_attr("multi_dataset__matrix_cache__timelimit_s", (type(None), int, float))
if self.multi_dataset__dataroot is None:
return
@@ -289,8 +296,12 @@ class AppConfig(object):
except ValueError:
raise ConfigurationError(f'Invalid matrix type in "allowed_matrix_types": {mtype}')
# matrix cache
MatrixDataCacheManager.set_max_datasets(self.multi_dataset__matrix_cache__max_datasets)
# create the matrix data cache manager:
if self.matrix_data_cache_manager is None:
self.matrix_data_cache_manager = MatrixDataCacheManager(
max_cached=self.multi_dataset__matrix_cache__max_datasets,
timelimit_s=self.multi_dataset__matrix_cache__timelimit_s,
)
def handle_user_annotations(self, context):
self.__check_attr("user_annotations__enable", bool)
@@ -328,7 +339,7 @@ class AppConfig(object):
# if the user has specified a fixed label file, go ahead and validate it
# so that we can remove errors early in the process.
if self.single_dataset__datapath and self.user_annotations__local_file_csv__file:
with context["matrix_cache"].data_adaptor(self.single_dataset__datapath, self) as data_adaptor:
with self.matrix_data_cache_manager.data_adaptor(self.single_dataset__datapath, self) as data_adaptor:
data_adaptor.check_new_labels(self.user_annotations.read_labels(data_adaptor))
if self.user_annotations__ontology__enable or self.user_annotations__ontology__obo_location:
@@ -372,7 +383,7 @@ class AppConfig(object):
self.__check_attr("diffexp__lfc_cutoff", float)
if self.single_dataset__datapath:
with context["matrix_cache"].data_adaptor(self.single_dataset__datapath, self) as data_adaptor:
with self.matrix_data_cache_manager.data_adaptor(self.single_dataset__datapath, self) as data_adaptor:
if self.diffexp__enable and data_adaptor.parameters.get("diffexp_may_be_slow", False):
context["messagefn"](
f"CAUTION: due to the size of your dataset, "
+4
View File
@@ -36,6 +36,10 @@ multi_dataset:
# is evicted from the cache first.
max_datasets: 5
# A matrix is automatically removed from the cache after timelimit_s number of seconds.
# If timelimit_s is set to None, then there is no time limit.
timelimit_s: 30
single_dataset:
datapath: null
obs_names: null