Improving asynch timeline generation

remotes/origin/issue/4795/notification_even_they_are_disabled
Alejandro Alonso 2016-05-31 08:02:30 +02:00 committed by David Barragán Merino
parent 868cc5fb8c
commit 6da3d8d30f
4 changed files with 35 additions and 53 deletions

View File

@ -32,9 +32,9 @@ class TimelineAppConfig(AppConfig):
signals.post_save.connect(handlers.on_new_history_entry, signals.post_save.connect(handlers.on_new_history_entry,
sender=apps.get_model("history", "HistoryEntry"), sender=apps.get_model("history", "HistoryEntry"),
dispatch_uid="timeline") dispatch_uid="timeline")
signals.pre_save.connect(handlers.create_membership_push_to_timeline, signals.post_save.connect(handlers.create_membership_push_to_timeline,
sender=apps.get_model("projects", "Membership")) sender=apps.get_model("projects", "Membership"))
signals.post_delete.connect(handlers.delete_membership_push_to_timeline, signals.pre_delete.connect(handlers.delete_membership_push_to_timeline,
sender=apps.get_model("projects", "Membership")) sender=apps.get_model("projects", "Membership"))
signals.post_save.connect(handlers.create_user_push_to_timeline, signals.post_save.connect(handlers.create_user_push_to_timeline,
sender=get_user_model()) sender=get_user_model())

View File

