Update task creation
This commit is contained in:
parent
c830a42cc6
commit
8c69a22b32
9 changed files with 82 additions and 71 deletions
10
src/newsreader/accounts/migrations/0012_remove_user_task.py
Normal file
10
src/newsreader/accounts/migrations/0012_remove_user_task.py
Normal file
|
|
@ -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")]
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
import json
|
|
||||||
|
|
||||||
from django.contrib.auth.models import AbstractUser
|
from django.contrib.auth.models import AbstractUser
|
||||||
from django.contrib.auth.models import UserManager as DjangoUserManager
|
from django.contrib.auth.models import UserManager as DjangoUserManager
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.translation import gettext as _
|
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):
|
class UserManager(DjangoUserManager):
|
||||||
|
|
@ -41,15 +40,6 @@ class UserManager(DjangoUserManager):
|
||||||
class User(AbstractUser):
|
class User(AbstractUser):
|
||||||
email = models.EmailField(_("email address"), unique=True)
|
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_refresh_token = models.CharField(max_length=255, blank=True, null=True)
|
||||||
reddit_access_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"
|
USERNAME_FIELD = "email"
|
||||||
REQUIRED_FIELDS = []
|
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):
|
def delete(self, *args, **kwargs):
|
||||||
self.task.delete()
|
tasks = PeriodicTask.objects.filter(name__contains=self.email)
|
||||||
|
tasks.delete()
|
||||||
|
|
||||||
return super().delete(*args, **kwargs)
|
return super().delete(*args, **kwargs)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,24 @@
|
||||||
from django.test import TestCase
|
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):
|
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):
|
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()
|
user.delete()
|
||||||
|
|
||||||
self.assertEquals(PeriodicTask.objects.count(), 0)
|
self.assertEquals(PeriodicTask.objects.count(), 0)
|
||||||
|
|
|
||||||
|
|
@ -290,7 +290,7 @@ class RedditClient(PostClient):
|
||||||
break
|
break
|
||||||
except StreamException as e:
|
except StreamException as e:
|
||||||
logger.exception(
|
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)
|
self.set_rule_error(stream.rule, e)
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@ from django.urls import reverse
|
||||||
|
|
||||||
import pytz
|
import pytz
|
||||||
|
|
||||||
|
from django_celery_beat.models import PeriodicTask
|
||||||
|
|
||||||
from newsreader.news.collection.choices import RuleTypeChoices
|
from newsreader.news.collection.choices import RuleTypeChoices
|
||||||
from newsreader.news.collection.models import CollectionRule
|
from newsreader.news.collection.models import CollectionRule
|
||||||
from newsreader.news.collection.tests.factories import FeedFactory
|
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.category.pk, self.category.pk)
|
||||||
self.assertEquals(rule.user.pk, self.user.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):
|
class FeedUpdateViewTestCase(CollectionRuleViewTestCase, TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,9 @@ class TwitterTimelineCreateViewTestCase(CollectionRuleViewTestCase, TestCase):
|
||||||
|
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
PeriodicTask.objects.get(
|
PeriodicTask.objects.get(
|
||||||
name=self.user.email, task="TwitterTimelineTask", enabled=True
|
name=f"{self.user.email}-timeline",
|
||||||
|
task="TwitterTimelineTask",
|
||||||
|
enabled=True,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,11 @@
|
||||||
|
import json
|
||||||
|
|
||||||
from django.urls import reverse_lazy
|
from django.urls import reverse_lazy
|
||||||
|
|
||||||
import pytz
|
import pytz
|
||||||
|
|
||||||
|
from django_celery_beat.models import IntervalSchedule, PeriodicTask
|
||||||
|
|
||||||
from newsreader.news.collection.models import CollectionRule
|
from newsreader.news.collection.models import CollectionRule
|
||||||
from newsreader.news.core.models import Category
|
from newsreader.news.core.models import Category
|
||||||
|
|
||||||
|
|
@ -32,3 +36,25 @@ class CollectionRuleDetailMixin:
|
||||||
kwargs = super().get_form_kwargs()
|
kwargs = super().get_form_kwargs()
|
||||||
kwargs["user"] = self.request.user
|
kwargs["user"] = self.request.user
|
||||||
return kwargs
|
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
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@ from django.urls import reverse
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
from django.views.generic.edit import CreateView, FormView, UpdateView
|
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.choices import RuleTypeChoices
|
||||||
from newsreader.news.collection.forms import (
|
from newsreader.news.collection.forms import (
|
||||||
CollectionRuleBulkForm,
|
CollectionRuleBulkForm,
|
||||||
|
|
@ -13,12 +15,14 @@ from newsreader.news.collection.models import CollectionRule
|
||||||
from newsreader.news.collection.views.base import (
|
from newsreader.news.collection.views.base import (
|
||||||
CollectionRuleDetailMixin,
|
CollectionRuleDetailMixin,
|
||||||
CollectionRuleViewMixin,
|
CollectionRuleViewMixin,
|
||||||
|
TaskCreationMixin,
|
||||||
)
|
)
|
||||||
from newsreader.utils.opml import parse_opml
|
from newsreader.utils.opml import parse_opml
|
||||||
|
|
||||||
|
|
||||||
class FeedUpdateView(CollectionRuleViewMixin, CollectionRuleDetailMixin, UpdateView):
|
class FeedUpdateView(CollectionRuleViewMixin, CollectionRuleDetailMixin, UpdateView):
|
||||||
template_name = "news/collection/views/feed-update.html"
|
template_name = "news/collection/views/feed-update.html"
|
||||||
|
context_object_name = "feed"
|
||||||
form_class = FeedForm
|
form_class = FeedForm
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
|
|
@ -26,10 +30,14 @@ class FeedUpdateView(CollectionRuleViewMixin, CollectionRuleDetailMixin, UpdateV
|
||||||
return queryset.filter(type=RuleTypeChoices.feed)
|
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"
|
template_name = "news/collection/views/feed-create.html"
|
||||||
|
task_interval = (1, IntervalSchedule.HOURS)
|
||||||
|
task_name = "feed"
|
||||||
|
task_type = "FeedTask"
|
||||||
form_class = FeedForm
|
form_class = FeedForm
|
||||||
context_object_name = "feed"
|
|
||||||
|
|
||||||
|
|
||||||
class OPMLImportView(FormView):
|
class OPMLImportView(FormView):
|
||||||
|
|
|
||||||
|
|
@ -1,44 +1,25 @@
|
||||||
import json
|
|
||||||
|
|
||||||
from django.views.generic.edit import CreateView, UpdateView
|
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.choices import RuleTypeChoices
|
||||||
from newsreader.news.collection.forms import TwitterTimelineForm
|
from newsreader.news.collection.forms import TwitterTimelineForm
|
||||||
from newsreader.news.collection.views.base import (
|
from newsreader.news.collection.views.base import (
|
||||||
CollectionRuleDetailMixin,
|
CollectionRuleDetailMixin,
|
||||||
CollectionRuleViewMixin,
|
CollectionRuleViewMixin,
|
||||||
|
TaskCreationMixin,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class TwitterTimelineCreateView(
|
class TwitterTimelineCreateView(
|
||||||
CollectionRuleViewMixin, CollectionRuleDetailMixin, CreateView
|
CollectionRuleViewMixin, CollectionRuleDetailMixin, TaskCreationMixin, CreateView
|
||||||
):
|
):
|
||||||
form_class = TwitterTimelineForm
|
form_class = TwitterTimelineForm
|
||||||
template_name = "news/collection/views/twitter/timeline-create.html"
|
template_name = "news/collection/views/twitter/timeline-create.html"
|
||||||
|
task_interval = (10, IntervalSchedule.MINUTES)
|
||||||
def form_valid(self, form):
|
task_name = "timeline"
|
||||||
response = super().form_valid(form)
|
task_type = "TwitterTimelineTask"
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
class TwitterTimelineUpdateView(
|
class TwitterTimelineUpdateView(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue