[Zope] oddity in MailHost queue processor thread
Maric Michaud
maric at aristote.info
Fri Apr 30 07:44:19 EDT 2010
Hi all,
I was surprised by the behavior of asynchronous mailing in zope 2.11.3
MailHost product. It creates a thread by instance of MailHost by the
mean of using self.absolute_url(1) as key for the queue_threads dictionnary.
It seems obviously wrong, IMO, if several instances share the same queue
directory, mesages actually get sent more than once.
Following is the monkey patch which works fine for me, but the idea is
straightforward, it's to use the realpath of the smtp_queue_directory as
the identifier of the thread, ensuring that MailHosts that share the
same queue directory will also share the same thread for processing mails.
regards,
# un monkey patch du mailhost de zope2.11, ce dernier utilise une thread
# par instance de mailhost pour la getsion de la queue de messages, ce n'est
# pas correct, il faut qu'il garantisse qu'il n'y a qu'une thread par
# répertoire réel de queue.
from Products.MailHost import MailHost as mh
if not hasattr(mh.MailBase, '_cfenet_patched_queueThreadAlive'):
mh.MailBase._cfenet_patched_queueThreadAlive =
mh.MailBase.queueThreadAlive
def queueThreadAlive(self):
"""return True/False is queue thread is working"""
from Products.MailHost import MailHost as mh
from os.path import realpath
# Il est important d'avoir un mailer unique par répertoire
th = mh.queue_threads.get(realpath(self.smtp_queue_directory))
return th and th.isAlive()
mh.MailBase.queueThreadAlive = queueThreadAlive
if not hasattr(mh.MailBase, '_cfenet_patched__stopQueueProcessorThread'):
mh.MailBase._cfenet_patched__stopQueueProcessorThread = \
mh.MailBase._stopQueueProcessorThread
@mh.synchronized(mh.MailBase.lock)
def _stopQueueProcessorThread(self):
""" Stop thread for processing the mail queue """
from Products.MailHost import MailHost as mh
from os.path import realpath
path = realpath(self.smtp_queue_directory)
if mh.queue_threads.has_key(path):
th = mh.queue_threads[path]
th.stop()
while th.isAlive():
# wait until thread is really dead
mh.time.sleep(0.3)
del mh.queue_threads[path]
mh.LOG.info('Thread for %s stopped' % path)
mh.MailBase._stopQueueProcessorThread = _stopQueueProcessorThread
if not hasattr(mh.MailBase, '_cfenet_patched__startQueueProcessorThread'):
mh.MailBase._cfenet_patched__startQueueProcessorThread = \
mh.MailBase._startQueueProcessorThread
@mh.synchronized(mh.MailBase.lock)
def _startQueueProcessorThread(self):
""" Start thread for processing the mail queue """
from Products.MailHost import MailHost as mh
from os.path import realpath
path = realpath(self.smtp_queue_directory)
if not mh.queue_threads.has_key(path):
th = mh.QueueProcessorThread()
th.setMailer(self._makeMailer())
th.setQueuePath(self.smtp_queue_directory)
th.start()
mh.queue_threads[path] = th
mh.LOG.info('Thread for %s started' % path)
mh.MailBase._startQueueProcessorThread = _startQueueProcessorThread
--
_____________
Maric Michaud
More information about the Zope
mailing list