Minimize the number of queries done while noop updating a user-preference

This commit is contained in:
Calen Pennington
2017-04-26 14:18:49 -04:00
parent 20caf52bea
commit 1811f7235f
9 changed files with 99 additions and 53 deletions

View File

@@ -268,7 +268,7 @@ class BookmarksListViewTests(BookmarksViewsTestsBase):
self.assertEqual(response.data['developer_message'], u'Parameter usage_id not provided.')
# Send empty data dictionary.
with self.assertNumQueries(8): # No queries for bookmark table.
with self.assertNumQueries(7): # No queries for bookmark table.
response = self.send_post(
client=self.client,
url=reverse('bookmarks'),

View File

@@ -170,3 +170,44 @@ class TestUserPreferenceMiddleware(TestCase):
self.assertIs(result, response)
self.assertEqual(response.mock_calls, [])
def test_preference_update_noop(self):
self.request.COOKIES[settings.LANGUAGE_COOKIE] = 'es'
# No preference yet, should write to the database
self.assertEqual(get_user_preference(self.user, LANGUAGE_KEY), None)
with self.assertNumQueries(5):
self.middleware.process_request(self.request)
self.assertEqual(get_user_preference(self.user, LANGUAGE_KEY), 'es')
response = mock.Mock(spec=HttpResponse)
with self.assertNumQueries(1):
self.middleware.process_response(self.request, response)
# Preference is the same as the cookie, shouldn't write to the database
with self.assertNumQueries(3):
self.middleware.process_request(self.request)
self.assertEqual(get_user_preference(self.user, LANGUAGE_KEY), 'es')
response = mock.Mock(spec=HttpResponse)
with self.assertNumQueries(1):
self.middleware.process_response(self.request, response)
# Cookie changed, should write to the database again
self.request.COOKIES[settings.LANGUAGE_COOKIE] = 'en'
with self.assertNumQueries(5):
self.middleware.process_request(self.request)
self.assertEqual(get_user_preference(self.user, LANGUAGE_KEY), 'en')
with self.assertNumQueries(1):
self.middleware.process_response(self.request, response)

View File

@@ -174,7 +174,7 @@ class TestOwnUsernameAPI(CacheIsolationTestCase, UserAPITestCase):
Test that a client (logged in) can get her own username.
"""
self.client.login(username=self.user.username, password=TEST_PASSWORD)
self._verify_get_own_username(15)
self._verify_get_own_username(14)
def test_get_username_inactive(self):
"""
@@ -184,7 +184,7 @@ class TestOwnUsernameAPI(CacheIsolationTestCase, UserAPITestCase):
self.client.login(username=self.user.username, password=TEST_PASSWORD)
self.user.is_active = False
self.user.save()
self._verify_get_own_username(15)
self._verify_get_own_username(14)
def test_get_username_not_logged_in(self):
"""
@@ -305,7 +305,7 @@ class TestAccountsAPI(CacheIsolationTestCase, UserAPITestCase):
"""
self.different_client.login(username=self.different_user.username, password=TEST_PASSWORD)
self.create_mock_profile(self.user)
with self.assertNumQueries(19):
with self.assertNumQueries(18):
response = self.send_get(self.different_client)
self._verify_full_shareable_account_response(response, account_privacy=ALL_USERS_VISIBILITY)
@@ -320,7 +320,7 @@ class TestAccountsAPI(CacheIsolationTestCase, UserAPITestCase):
"""
self.different_client.login(username=self.different_user.username, password=TEST_PASSWORD)
self.create_mock_profile(self.user)
with self.assertNumQueries(19):
with self.assertNumQueries(18):
response = self.send_get(self.different_client)
self._verify_private_account_response(response, account_privacy=PRIVATE_VISIBILITY)
@@ -395,12 +395,12 @@ class TestAccountsAPI(CacheIsolationTestCase, UserAPITestCase):
self.assertEqual(False, data["accomplishments_shared"])
self.client.login(username=self.user.username, password=TEST_PASSWORD)
verify_get_own_information(17)
verify_get_own_information(16)
# Now make sure that the user can get the same information, even if not active
self.user.is_active = False
self.user.save()
verify_get_own_information(11)
verify_get_own_information(10)
def test_get_account_empty_string(self):
"""
@@ -414,7 +414,7 @@ class TestAccountsAPI(CacheIsolationTestCase, UserAPITestCase):
legacy_profile.save()
self.client.login(username=self.user.username, password=TEST_PASSWORD)
with self.assertNumQueries(17):
with self.assertNumQueries(16):
response = self.send_get(self.client)
for empty_field in ("level_of_education", "gender", "country", "bio"):
self.assertIsNone(response.data[empty_field])

View File

@@ -83,6 +83,7 @@ class PreferenceValidationError(PreferenceRequestError):
"""
def __init__(self, preference_errors):
self.preference_errors = preference_errors
super(PreferenceValidationError, self).__init__(preference_errors)
class PreferenceUpdateError(PreferenceRequestError):
@@ -93,6 +94,7 @@ class PreferenceUpdateError(PreferenceRequestError):
def __init__(self, developer_message, user_message=None):
self.developer_message = developer_message
self.user_message = user_message
super(PreferenceUpdateError, self).__init__(developer_message)
class CountryCodeError(ValueError):

View File

@@ -142,7 +142,9 @@ def update_user_preferences(requesting_user, update, user=None):
if preference_value is not None:
try:
serializer = serializers[preference_key]
serializer.save()
if serializer.instance is None or serializer.instance.value != serializer.validated_data['value']:
serializer.save()
except Exception as error:
raise _create_preference_update_error(preference_key, preference_value, error)
else:
@@ -177,10 +179,11 @@ def set_user_preference(requesting_user, preference_key, preference_value, usern
existing_user = _get_authorized_user(requesting_user, username)
serializer = create_user_preference_serializer(existing_user, preference_key, preference_value)
validate_user_preference_serializer(serializer, preference_key, preference_value)
try:
serializer.save()
except Exception as error:
raise _create_preference_update_error(preference_key, preference_value, error)
if serializer.instance is None or serializer.instance.value != serializer.validated_data['value']:
try:
serializer.save()
except Exception as error:
raise _create_preference_update_error(preference_key, preference_value, error)
@intercept_errors(UserAPIInternalError, ignore_errors=[UserAPIRequestError])
@@ -353,13 +356,13 @@ def create_user_preference_serializer(user, preference_key, preference_value):
except ObjectDoesNotExist:
existing_user_preference = None
new_data = {
"user": user.id,
"key": preference_key,
"value": preference_value,
}
if existing_user_preference:
serializer = RawUserPreferenceSerializer(existing_user_preference, data=new_data)
serializer = RawUserPreferenceSerializer(existing_user_preference, data=new_data, partial=True)
else:
new_data['user'] = user.id
serializer = RawUserPreferenceSerializer(data=new_data)
return serializer