Skip to content

Commit

Permalink
collectionviews: Synchronize concurrent ensure_initiated functions
Browse files Browse the repository at this point in the history
It is possible for concurrent requests to be served by different threads
in the same Python process, resulting in unexpected behaviour if the
wrapper function from ensure_initiated is not finished executing for the
first time. To solve this, wrap the critical code in a lock.

https://phabricator.endlessm.com/T35159
  • Loading branch information
dylanmccall committed Feb 9, 2024
1 parent 8542bd1 commit d4db24e
Showing 1 changed file with 7 additions and 3 deletions.
10 changes: 7 additions & 3 deletions kolibri_explore_plugin/collectionviews.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import time
from enum import auto
from enum import IntEnum
from threading import RLock

from django.utils.translation import gettext_lazy as _
from kolibri.core.content.errors import InsufficientStorageSpaceError
Expand Down Expand Up @@ -72,6 +73,8 @@
"completed": 1,
}

ENSURE_INITIATED_RLOCK = RLock()


class ChannelNotImported(Exception):
pass
Expand Down Expand Up @@ -763,9 +766,10 @@ def ensure_initiated(api_function):
"""Decorator to initiate only once in the first API call."""

def wrapper(*args, **kwargs):
if _collection_download_manager is None:
_read_content_manifests()
return api_function(*args, **kwargs)
with ENSURE_INITIATED_RLOCK:
if _collection_download_manager is None:
_read_content_manifests()
return api_function(*args, **kwargs)

return wrapper

Expand Down

0 comments on commit d4db24e

Please sign in to comment.