Commit ec787a99 by adeel khan Committed by GitHub

Merge pull request #15332 from…

Merge pull request #15332 from edx/adeel/LEARNER-1188_Setting_connection_timeout_value_for_sailthru_api_call

Implementing connection timeout for sailthru api call.
parents 95b3055f 52e28d91
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('email_marketing', '0004_emailmarketingconfiguration_welcome_email_send_delay'),
]
operations = [
migrations.AddField(
model_name='emailmarketingconfiguration',
name='user_registration_cookie_timeout_delay',
field=models.FloatField(default=1.5, help_text='The number of seconds to delay/timeout wait to get cookie values from sailthru.'),
),
]
......@@ -136,6 +136,14 @@ class EmailMarketingConfiguration(ConfigurationModel):
)
)
# The number of seconds to delay/timeout wait to get cookie values from sailthru.
user_registration_cookie_timeout_delay = models.fields.FloatField(
default=1.5,
help_text=_(
"The number of seconds to delay/timeout wait to get cookie values from sailthru."
)
)
def __unicode__(self):
return u"Email marketing configuration: New user list %s, Activation template: %s" % \
(self.sailthru_new_user_list, self.sailthru_activation_template)
......@@ -9,9 +9,10 @@ from django.conf import settings
from django.dispatch import receiver
from sailthru.sailthru_client import SailthruClient
from sailthru.sailthru_error import SailthruClientError
from celery.exceptions import TimeoutError
from email_marketing.models import EmailMarketingConfiguration
from lms.djangoapps.email_marketing.tasks import update_user, update_user_email
from lms.djangoapps.email_marketing.tasks import update_user, update_user_email, get_email_cookies_via_sailthru
from student.cookies import CREATE_LOGON_COOKIE
from student.views import REGISTER_USER
from util.model_utils import USER_FIELD_CHANGED
......@@ -54,41 +55,34 @@ def add_email_marketing_cookies(sender, response=None, user=None,
if sailthru_content:
post_parms['cookies'] = {'anonymous_interest': sailthru_content}
try:
sailthru_client = SailthruClient(email_config.sailthru_key, email_config.sailthru_secret)
log.info(
'Sending to Sailthru the user interest cookie [%s] for user [%s]',
post_parms.get('cookies', ''),
user.email
)
time_before_call = datetime.datetime.now()
time_before_call = datetime.datetime.now()
sailthru_response = get_email_cookies_via_sailthru.delay(user.email, post_parms)
sailthru_response = \
sailthru_client.api_post("user", post_parms)
try:
# synchronous call to get result of an asynchronous celery task, with timeout
sailthru_response.get(timeout=email_config.user_registration_cookie_timeout_delay,
propagate=True)
cookie = sailthru_response.result
except TimeoutError as exc:
log.error("Timeout error while attempting to obtain cookie from Sailthru: %s", unicode(exc))
return response
except SailthruClientError as exc:
log.error("Exception attempting to obtain cookie from Sailthru: %s", unicode(exc))
return response
if sailthru_response.is_ok():
if 'keys' in sailthru_response.json and 'cookie' in sailthru_response.json['keys']:
cookie = sailthru_response.json['keys']['cookie']
response.set_cookie(
'sailthru_hid',
cookie,
max_age=365 * 24 * 60 * 60, # set for 1 year
domain=settings.SESSION_COOKIE_DOMAIN,
path='/',
)
_log_sailthru_api_call_time(time_before_call)
else:
log.error("No cookie returned attempting to obtain cookie from Sailthru for %s", user.email)
if not cookie:
log.error("No cookie returned attempting to obtain cookie from Sailthru for %s", user.email)
return response
else:
error = sailthru_response.get_error()
# generally invalid email address
log.info("Error attempting to obtain cookie from Sailthru: %s", error.get_message())
response.set_cookie(
'sailthru_hid',
cookie,
max_age=365 * 24 * 60 * 60, # set for 1 year
domain=settings.SESSION_COOKIE_DOMAIN,
path='/',
)
_log_sailthru_api_call_time(time_before_call)
return response
......
......@@ -17,6 +17,46 @@ log = logging.getLogger(__name__)
SAILTHRU_LIST_CACHE_KEY = "email.marketing.cache"
@task(bind=True)
def get_email_cookies_via_sailthru(self, user_email, post_parms):
"""
Adds/updates Sailthru cookie information for a new user.
Args:
post_parms(dict): User profile information to pass as 'vars' to Sailthru
Returns:
cookie(str): cookie fetched from Sailthru
"""
email_config = EmailMarketingConfiguration.current()
if not email_config.enabled:
return None
try:
sailthru_client = SailthruClient(email_config.sailthru_key, email_config.sailthru_secret)
log.info(
'Sending to Sailthru the user interest cookie [%s] for user [%s]',
post_parms.get('cookies', ''),
user_email
)
sailthru_response = sailthru_client.api_post("user", post_parms)
except SailthruClientError as exc:
log.error("Exception attempting to obtain cookie from Sailthru: %s", unicode(exc))
raise SailthruClientError
if sailthru_response.is_ok():
if 'keys' in sailthru_response.json and 'cookie' in sailthru_response.json['keys']:
cookie = sailthru_response.json['keys']['cookie']
return cookie
else:
log.error("No cookie returned attempting to obtain cookie from Sailthru for %s", user_email)
else:
error = sailthru_response.get_error()
# generally invalid email address
log.info("Error attempting to obtain cookie from Sailthru: %s", error.get_message())
return None
# pylint: disable=not-callable
@task(bind=True, default_retry_delay=3600, max_retries=24)
def update_user(self, sailthru_vars, email, site=None, new_user=False, activation=False):
......
......@@ -25,7 +25,8 @@ from email_marketing.tasks import (
_get_list_from_email_marketing_provider,
_get_or_create_user_list,
update_user,
update_user_email
update_user_email,
get_email_cookies_via_sailthru
)
from student.tests.factories import UserFactory, UserProfileFactory
from util.json_request import JsonResponse
......@@ -98,13 +99,10 @@ class EmailMarketingTests(TestCase):
self.request.COOKIES['anonymous_interest'] = 'cookie_content'
mock_get_current_request.return_value = self.request
mock_sailthru.return_value = SailthruResponse(JsonResponse({'keys': {'cookie': 'test_cookie'}}))
cookie_log = "Sending to Sailthru the user interest cookie [{'anonymous_interest': 'cookie_content'}]" \
' for user [test@edx.org]'
with LogCapture(LOGGER_NAME, level=logging.INFO) as logger:
add_email_marketing_cookies(None, response=response, user=self.user)
logger.check(
(LOGGER_NAME, 'INFO', cookie_log),
(LOGGER_NAME, 'INFO',
'Started at {start} and ended at {end}, time spent:{delta} milliseconds'.format(
start=datetime.datetime.now().isoformat(' '),
......@@ -121,6 +119,28 @@ class EmailMarketingTests(TestCase):
self.assertEquals(response.cookies['sailthru_hid'].value, "test_cookie")
@patch('email_marketing.signals.SailthruClient.api_post')
def test_get_cookies_via_sailthu(self, mock_sailthru):
cookies = {'cookie': 'test_cookie'}
mock_sailthru.return_value = SailthruResponse(JsonResponse({'keys': cookies}))
post_parms = {
'id': self.user.email,
'fields': {'keys': 1},
'vars': {'last_login_date': datetime.datetime.now().strftime("%Y-%m-%d")},
'cookies': {'anonymous_interest': 'cookie_content'}
}
expected_cookie = get_email_cookies_via_sailthru.delay(self.user.email, post_parms)
mock_sailthru.assert_called_with('user',
{'fields': {'keys': 1},
'cookies': {'anonymous_interest': 'cookie_content'},
'id': TEST_EMAIL,
'vars': {'last_login_date': ANY}})
self.assertEqual(cookies['cookie'], expected_cookie.result)
@patch('email_marketing.signals.SailthruClient.api_post')
def test_drop_cookie_error_path(self, mock_sailthru):
"""
test that error paths return no cookie
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment