fp7-ofelia / ocf

OFELIA Control Framework (OCF) is a set of software tools for testbed management.
http://fp7-ofelia.github.com/ocf/
Other
18 stars 14 forks source link

Mail delivery may take too long under some circumstances #139

Closed CarolinaFernandez closed 11 years ago

CarolinaFernandez commented 11 years ago

Django's send_mail method is used "at it is", but no check is being made in case of any of the following happens:

For example, with the new plugin system an e-mail will be sent if some errors are found in the topology; but this should not affect the load page, which is already mildly high.

Operations like these that do not affect normal flow may be rather dispatched to background...

CarolinaFernandez commented 11 years ago

In order to modify the minimum possible quantity of code, a new Expedient send_mail (wrapper) method was made; which invokes a thread to use the Django's normal send_mail with the given parameters. Every call to send_mail (within django.core.mail) was replaced by this new method.

File: expedient/src/python/expedient/common/utils/mail.py

def send_mail(subject, message, from_email, recipient_list):
    """
    Wrapper for the send_mail method within django.core.mail
    which uses a thread to decouple its execution from the
    main program. This is specially useful if mail server
    configuration is erroneus, server is very busy, etc; so
    normal flow will not be affected.
    """
    ServiceThread.start_method_new_thread(
                                          django__send_mail,
                                          None,
                                          None,
                                          subject,
                                          message,
                                          from_email,
                                          recipient_list,
                                         )

File: expedient/src/python/expedient/common/utils/ServiceThread.py

from threading import Thread

class ServiceThread(Thread):

    __method = None
    __params = None
    callback_url = None
    request_user = None

    @staticmethod
    def start_method_new_thread(method, request_user = None, url = None, *params):
        thread = ServiceThread()
        # Add this 2 params if != None
        if request_user:
            thread.request_user = request_user
        if url:
            thread.callback_url = url
        thread.start_method(method, *params)

    def start_method(self, method, *params):
        self.__method = method
        self.__params = params
        self.start()

    def run(self):
        # self.__params is a tuple of arguments. The asterisk ("*")
        # converts this tuple into a series of arguments
        try:
            self.__method(*self.__params)
        except Exception as e:
            print "[WARNING] ServiceThread could not execute %s(%s).
                Details: %s" % (str(self.__method), str(self.__params), str(e))