Skip to content

Commit

Permalink
feat: make it possible to globally disable forum v2 with setting
Browse files Browse the repository at this point in the history
We introduce a setting that allows us to bypass any course waffle flag
check. The advantage of such a setting is that we don't need to find the
course ID: in some cases, we might not have access to the course ID, and
we need to look for it... in forum v2.

See discussion here: openedx/forum#137
  • Loading branch information
regisb committed Dec 9, 2024
1 parent 2cb9aef commit e2c5fec
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 14 deletions.
14 changes: 13 additions & 1 deletion openedx/core/djangoapps/discussions/config/waffle.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
This module contains various configuration settings via
waffle switches for the discussions app.
"""
from django.conf import settings

from openedx.core.djangoapps.waffle_utils import CourseWaffleFlag

Expand Down Expand Up @@ -57,6 +58,17 @@

def is_forum_v2_enabled(course_id):
"""
Returns a boolean if forum V2 is enabled on the course
Returns whether forum V2 is enabled on the course. This is a 2-step check:
1. Check value of settings.DISABLE_FORUM_V2: if it exists and is true, this setting overrides any course flag.
2. Else, check the value of the corresponding course waffle flag.
"""
if is_forum_v2_disabled_globally():
return False
return ENABLE_FORUM_V2.is_enabled(course_id)

def is_forum_v2_disabled_globally() -> bool:
"""
Return True if DISABLE_FORUM_V2 is defined and true-ish.
"""
return getattr(settings, "DISABLE_FORUM_V2", False)
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@


import logging
import typing as t

from .utils import CommentClientRequestError, extract, perform_request, get_course_key
from forum import api as forum_api
from openedx.core.djangoapps.discussions.config.waffle import is_forum_v2_enabled
from openedx.core.djangoapps.discussions.config.waffle import is_forum_v2_enabled, is_forum_v2_disabled_globally

log = logging.getLogger(__name__)

Expand Down Expand Up @@ -72,13 +73,14 @@ def retrieve(self, *args, **kwargs):

def _retrieve(self, *args, **kwargs):
course_id = self.attributes.get("course_id") or kwargs.get("course_id")
if not course_id:
course_id = forum_api.get_course_id_by_comment(self.id)
course_key = get_course_key(course_id)
if course_id:
use_forumv2 = is_forum_v2_enabled(course_id)
else:
use_forumv2, course_id = is_forum_v2_enabled_for_comment(self.id)
response = None
if is_forum_v2_enabled(course_key):
if use_forumv2:
if self.type == "comment":
response = forum_api.get_parent_comment(comment_id=self.attributes["id"], course_id=str(course_key))
response = forum_api.get_parent_comment(comment_id=self.attributes["id"], course_id=course_id)
if response is None:
raise CommentClientRequestError("Forum v2 API call is missing")
else:
Expand Down Expand Up @@ -369,3 +371,21 @@ def handle_create_thread(self, course_id):
context=request_data.get("context", None),
)
return response

def is_forum_v2_enabled_for_comment(comment_id: str) -> tuple[bool, t.Optional[str]]:
"""
Figure out whether we use forum v2 for a given comment.
See is_forum_v2_enabled_for_thread.
Return:
enabled (bool)
course_id (str or None)
"""
if is_forum_v2_disabled_globally():
return False, None

course_id = forum_api.get_course_id_by_comment(comment_id)
course_key = get_course_key(course_id)
return is_forum_v2_enabled(course_key), course_id
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@


import logging
import typing as t

from eventtracking import tracker

from . import models, settings, utils
from forum import api as forum_api
from openedx.core.djangoapps.discussions.config.waffle import is_forum_v2_enabled
from openedx.core.djangoapps.discussions.config.waffle import is_forum_v2_enabled, is_forum_v2_disabled_globally

log = logging.getLogger(__name__)

Expand Down Expand Up @@ -171,17 +172,14 @@ def _retrieve(self, *args, **kwargs):
'merge_question_type_responses': kwargs.get('merge_question_type_responses', False)
}
request_params = utils.strip_none(request_params)
course_id = kwargs.get("course_id")
if not course_id:
course_id = forum_api.get_course_id_by_thread(self.id)
course_key = utils.get_course_key(course_id)
if is_forum_v2_enabled(course_key):
use_forumv2, course_id = is_forum_v2_enabled_for_thread(self.id)
if use_forumv2:
if user_id := request_params.get('user_id'):
request_params['user_id'] = str(user_id)
response = forum_api.get_thread(
thread_id=self.id,
params=request_params,
course_id=str(course_key)
course_id=course_id,
)
else:
response = utils.perform_request(
Expand Down Expand Up @@ -296,3 +294,28 @@ def _url_for_pin_thread(thread_id):

def _url_for_un_pin_thread(thread_id):
return f"{settings.PREFIX}/threads/{thread_id}/unpin"


def is_forum_v2_enabled_for_thread(thread_id: str) -> tuple[bool, t.Optional[str]]:
"""
Figure out whether we use forum v2 for a given thread.
This is a complex affair... First, we check the value of the DISABLE_FORUM_V2
setting, which overrides everything. If this setting does not exist, then we need to
find the course ID that corresponds to the thread ID. Then, we return the value of
the course waffle flag for this course ID.
Note that to fetch the course ID associated to a thread ID, we need to connect both
to mongodb and mysql. As a consequence, when forum v2 needs adequate connection
strings for both backends.
Return:
enabled (bool)
course_id (str or None)
"""
if is_forum_v2_disabled_globally():
return True, None
course_id = forum_api.get_course_id_by_thread(thread_id)
course_key = utils.get_course_key(course_id)
return is_forum_v2_enabled(course_key), course_id

0 comments on commit e2c5fec

Please sign in to comment.