From 8c69a22b3264cd2cdc557860c05c00ea1e28299f Mon Sep 17 00:00:00 2001 From: Sonny Bakker Date: Sat, 26 Sep 2020 18:51:40 +0200 Subject: [PATCH] Update task creation --- .../migrations/0012_remove_user_task.py | 10 ++++++ src/newsreader/accounts/models.py | 34 +++---------------- src/newsreader/accounts/tests/tests.py | 26 +++++++------- src/newsreader/news/collection/reddit.py | 2 +- .../news/collection/tests/views/test_crud.py | 8 +++++ .../tests/views/test_twitter_views.py | 4 ++- src/newsreader/news/collection/views/base.py | 26 ++++++++++++++ src/newsreader/news/collection/views/feed.py | 12 +++++-- .../news/collection/views/twitter.py | 31 ++++------------- 9 files changed, 82 insertions(+), 71 deletions(-) create mode 100644 src/newsreader/accounts/migrations/0012_remove_user_task.py diff --git a/src/newsreader/accounts/migrations/0012_remove_user_task.py b/src/newsreader/accounts/migrations/0012_remove_user_task.py new file mode 100644 index 0000000..250d300 --- /dev/null +++ b/src/newsreader/accounts/migrations/0012_remove_user_task.py @@ -0,0 +1,10 @@ +# Generated by Django 3.0.7 on 2020-09-26 15:34 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [("accounts", "0011_auto_20200913_2101")] + + operations = [migrations.RemoveField(model_name="user", name="task")] diff --git a/src/newsreader/accounts/models.py b/src/newsreader/accounts/models.py index baf0b39..6341385 100644 --- a/src/newsreader/accounts/models.py +++ b/src/newsreader/accounts/models.py @@ -1,11 +1,10 @@ -import json from django.contrib.auth.models import AbstractUser from django.contrib.auth.models import UserManager as DjangoUserManager from django.db import models from django.utils.translation import gettext as _ -from django_celery_beat.models import IntervalSchedule, PeriodicTask +from django_celery_beat.models import PeriodicTask class UserManager(DjangoUserManager): @@ -41,15 +40,6 @@ class UserManager(DjangoUserManager): class User(AbstractUser): email = models.EmailField(_("email address"), unique=True) - task = models.OneToOneField( - PeriodicTask, - on_delete=models.CASCADE, - null=True, - blank=True, - editable=False, - verbose_name="collection task", - ) - reddit_refresh_token = models.CharField(max_length=255, blank=True, null=True) reddit_access_token = models.CharField(max_length=255, blank=True, null=True) @@ -63,26 +53,10 @@ class User(AbstractUser): USERNAME_FIELD = "email" REQUIRED_FIELDS = [] - def save(self, *args, **kwargs): - super().save(*args, **kwargs) - - if not self.task: - task_interval, _ = IntervalSchedule.objects.get_or_create( - every=1, period=IntervalSchedule.HOURS - ) - - self.task, _ = PeriodicTask.objects.get_or_create( - enabled=True, - interval=task_interval, - name=f"{self.email}-collection-task", - task="FeedTask", - args=json.dumps([self.pk]), - ) - - self.save() - def delete(self, *args, **kwargs): - self.task.delete() + tasks = PeriodicTask.objects.filter(name__contains=self.email) + tasks.delete() + return super().delete(*args, **kwargs) @property diff --git a/src/newsreader/accounts/tests/tests.py b/src/newsreader/accounts/tests/tests.py index e28dbd3..9f6a20f 100644 --- a/src/newsreader/accounts/tests/tests.py +++ b/src/newsreader/accounts/tests/tests.py @@ -1,22 +1,24 @@ from django.test import TestCase -from django_celery_beat.models import PeriodicTask +from django_celery_beat.models import IntervalSchedule, PeriodicTask -from newsreader.accounts.models import User +from newsreader.accounts.tests.factories import UserFactory class UserTestCase(TestCase): - def test_task_is_created(self): - user = User.objects.create(email="durp@burp.nl", task=None) - task = PeriodicTask.objects.get(name=f"{user.email}-collection-task") - - user.refresh_from_db() - - self.assertEquals(task, user.task) - self.assertEquals(PeriodicTask.objects.count(), 1) - def test_task_is_deleted(self): - user = User.objects.create(email="durp@burp.nl", task=None) + user = UserFactory(email="durp@burp.nl") + + interval = IntervalSchedule.objects.create( + every=1, period=IntervalSchedule.HOURS + ) + PeriodicTask.objects.create( + name=f"{user.email}-feed", task="FeedTask", interval=interval + ) + PeriodicTask.objects.create( + name=f"{user.email}-timeline", task="TwitterTimelineTask", interval=interval + ) + user.delete() self.assertEquals(PeriodicTask.objects.count(), 0) diff --git a/src/newsreader/news/collection/reddit.py b/src/newsreader/news/collection/reddit.py index 1cb9e29..22af39f 100644 --- a/src/newsreader/news/collection/reddit.py +++ b/src/newsreader/news/collection/reddit.py @@ -290,7 +290,7 @@ class RedditClient(PostClient): break except StreamException as e: logger.exception( - "Stream failed reading content from {stream.rule.url}" + f"Stream failed reading content from {stream.rule.url}" ) self.set_rule_error(stream.rule, e) diff --git a/src/newsreader/news/collection/tests/views/test_crud.py b/src/newsreader/news/collection/tests/views/test_crud.py index e10f997..7da241d 100644 --- a/src/newsreader/news/collection/tests/views/test_crud.py +++ b/src/newsreader/news/collection/tests/views/test_crud.py @@ -3,6 +3,8 @@ from django.urls import reverse import pytz +from django_celery_beat.models import PeriodicTask + from newsreader.news.collection.choices import RuleTypeChoices from newsreader.news.collection.models import CollectionRule from newsreader.news.collection.tests.factories import FeedFactory @@ -37,6 +39,12 @@ class FeedCreateViewTestCase(CollectionRuleViewTestCase, TestCase): self.assertEquals(rule.category.pk, self.category.pk) self.assertEquals(rule.user.pk, self.user.pk) + self.assertTrue( + PeriodicTask.objects.get( + name=f"{self.user.email}-feed", task="FeedTask", enabled=True + ) + ) + class FeedUpdateViewTestCase(CollectionRuleViewTestCase, TestCase): def setUp(self): diff --git a/src/newsreader/news/collection/tests/views/test_twitter_views.py b/src/newsreader/news/collection/tests/views/test_twitter_views.py index 35897be..129ed79 100644 --- a/src/newsreader/news/collection/tests/views/test_twitter_views.py +++ b/src/newsreader/news/collection/tests/views/test_twitter_views.py @@ -41,7 +41,9 @@ class TwitterTimelineCreateViewTestCase(CollectionRuleViewTestCase, TestCase): self.assertTrue( PeriodicTask.objects.get( - name=self.user.email, task="TwitterTimelineTask", enabled=True + name=f"{self.user.email}-timeline", + task="TwitterTimelineTask", + enabled=True, ) ) diff --git a/src/newsreader/news/collection/views/base.py b/src/newsreader/news/collection/views/base.py index 982a4d3..8a9207d 100644 --- a/src/newsreader/news/collection/views/base.py +++ b/src/newsreader/news/collection/views/base.py @@ -1,7 +1,11 @@ +import json + from django.urls import reverse_lazy import pytz +from django_celery_beat.models import IntervalSchedule, PeriodicTask + from newsreader.news.collection.models import CollectionRule from newsreader.news.core.models import Category @@ -32,3 +36,25 @@ class CollectionRuleDetailMixin: kwargs = super().get_form_kwargs() kwargs["user"] = self.request.user return kwargs + + +class TaskCreationMixin: + def form_valid(self, form): + response = super().form_valid(form) + + interval, period = self.task_interval + task_interval, _ = IntervalSchedule.objects.get_or_create( + every=interval, period=period + ) + + PeriodicTask.objects.get_or_create( + name=f"{self.request.user.email}-{self.task_name}", + task=self.task_type, + enabled=True, + defaults={ + "args": json.dumps([self.request.user.pk]), + "interval": task_interval, + }, + ) + + return response diff --git a/src/newsreader/news/collection/views/feed.py b/src/newsreader/news/collection/views/feed.py index 872d716..b7803d2 100644 --- a/src/newsreader/news/collection/views/feed.py +++ b/src/newsreader/news/collection/views/feed.py @@ -3,6 +3,8 @@ from django.urls import reverse from django.utils.translation import gettext as _ from django.views.generic.edit import CreateView, FormView, UpdateView +from django_celery_beat.models import IntervalSchedule + from newsreader.news.collection.choices import RuleTypeChoices from newsreader.news.collection.forms import ( CollectionRuleBulkForm, @@ -13,12 +15,14 @@ from newsreader.news.collection.models import CollectionRule from newsreader.news.collection.views.base import ( CollectionRuleDetailMixin, CollectionRuleViewMixin, + TaskCreationMixin, ) from newsreader.utils.opml import parse_opml class FeedUpdateView(CollectionRuleViewMixin, CollectionRuleDetailMixin, UpdateView): template_name = "news/collection/views/feed-update.html" + context_object_name = "feed" form_class = FeedForm def get_queryset(self): @@ -26,10 +30,14 @@ class FeedUpdateView(CollectionRuleViewMixin, CollectionRuleDetailMixin, UpdateV return queryset.filter(type=RuleTypeChoices.feed) -class FeedCreateView(CollectionRuleViewMixin, CollectionRuleDetailMixin, CreateView): +class FeedCreateView( + CollectionRuleViewMixin, CollectionRuleDetailMixin, TaskCreationMixin, CreateView +): template_name = "news/collection/views/feed-create.html" + task_interval = (1, IntervalSchedule.HOURS) + task_name = "feed" + task_type = "FeedTask" form_class = FeedForm - context_object_name = "feed" class OPMLImportView(FormView): diff --git a/src/newsreader/news/collection/views/twitter.py b/src/newsreader/news/collection/views/twitter.py index 563bddf..1755b49 100644 --- a/src/newsreader/news/collection/views/twitter.py +++ b/src/newsreader/news/collection/views/twitter.py @@ -1,44 +1,25 @@ -import json from django.views.generic.edit import CreateView, UpdateView -from django_celery_beat.models import IntervalSchedule, PeriodicTask +from django_celery_beat.models import IntervalSchedule from newsreader.news.collection.choices import RuleTypeChoices from newsreader.news.collection.forms import TwitterTimelineForm from newsreader.news.collection.views.base import ( CollectionRuleDetailMixin, CollectionRuleViewMixin, + TaskCreationMixin, ) class TwitterTimelineCreateView( - CollectionRuleViewMixin, CollectionRuleDetailMixin, CreateView + CollectionRuleViewMixin, CollectionRuleDetailMixin, TaskCreationMixin, CreateView ): form_class = TwitterTimelineForm template_name = "news/collection/views/twitter/timeline-create.html" - - def form_valid(self, form): - response = super().form_valid(form) - - task_interval, _ = IntervalSchedule.objects.get_or_create( - every=1, period=IntervalSchedule.HOURS - ) - - task, _ = PeriodicTask.objects.get_or_create( - name=self.request.user.email, - task="TwitterTimelineTask", - enabled=True, - defaults={ - "args": json.dumps([self.request.user.pk]), - "interval": task_interval, - }, - ) - - self.request.user.task = task - self.request.user.save() - - return response + task_interval = (10, IntervalSchedule.MINUTES) + task_name = "timeline" + task_type = "TwitterTimelineTask" class TwitterTimelineUpdateView(