As for having the LMS actually use blockstore libraries, I’m not familiar with how edx.org deploys blockstore, or even if they use edx-configuration for it.
It looks to me like the blockstore role in edx-configuration is currently borked in a subtle way:
blockstore
inherits from the edx_django_service
role via a meta dependency, and in its dependency declaration it sets a bunch of variables for that service.
- One of those variables is
edx_django_service_default_db_conn_max_age
, which it sets as follows:
edx_django_service_default_db_conn_max_age: '{{ BLOCKSTORE_DATABASE_CONN_MAX_AGE }}'
For comparison, see also:
edx_django_service_default_db_atomic_requests: true
Note how the former value is quoted, which it must be, due to a quirk in the YAML parser that Ansible uses. The latter is not.
When edx_django_service
(which itself depends on edx_service
) creates the edx_service_config
dictionary and then renders the blockstore.yml
file using the | to_nice_yaml
filter in edx_service/templates/config.yml.j2
, it apparently treats the quoted value as a string, whereas the unquoted value is correctly interpreted as a boolean. And what you end up getting in blockstore.yml
is:
DATABASES:
default:
ATOMIC_REQUESTS: true
CONN_MAX_AGE: '60'
Unfortunately Django doesn’t accept a string for CONN_MAX_AGE
. Any API requests to a thus-configured blockstore end up in an HTTP 500, with this exception in the blockstore-stdout.log
:
2020-07-07 12:05:05,673 ERROR 1564 [django.request] exception.py:135 - Internal Server Error: /api/v1/
Traceback (most recent call last):
File "/edx/app/blockstore/venvs/blockstore/lib/python3.5/site-packages/django/core/handlers/exception.py", line 41, in inner
response = get_response(request)
File "/edx/app/blockstore/venvs/blockstore/lib/python3.5/site-packages/django/core/handlers/base.py", line 187, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/edx/app/blockstore/venvs/blockstore/lib/python3.5/site-packages/django/core/handlers/base.py", line 185, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/usr/lib/python3.5/contextlib.py", line 29, in inner
with self._recreate_cm():
File "/edx/app/blockstore/venvs/blockstore/lib/python3.5/site-packages/django/db/transaction.py", line 158, in __enter__
if not connection.get_autocommit():
File "/edx/app/blockstore/venvs/blockstore/lib/python3.5/site-packages/django/db/backends/base/base.py", line 385, in get_autocommit
self.ensure_connection()
File "/edx/app/blockstore/venvs/blockstore/lib/python3.5/site-packages/django/db/backends/base/base.py", line 213, in ensure_connection
self.connect()
File "/edx/app/blockstore/venvs/blockstore/lib/python3.5/site-packages/django/db/backends/base/base.py", line 184, in connect
self.close_at = None if max_age is None else time.time() + max_age
Is there a workaround for this?
Maybe that’s another question for @braden, as I understand he’s the original author of that role.