@ -17,6 +17,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
from django.apps import apps from django.apps import apps
from django.contrib.auth import get_user_model
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.db.models import Model from django.db.models import Model
from django.db.models import Q from django.db.models import Q
@ -89,10 +90,27 @@ def _push_to_timeline(objects, instance:object, event_type:str, created_datetime
@app.task @app.task
def push_to_timelines(project, user, obj, event_type, created_datetime, extra_data={}): def push_to_timelines(project_id, user_id, obj_app_label, obj_model_name, obj_id, event_type, created_datetime, extra_data={}):
if project is not None: ObjModel = apps.get_model(obj_app_label, obj_model_name)
try:
obj = ObjModel.objects.get(id=obj_id)
except ObjModel.DoesNotExist:
return
try:
user = get_user_model().objects.get(id=user_id)
except get_user_model().DoesNotExist:
return
if project_id is not None:
# Actions related with a project # Actions related with a project
projectModel = apps.get_model("projects", "Project")
try:
project = projectModel.objects.get(id=project_id)
except projectModel.DoesNotExist:
return
## Project timeline ## Project timeline
_push_to_timeline(project, obj, event_type, created_datetime, _push_to_timeline(project, obj, event_type, created_datetime,
namespace=build_project_namespace(project), namespace=build_project_namespace(project),

View File

@ -18,6 +18,7 @@
from django.conf import settings from django.conf import settings
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.contrib.contenttypes.models import ContentType
from django.utils import timezone from django.utils import timezone
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
@ -29,11 +30,14 @@ from taiga.timeline.service import (push_to_timelines,
extract_user_info) extract_user_info)
def _push_to_timelines(*args, **kwargs): def _push_to_timelines(project, user, obj, event_type, created_datetime, extra_data={}):
project_id = None if project is None else project.id
ct = ContentType.objects.get_for_model(obj)
if settings.CELERY_ENABLED: if settings.CELERY_ENABLED:
push_to_timelines.delay(*args, **kwargs) push_to_timelines.delay(project_id, user.id, ct.app_label, ct.model, obj.id, event_type, created_datetime, extra_data=extra_data)
else: else:
push_to_timelines(*args, **kwargs) push_to_timelines(project_id, user.id, ct.app_label, ct.model, obj.id, event_type, created_datetime, extra_data=extra_data)
def _clean_description_fields(values_diff): def _clean_description_fields(values_diff):
@ -89,7 +93,7 @@ def on_new_history_entry(sender, instance, created, **kwargs):
_push_to_timelines(project, user, obj, event_type, created_datetime, extra_data=extra_data) _push_to_timelines(project, user, obj, event_type, created_datetime, extra_data=extra_data)
def create_membership_push_to_timeline(sender, instance, **kwargs): def create_membership_push_to_timeline(sender, instance, created, **kwargs):
""" """
Creating new membership with associated user. If the user is the project owner we don't Creating new membership with associated user. If the user is the project owner we don't
do anything because that info will be shown in created project timeline entry do anything because that info will be shown in created project timeline entry
@ -99,29 +103,10 @@ def create_membership_push_to_timeline(sender, instance, **kwargs):
""" """
# We shown in created project timeline entry # We shown in created project timeline entry
if not instance.pk and instance.user and instance.user != instance.project.owner: if created and instance.user and instance.user != instance.project.owner:
created_datetime = instance.created_at created_datetime = instance.created_at
_push_to_timelines(instance.project, instance.user, instance, "create", created_datetime) _push_to_timelines(instance.project, instance.user, instance, "create", created_datetime)
# Updating existing membership
elif instance.pk:
try:
prev_instance = sender.objects.get(pk=instance.pk)
if instance.user != prev_instance.user:
created_datetime = timezone.now()
# The new member
_push_to_timelines(instance.project, instance.user, instance, "create", created_datetime)
# If we are updating the old user is removed from project
if prev_instance.user:
_push_to_timelines(instance.project,
prev_instance.user,
prev_instance,
"delete",
created_datetime)
except sender.DoesNotExist:
# This happens with some tests, when a membership is created with a concrete id
pass
def delete_membership_push_to_timeline(sender, instance, **kwargs): def delete_membership_push_to_timeline(sender, instance, **kwargs):
if instance.user: if instance.user:

View File

@ -351,29 +351,6 @@ def test_update_wiki_page_timeline():
assert user_watcher_timeline[0].data["values_diff"]["slug"][1] == "test wiki page timeline updated" assert user_watcher_timeline[0].data["values_diff"]["slug"][1] == "test wiki page timeline updated"
def test_update_membership_timeline():
user_1 = factories.UserFactory.create()
user_2 = factories.UserFactory.create()
membership = factories.MembershipFactory.create(user=user_1)
membership.user = user_2
membership.save()
project_timeline = service.get_project_timeline(membership.project)
user_1_timeline = service.get_user_timeline(user_1)
user_2_timeline = service.get_user_timeline(user_2)
assert project_timeline[0].event_type == "projects.membership.delete"
assert project_timeline[0].data["project"]["id"] == membership.project.id
assert project_timeline[0].data["user"]["id"] == user_1.id
assert project_timeline[1].event_type == "projects.membership.create"
assert project_timeline[1].data["project"]["id"] == membership.project.id
assert project_timeline[1].data["user"]["id"] == user_2.id
assert user_1_timeline[0].event_type == "projects.membership.delete"
assert user_1_timeline[0].data["project"]["id"] == membership.project.id
assert user_1_timeline[0].data["user"]["id"] == user_1.id
assert user_2_timeline[0].event_type == "projects.membership.create"
assert user_2_timeline[0].data["project"]["id"] == membership.project.id
assert user_2_timeline[0].data["user"]["id"] == user_2.id
def test_delete_project_timeline(): def test_delete_project_timeline():
project = factories.ProjectFactory.create(name="test project timeline") project = factories.ProjectFactory.create(name="test project timeline")
user_watcher= factories.UserFactory() user_watcher= factories.UserFactory()
@ -534,9 +511,11 @@ def test_timeline_error_use_member_ids_instead_of_memberships_ids():
history_services.take_snapshot(user_story, user=member_user) history_services.take_snapshot(user_story, user=member_user)
user_timeline = service.get_profile_timeline(member_user) user_timeline = service.get_profile_timeline(member_user)
assert len(user_timeline) == 2
assert len(user_timeline) == 3
assert user_timeline[0].event_type == "userstories.userstory.create" assert user_timeline[0].event_type == "userstories.userstory.create"
assert user_timeline[1].event_type == "users.user.create" assert user_timeline[1].event_type == "projects.membership.create"
assert user_timeline[2].event_type == "users.user.create"
external_user_timeline = service.get_profile_timeline(external_user) external_user_timeline = service.get_profile_timeline(external_user)
assert len(external_user_timeline) == 1 assert len(external_user_timeline) == 1