diff --git a/.gitignore b/.gitignore index a7fa46a4..6365d655 100644 --- a/.gitignore +++ b/.gitignore @@ -69,3 +69,4 @@ docs/Makefile /docs/_build /venv311 /.python-version +/huey.log diff --git a/base.cfg b/base.cfg index a3f14bc3..92ddd9e8 100644 --- a/base.cfg +++ b/base.cfg @@ -14,10 +14,12 @@ parts = i18ndude omelette robot + huey plone-helper-scripts develop = . + src/collective.taskqueue2 [instance] @@ -26,10 +28,13 @@ user = admin:admin http-address = 8080 environment-vars = zope_i18n_compile_mo_files true + HUEY_CONSUMER True + HUEY_LOG_LEVEL WARNING eggs = Plone Pillow pdbpp + huey Products.EasyNewsletter [test] [vscode] @@ -90,6 +95,10 @@ eggs = zest.releaser recipe = zc.recipe.egg eggs = i18ndude +[huey] +recipe = zc.recipe.egg +eggs = huey + [plone-helper-scripts] recipe = zc.recipe.egg @@ -99,6 +108,7 @@ eggs = interpreter = zopepy scripts = zopepy + huey_consumer plone-compile-resources diff --git a/setup.cfg b/setup.cfg index b91799fe..9d438cda 100644 --- a/setup.cfg +++ b/setup.cfg @@ -18,6 +18,7 @@ ignore = C813, C101, E203 + F401 # E203, E266 exclude = bootstrap.py,docs,*.egg.,omelette max-line-length = 88 diff --git a/setup.py b/setup.py index 9930adee..0d59ef92 100644 --- a/setup.py +++ b/setup.py @@ -53,6 +53,9 @@ "html2text", "email-validator>=1.1.2", "six", + "collective.taskqueue2", + # "huey", + # "gevent", ], extras_require=dict( test=[ diff --git a/src/Products/EasyNewsletter/__init__.py b/src/Products/EasyNewsletter/__init__.py index a2a29932..7ce1baa3 100644 --- a/src/Products/EasyNewsletter/__init__.py +++ b/src/Products/EasyNewsletter/__init__.py @@ -2,7 +2,9 @@ # avoid circular import # from Products.EasyNewsletter import config # noqa from zope.i18nmessageid import MessageFactory +import logging +log = logging.getLogger("Products.EasyNewsletter") EasyNewsletterMessageFactory = MessageFactory("Products.EasyNewsletter") _ = EasyNewsletterMessageFactory diff --git a/src/Products/EasyNewsletter/configure.zcml b/src/Products/EasyNewsletter/configure.zcml index b3cf9448..40f615ec 100644 --- a/src/Products/EasyNewsletter/configure.zcml +++ b/src/Products/EasyNewsletter/configure.zcml @@ -15,6 +15,7 @@ + diff --git a/src/Products/EasyNewsletter/content/newsletter_issue.py b/src/Products/EasyNewsletter/content/newsletter_issue.py index 0be2fa4e..c2ff5fa1 100644 --- a/src/Products/EasyNewsletter/content/newsletter_issue.py +++ b/src/Products/EasyNewsletter/content/newsletter_issue.py @@ -206,7 +206,8 @@ class NewsletterIssue(Container): context_property("content_aggregation_sources") def get_newsletter(self): - return self.__parent__ + return self.aq_inner.aq_parent + # return self.__parent__ # bbb to support ATCT way, needs to be removed in v5.x: getNewsletter = get_newsletter diff --git a/src/Products/EasyNewsletter/issuedatafetcher.py b/src/Products/EasyNewsletter/issuedatafetcher.py index 105d0aa8..cc1cca79 100644 --- a/src/Products/EasyNewsletter/issuedatafetcher.py +++ b/src/Products/EasyNewsletter/issuedatafetcher.py @@ -105,7 +105,9 @@ def _render_output_html(self, preview=False): with header+body+footer (raw html). """ output_tmpl_id = self.issue.output_template - issue_tmpl = self.issue.restrictedTraverse(str(output_tmpl_id)) + issue_tmpl = self.issue.restrictedTraverse(str(output_tmpl_id), None) + if not issue_tmpl: + import pdb; pdb.set_trace() # NOQA: E702 output_html = issue_tmpl.render() return output_html diff --git a/src/Products/EasyNewsletter/queue/configure.zcml b/src/Products/EasyNewsletter/queue/configure.zcml index 530a25e9..0c6a976a 100644 --- a/src/Products/EasyNewsletter/queue/configure.zcml +++ b/src/Products/EasyNewsletter/queue/configure.zcml @@ -8,6 +8,9 @@ /> + diff --git a/src/Products/EasyNewsletter/queue/huey/__init__.py b/src/Products/EasyNewsletter/queue/huey/__init__.py new file mode 100644 index 00000000..40a96afc --- /dev/null +++ b/src/Products/EasyNewsletter/queue/huey/__init__.py @@ -0,0 +1 @@ +# -*- coding: utf-8 -*- diff --git a/src/Products/EasyNewsletter/queue/huey/configure.zcml b/src/Products/EasyNewsletter/queue/huey/configure.zcml new file mode 100644 index 00000000..cffc29ea --- /dev/null +++ b/src/Products/EasyNewsletter/queue/huey/configure.zcml @@ -0,0 +1,14 @@ + + + + diff --git a/src/Products/EasyNewsletter/queue/huey/handler.py b/src/Products/EasyNewsletter/queue/huey/handler.py new file mode 100644 index 00000000..2f828830 --- /dev/null +++ b/src/Products/EasyNewsletter/queue/huey/handler.py @@ -0,0 +1,11 @@ +from zope.interface import implementer +from Products.EasyNewsletter.queue.interfaces import IIssueQueue +from .huey_tasks import send_newsletters + + +@implementer(IIssueQueue) +class IssueQueue(object): + def start(self, context): + """Queues issue for sendout through huey-mini task queue""" + task_res = send_newsletters(context.UID()) + return task_res diff --git a/src/Products/EasyNewsletter/queue/huey/huey_tasks.py b/src/Products/EasyNewsletter/queue/huey/huey_tasks.py new file mode 100644 index 00000000..b28f5e48 --- /dev/null +++ b/src/Products/EasyNewsletter/queue/huey/huey_tasks.py @@ -0,0 +1,25 @@ +import tempfile + +from huey import SqliteHuey +from plone import api +from Products.EasyNewsletter import log + +QUEUE_NAME = "Products.EasyNewsletter.queue" +# VIEW_NAME = "enl_taskqueue_sendout" + +huey_db_name = tempfile.NamedTemporaryFile(suffix=".db", delete=False).name +huey = SqliteHuey(filename=huey_db_name) +log.info(f"Huey SQLite DB: {huey_db_name}") + + +@huey.task() +def send_newsletters(uid): + """ resolve the context object by given uid and triggers + generation and sending of the newsletter issue. + """ + # from zope.component import getGlobalSiteManager + # gsm = getGlobalSiteManager() + # import pdb; pdb.set_trace() # NOQA: E702 + context = api.content.get(UID=uid) + send_view = api.content.get_view(name="send-issue", context=context) + send_view.send() diff --git a/src/Products/EasyNewsletter/queue/huey/view.py b/src/Products/EasyNewsletter/queue/huey/view.py new file mode 100644 index 00000000..7a44b5d2 --- /dev/null +++ b/src/Products/EasyNewsletter/queue/huey/view.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +from plone import api +from plone.protect.interfaces import IDisableCSRFProtection +from Products.Five.browser import BrowserView +from zope.interface import alsoProvides + +from Products.EasyNewsletter import log + + +class ProcessQueue(BrowserView): + def __call__(self): + alsoProvides(self.request, IDisableCSRFProtection) + log.info("generating and sending newsletter issue emails") + send_view = api.content.get_view(name="send-issue", context=self.context) + send_view.send() + log.info("sending done ;)") diff --git a/src/Products/EasyNewsletter/queue/taskqueue/configure.zcml b/src/Products/EasyNewsletter/queue/taskqueue/configure.zcml index cbec8cae..e6a7022b 100644 --- a/src/Products/EasyNewsletter/queue/taskqueue/configure.zcml +++ b/src/Products/EasyNewsletter/queue/taskqueue/configure.zcml @@ -6,9 +6,9 @@ + diff --git a/src/Products/EasyNewsletter/queue/taskqueue/handler.py b/src/Products/EasyNewsletter/queue/taskqueue/handler.py index 7f5fb51d..821bc033 100644 --- a/src/Products/EasyNewsletter/queue/taskqueue/handler.py +++ b/src/Products/EasyNewsletter/queue/taskqueue/handler.py @@ -1,18 +1,34 @@ # -*- coding: utf-8 -*- -from collective.taskqueue import taskqueue +from plone import api +from collective.taskqueue2.huey_tasks import schedule_browser_view from Products.EasyNewsletter.queue.interfaces import IIssueQueue from zope.interface import implementer QUEUE_NAME = "Products.EasyNewsletter.queue" -VIEW_NAME = "enl_taskqueue_sendout" +ENL_VIEW_NAME = "enl_taskqueue_sendout" @implementer(IIssueQueue) class TCIssueQueue(object): def start(self, context): """Queues issue for sendout through collective.taskqueue""" - jobid = taskqueue.add( - "/".join(context.getPhysicalPath() + (VIEW_NAME,)), queue=QUEUE_NAME + # import pdb; pdb.set_trace() # NOQA: E702 + result = schedule_browser_view( + view_name=ENL_VIEW_NAME, + context_path="/".join(context.getPhysicalPath()), + site_path="/".join(api.portal.get().getPhysicalPath()), + username=api.user.get_current().getId(), + params=dict( + base=context.REQUEST.base, + layers=context.REQUEST.__provides__, + cookies=context.REQUEST.cookies, + form=dict(), + _plonebrowserlayer_=context.REQUEST._plonebrowserlayer_, + _plonetheme_=context.REQUEST._plonetheme_, + ), ) - return jobid + # jobid = taskqueue.add( + # "/".join(context.getPhysicalPath() + (VIEW_NAME,)), queue=QUEUE_NAME + # ) + return result diff --git a/src/Products/EasyNewsletter/queue/taskqueue/view.py b/src/Products/EasyNewsletter/queue/taskqueue/view.py index daba1aa4..5b6038c9 100644 --- a/src/Products/EasyNewsletter/queue/taskqueue/view.py +++ b/src/Products/EasyNewsletter/queue/taskqueue/view.py @@ -1,10 +1,18 @@ # -*- coding: utf-8 -*- +from plone import api from plone.protect.interfaces import IDisableCSRFProtection from Products.Five.browser import BrowserView from zope.interface import alsoProvides +from Products.EasyNewsletter import log + class ProcessQueue(BrowserView): def __call__(self): alsoProvides(self.request, IDisableCSRFProtection) - self.context.send() + log.info("start sending:\n") + import pdb; pdb.set_trace() # NOQA: E702`c` + # send_view = api.content.get_view(name="send-issue", context=self.context) + send_view = self.context.restrictedTraverse("send-issue") + send_view.send() + log.info("sending done ;)\n") diff --git a/src/Products/EasyNewsletter/views/configure.zcml b/src/Products/EasyNewsletter/views/configure.zcml index 5188ea3b..aefbacfa 100644 --- a/src/Products/EasyNewsletter/views/configure.zcml +++ b/src/Products/EasyNewsletter/views/configure.zcml @@ -26,8 +26,9 @@ name="send-issue" for="Products.EasyNewsletter.content.newsletter_issue.INewsletterIssue" class=".newsletter_issue_send.NewsletterIssueSend" - permission="cmf.ModifyPortalContent" + permission="zope2.View" /> +