ucam-department-of-psychiatry / crate

Create and use de-identified research databases. Preprocess, extract text, anonymise/de-identify, link, apply natural language processing, query for research, manage consent for contact.
GNU General Public License v3.0
19 stars 7 forks source link

Possible race condition on Django startup #132

Open RudolfCardinal opened 9 months ago

RudolfCardinal commented 9 months ago

Doesn't always happen, but it looks like the global research_database_info = ResearchDatabaseInfo() in research_db_info.py is flawed because it's global:

2023-10-08 14:32:15.366 [p3176044.t140577329673792] crate_anon.crateweb.research.research_db_info:INFO: Fetching/caching database structure (for database '', schema 'anonymous_output')...
2023-10-08 14:32:15.377 [p3176044.t140577795391488] crate_anon.crateweb.research.research_db_info:INFO: Fetching/caching database structure (for database '', schema 'anonymous_output')...
Exception in thread django-main-thread:
Traceback (most recent call last):
  File "/usr/lib/python3.10/threading.py", line 1016, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.10/threading.py", line 953, in run
    self._target(*self._args, **self._kwargs)
  File "/home/rudolf/dev/venvs/crate/lib/python3.10/site-packages/django/utils/autoreload.py", line 64, in wrapper
    fn(*args, **kwargs)
  File "/home/rudolf/dev/venvs/crate/lib/python3.10/site-packages/django/core/management/commands/runserver.py", line 118, in inner_run
    self.check(display_num_errors=True)
  File "/home/rudolf/dev/venvs/crate/lib/python3.10/site-packages/django/core/management/base.py", line 419, in check
    all_issues = checks.run_checks(
  File "/home/rudolf/dev/venvs/crate/lib/python3.10/site-packages/django/core/checks/registry.py", line 76, in run_checks
    new_errors = check(app_configs=app_configs, databases=databases)
  File "/home/rudolf/dev/venvs/crate/lib/python3.10/site-packages/django/core/checks/urls.py", line 40, in check_url_namespaces_unique
    all_namespaces = _load_all_namespaces(resolver)
  File "/home/rudolf/dev/venvs/crate/lib/python3.10/site-packages/django/core/checks/urls.py", line 57, in _load_all_namespaces
    url_patterns = getattr(resolver, 'url_patterns', [])
  File "/home/rudolf/dev/venvs/crate/lib/python3.10/site-packages/django/utils/functional.py", line 48, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/home/rudolf/dev/venvs/crate/lib/python3.10/site-packages/django/urls/resolvers.py", line 602, in url_patterns
    patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
  File "/home/rudolf/dev/venvs/crate/lib/python3.10/site-packages/django/utils/functional.py", line 48, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/home/rudolf/dev/venvs/crate/lib/python3.10/site-packages/django/urls/resolvers.py", line 595, in urlconf_module
    return import_module(self.urlconf_name)
  File "/usr/lib/python3.10/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 883, in exec_module
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "/home/rudolf/Documents/code/crate/crate_anon/crateweb/config/urls.py", line 87, in <module>
    research_database_info.get_colinfolist()
  File "/home/rudolf/dev/venvs/crate/lib/python3.10/site-packages/cardinal_pythonlib/django/function_cache.py", line 176, in wrapper
    func_result = fn(*args, **kwargs)
  File "/home/rudolf/Documents/code/crate/crate_anon/crateweb/research/research_db_info.py", line 1370, in get_colinfolist
    colinfolist.extend(dbi.colinfolist)
  File "/home/rudolf/Documents/code/crate/crate_anon/crateweb/research/research_db_info.py", line 419, in colinfolist
    ColumnInfo(**d) for d in self.schema_infodictlist
  File "/home/rudolf/Documents/code/crate/crate_anon/crateweb/research/research_db_info.py", line 406, in schema_infodictlist
    self._schema_infodictlist = self.get_schema_infodictlist(
  File "/home/rudolf/Documents/code/crate/crate_anon/crateweb/research/research_db_info.py", line 918, in get_schema_infodictlist
    cursor = connection.cursor()
  File "/home/rudolf/dev/venvs/crate/lib/python3.10/site-packages/django/utils/asyncio.py", line 33, in inner
    return func(*args, **kwargs)
  File "/home/rudolf/dev/venvs/crate/lib/python3.10/site-packages/django/db/backends/base/base.py", line 259, in cursor
    return self._cursor()
  File "/home/rudolf/dev/venvs/crate/lib/python3.10/site-packages/django/db/backends/base/base.py", line 235, in _cursor
    self.ensure_connection()
  File "/home/rudolf/dev/venvs/crate/lib/python3.10/site-packages/django/utils/asyncio.py", line 33, in inner
    return func(*args, **kwargs)
  File "/home/rudolf/dev/venvs/crate/lib/python3.10/site-packages/django/db/backends/base/base.py", line 219, in ensure_connection
    self.connect()
  File "/home/rudolf/dev/venvs/crate/lib/python3.10/site-packages/django/utils/asyncio.py", line 33, in inner
    return func(*args, **kwargs)
  File "/home/rudolf/dev/venvs/crate/lib/python3.10/site-packages/django/db/backends/base/base.py", line 202, in connect
    self.init_connection_state()
  File "/home/rudolf/dev/venvs/crate/lib/python3.10/site-packages/django/db/backends/mysql/base.py", line 245, in init_connection_state
    if self.features.is_sql_auto_is_null_enabled:
  File "/home/rudolf/dev/venvs/crate/lib/python3.10/site-packages/django/utils/functional.py", line 48, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/home/rudolf/dev/venvs/crate/lib/python3.10/site-packages/django/db/backends/mysql/features.py", line 163, in is_sql_auto_is_null_enabled
    return self.connection.mysql_server_data['sql_auto_is_null']
  File "/home/rudolf/dev/venvs/crate/lib/python3.10/site-packages/django/utils/functional.py", line 48, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/home/rudolf/dev/venvs/crate/lib/python3.10/site-packages/django/db/backends/mysql/base.py", line 366, in mysql_server_data
    with self.temporary_connection() as cursor:
  File "/usr/lib/python3.10/contextlib.py", line 135, in __enter__
    return next(self.gen)
  File "/home/rudolf/dev/venvs/crate/lib/python3.10/site-packages/django/db/backends/base/base.py", line 603, in temporary_connection
    with self.cursor() as cursor:
  File "/home/rudolf/dev/venvs/crate/lib/python3.10/site-packages/django/utils/asyncio.py", line 33, in inner
    return func(*args, **kwargs)
  File "/home/rudolf/dev/venvs/crate/lib/python3.10/site-packages/django/db/backends/base/base.py", line 259, in cursor
    return self._cursor()
  File "/home/rudolf/dev/venvs/crate/lib/python3.10/site-packages/django/db/backends/base/base.py", line 237, in _cursor
    return self._prepare_cursor(self.create_cursor(name))
  File "/home/rudolf/dev/venvs/crate/lib/python3.10/site-packages/django/db/backends/base/base.py", line 227, in _prepare_cursor
    self.validate_thread_sharing()
  File "/home/rudolf/dev/venvs/crate/lib/python3.10/site-packages/django/db/backends/base/base.py", line 552, in validate_thread_sharing
    raise DatabaseError(
django.db.utils.DatabaseError: DatabaseWrapper objects created in a thread can only be used in that same thread. The object with alias 'research' was created in thread id 140577795391488 and this is thread id 140577329673792.