From f5f3cff2344cbf8d4e06571881fa2250e579e2ea Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Wed, 29 Apr 2015 10:19:34 +0200 Subject: [PATCH] Improving timeline migration and regeneration --- taiga/timeline/management/__init__.py | 0 .../management/commands/rebuild_timeline.py | 87 +++++++++++++++++++ .../migrations/0002_auto_20150327_1056.py | 71 +-------------- 3 files changed, 89 insertions(+), 69 deletions(-) create mode 100644 taiga/timeline/management/__init__.py create mode 100644 taiga/timeline/management/commands/rebuild_timeline.py diff --git a/taiga/timeline/management/__init__.py b/taiga/timeline/management/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/taiga/timeline/management/commands/rebuild_timeline.py b/taiga/timeline/management/commands/rebuild_timeline.py new file mode 100644 index 00000000..aef51194 --- /dev/null +++ b/taiga/timeline/management/commands/rebuild_timeline.py @@ -0,0 +1,87 @@ +# Copyright (C) 2014 Andrey Antukh +# Copyright (C) 2014 Jesús Espino +# Copyright (C) 2014 David Barragán +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +from django.core.exceptions import ObjectDoesNotExist +from django.core.management.base import BaseCommand +from django.db.models import Model + +from taiga.projects.models import Project +from taiga.projects.history import services as history_services +from taiga.projects.history.choices import HistoryType +from taiga.projects.history.models import HistoryEntry +from taiga.timeline.models import Timeline +from taiga.timeline.service import (_add_to_object_timeline, _get_impl_key_from_model, + _timeline_impl_map, extract_user_info) +from taiga.timeline.signals import on_new_history_entry, _push_to_timelines +from taiga.users.models import User + +from unittest.mock import patch +from django.contrib.contenttypes.models import ContentType + +timelime_objects = [] +created = None + +def custom_add_to_object_timeline(obj:object, instance:object, event_type:str, namespace:str="default", extra_data:dict={}): + global created + global timelime_objects + assert isinstance(obj, Model), "obj must be a instance of Model" + assert isinstance(instance, Model), "instance must be a instance of Model" + event_type_key = _get_impl_key_from_model(instance.__class__, event_type) + impl = _timeline_impl_map.get(event_type_key, None) + + timelime_objects.append(Timeline( + content_object=obj, + namespace=namespace, + event_type=event_type_key, + project=instance.project, + data=impl(instance, extra_data=extra_data), + data_content_type = ContentType.objects.get_for_model(instance.__class__), + created = created, + )) + + +def generate_timeline(): + global created + global timelime_objects + with patch('taiga.timeline.service._add_to_object_timeline', new=custom_add_to_object_timeline): + # Projects api wasn't a HistoryResourceMixin so we can't interate on the HistoryEntries in this case + for project in Project.objects.order_by("created_date").iterator(): + created = project.created_date + print("Project:", created) + extra_data = { + "values_diff": {}, + "user": extract_user_info(project.owner), + } + _push_to_timelines(project, project.owner, project, "create", extra_data=extra_data) + + Timeline.objects.bulk_create(timelime_objects, batch_size=10000) + timelime_objects = [] + + for historyEntry in HistoryEntry.objects.order_by("created_at").iterator(): + print("History entry:", historyEntry.created_at) + try: + created = historyEntry.created_at + on_new_history_entry(None, historyEntry, None) + except ObjectDoesNotExist as e: + print("Ignoring") + + Timeline.objects.bulk_create(timelime_objects, batch_size=10000) + + +class Command(BaseCommand): + def handle(self, *args, **options): + Timeline.objects.all().delete() + generate_timeline() diff --git a/taiga/timeline/migrations/0002_auto_20150327_1056.py b/taiga/timeline/migrations/0002_auto_20150327_1056.py index c1c67365..6c8a2066 100644 --- a/taiga/timeline/migrations/0002_auto_20150327_1056.py +++ b/taiga/timeline/migrations/0002_auto_20150327_1056.py @@ -3,74 +3,8 @@ from __future__ import unicode_literals from django.db import models, migrations -from django.core.exceptions import ObjectDoesNotExist -from django.db.models import Model - -from taiga.projects.models import Project -from taiga.projects.history import services as history_services -from taiga.projects.history.choices import HistoryType -from taiga.projects.history.models import HistoryEntry -from taiga.timeline.models import Timeline -from taiga.timeline.service import (_add_to_object_timeline, _get_impl_key_from_model, - _timeline_impl_map, extract_user_info) -from taiga.timeline.signals import on_new_history_entry, _push_to_timelines -from taiga.users.models import User - -from unittest.mock import patch -from django.contrib.contenttypes.models import ContentType - import django_pgjson.fields -import django.utils.timezone - - -timelime_objects = [] -created = None - -def custom_add_to_object_timeline(obj:object, instance:object, event_type:str, namespace:str="default", extra_data:dict={}): - global created - global timelime_objects - assert isinstance(obj, Model), "obj must be a instance of Model" - assert isinstance(instance, Model), "instance must be a instance of Model" - event_type_key = _get_impl_key_from_model(instance.__class__, event_type) - impl = _timeline_impl_map.get(event_type_key, None) - - timelime_objects.append(Timeline( - content_object=obj, - namespace=namespace, - event_type=event_type_key, - project=instance.project, - data=impl(instance, extra_data=extra_data), - data_content_type = ContentType.objects.get_for_model(instance.__class__), - created = created, - )) - - -def generate_timeline(apps, schema_editor): - global created - global timelime_objects - with patch('taiga.timeline.service._add_to_object_timeline', new=custom_add_to_object_timeline): - # Projects api wasn't a HistoryResourceMixin so we can't interate on the HistoryEntries in this case - for project in Project.objects.order_by("created_date").iterator(): - created = project.created_date - print("Project:", created) - extra_data = { - "values_diff": {}, - "user": extract_user_info(project.owner), - } - _push_to_timelines(project, project.owner, project, "create", extra_data=extra_data) - - Timeline.objects.bulk_create(timelime_objects, batch_size=10000) - timelime_objects = [] - - for historyEntry in HistoryEntry.objects.order_by("created_at").iterator(): - print("History entry:", historyEntry.created_at) - try: - created = historyEntry.created_at - on_new_history_entry(None, historyEntry, None) - except ObjectDoesNotExist as e: - print("Ignoring") - - Timeline.objects.bulk_create(timelime_objects, batch_size=10000) +from django.utils import timezone class Migration(migrations.Migration): @@ -95,7 +29,7 @@ class Migration(migrations.Migration): ('project', models.ForeignKey(to='projects.Project')), ('data', django_pgjson.fields.JsonField()), ('data_content_type', models.ForeignKey(to='contenttypes.ContentType', related_name='data_timelines')), - ('created', models.DateTimeField(default=django.utils.timezone.now)), + ('created', models.DateTimeField(default=timezone.now)), ('content_type', models.ForeignKey(to='contenttypes.ContentType', related_name='content_type_timelines')), ], options={ @@ -106,5 +40,4 @@ class Migration(migrations.Migration): name='timeline', index_together=set([('content_type', 'object_id', 'namespace')]), ), - migrations.RunPython(generate_timeline), ]