From ce47e1f5474c67c014381414ef27dc266c66cb95 Mon Sep 17 00:00:00 2001 From: christopher lee Date: Tue, 1 May 2018 10:32:52 -0400 Subject: [PATCH] Update rate limit for enrollment api LEARNER-5101: The current rate limit was adjusted to be very high for staff users to account for excessive calls from the ecommerce service. The ecommerce service has been updated to not make these calls. This commit intends to adjust the rate limit to it's original state before the excessive calls. --- common/djangoapps/enrollment/__init__.py | 9 +++++ common/djangoapps/enrollment/views.py | 48 ++++++++++++++++-------- 2 files changed, 42 insertions(+), 15 deletions(-) diff --git a/common/djangoapps/enrollment/__init__.py b/common/djangoapps/enrollment/__init__.py index e69de29bb2..c3623e65c5 100644 --- a/common/djangoapps/enrollment/__init__.py +++ b/common/djangoapps/enrollment/__init__.py @@ -0,0 +1,9 @@ +""" +Enrollment API helpers and settings +""" +from openedx.core.djangoapps.waffle_utils import (WaffleFlag, WaffleFlagNamespace) + +WAFFLE_FLAG_NAMESPACE = WaffleFlagNamespace(name='enrollment_api_rate_limit') + +REDUCE_RATE_LIMIT_FOR_STAFF_FOR_ENROLLMENT_API = WaffleFlag(WAFFLE_FLAG_NAMESPACE, 'reduce_staff_rate_limit') +USE_UNIVERSAL_RATE_LIMIT_FOR_ENROLLMENT_API = WaffleFlag(WAFFLE_FLAG_NAMESPACE, 'use_universal_rate_limit') diff --git a/common/djangoapps/enrollment/views.py b/common/djangoapps/enrollment/views.py index 96e3deddff..d642daedf6 100644 --- a/common/djangoapps/enrollment/views.py +++ b/common/djangoapps/enrollment/views.py @@ -5,26 +5,22 @@ consist primarily of authentication, request validation, and serialization. """ import logging +from course_modes.models import CourseMode from django.contrib.auth import get_user_model from django.core.exceptions import ObjectDoesNotExist from django.utils.decorators import method_decorator from edx_rest_framework_extensions.authentication import JwtAuthentication -from opaque_keys import InvalidKeyError -from opaque_keys.edx.keys import CourseKey -from rest_framework import status, permissions -from rest_framework.response import Response -from rest_framework.throttling import UserRateThrottle -from rest_framework.views import APIView -from six import text_type - -from course_modes.models import CourseMode from enrollment import api from enrollment.errors import CourseEnrollmentError, CourseEnrollmentExistsError, CourseModeNotFoundError +from enrollment import REDUCE_RATE_LIMIT_FOR_STAFF_FOR_ENROLLMENT_API, \ + USE_UNIVERSAL_RATE_LIMIT_FOR_ENROLLMENT_API +from opaque_keys import InvalidKeyError +from opaque_keys.edx.keys import CourseKey + from openedx.core.djangoapps.cors_csrf.authentication import SessionAuthenticationCrossDomainCsrf from openedx.core.djangoapps.cors_csrf.decorators import ensure_csrf_cookie_cross_domain from openedx.core.djangoapps.embargo import api as embargo_api from openedx.core.djangoapps.user_api.accounts.permissions import CanRetireUser -from openedx.core.djangoapps.user_api.models import UserRetirementStatus from openedx.core.djangoapps.user_api.preferences.api import update_email_opt_in from openedx.core.lib.api.authentication import ( OAuth2AuthenticationAllowInactiveUser, @@ -35,10 +31,15 @@ from openedx.core.lib.exceptions import CourseNotFoundError from openedx.core.lib.log_utils import audit_log from openedx.features.enterprise_support.api import ( ConsentApiServiceClient, - EnterpriseApiServiceClient, EnterpriseApiException, + EnterpriseApiServiceClient, enterprise_enabled ) +from rest_framework import permissions, status +from rest_framework.response import Response +from rest_framework.throttling import UserRateThrottle +from rest_framework.views import APIView +from six import text_type from student.auth import user_has_role from student.models import User from student.roles import CourseStaffRole, GlobalStaff @@ -77,14 +78,31 @@ class ApiKeyPermissionMixIn(object): class EnrollmentUserThrottle(UserRateThrottle, ApiKeyPermissionMixIn): """Limit the number of requests users can make to the enrollment API.""" - # The staff Throttle rate is currently being adjusted to meet the needs of the eCommerce API calls. - # This should be reviewed for performance and we should determine the optimum throttle for the needs of this API. - # https://openedx.atlassian.net/wiki/spaces/LEARNER/pages/645923004/eCommerce+Guild + # TODO: After confirming that reducing the throttle is successful, remove + # and clean up waffles. The rate limit has been increased over the course + # of a few months to account for unnecessary calls from the ecommerce + # service. These calls are no longer made and the plan is to set the + # rate limit back to its original state. LEARNER-5148 + + # Current rate limit THROTTLE_RATES = { 'user': '40/minute', - 'staff': '2000/minute', # Decided on by looking at number of API calls to the Enrollment API from Staff users + 'staff': '2000/minute', } + # Less aggressive reduction in throttle limit. This should not be necessary + if REDUCE_RATE_LIMIT_FOR_STAFF_FOR_ENROLLMENT_API.is_enabled(): + THROTTLE_RATES = { + 'user': '40/minute', + 'staff': '400/minute', + } + + # Original rate Limit before rate limit increases. + if USE_UNIVERSAL_RATE_LIMIT_FOR_ENROLLMENT_API.is_enabled(): + THROTTLE_RATES = { + 'user': '40/minute', + } + def allow_request(self, request, view): # Use a special scope for staff to allow for a separate throttle rate user = request.user