Extract update_messages_for_topic_edit().

This is somewhat hairy logic, so it's nice
to extract it and not worry about variable leaks.

Also, this moves some legacy "subject" references out
of actions.py.
This commit is contained in:
Steve Howell 2018-11-01 18:55:14 +00:00 committed by Tim Abbott
parent 32232377f7
commit 0cf4cddc5b
2 changed files with 39 additions and 22 deletions

View File

@ -58,6 +58,7 @@ from zerver.lib.stream_topic import StreamTopicTarget
from zerver.lib.topic import ( from zerver.lib.topic import (
filter_by_exact_message_topic, filter_by_exact_message_topic,
filter_by_topic_name_via_message, filter_by_topic_name_via_message,
update_messages_for_topic_edit,
ORIG_TOPIC, ORIG_TOPIC,
PREV_TOPIC, PREV_TOPIC,
TOPIC_LINKS, TOPIC_LINKS,
@ -3969,27 +3970,12 @@ def do_update_message(user_profile: UserProfile, message: Message, topic_name: O
edit_history_event[PREV_TOPIC] = orig_topic_name edit_history_event[PREV_TOPIC] = orig_topic_name
if propagate_mode in ["change_later", "change_all"]: if propagate_mode in ["change_later", "change_all"]:
propagate_query = Q(recipient = message.recipient, subject = orig_topic_name) messages_list = update_messages_for_topic_edit(
# We only change messages up to 2 days in the past, to avoid hammering our message=message,
# DB by changing an unbounded amount of messages propagate_mode=propagate_mode,
if propagate_mode == 'change_all': orig_topic_name=orig_topic_name,
before_bound = timezone_now() - datetime.timedelta(days=2) topic_name=topic_name,
)
propagate_query = (propagate_query & ~Q(id = message.id) &
Q(pub_date__range=(before_bound, timezone_now())))
if propagate_mode == 'change_later':
propagate_query = propagate_query & Q(id__gt = message.id)
messages = Message.objects.filter(propagate_query).select_related()
# Evaluate the query before running the update
messages_list = list(messages)
messages.update(subject=topic_name)
for m in messages_list:
# The cached ORM object is not changed by messages.update()
# and the remote cache update requires the new value
m.set_topic_name(topic_name)
changed_messages += messages_list changed_messages += messages_list

View File

@ -1,5 +1,8 @@
import datetime
from django.db import connection from django.db import connection
from django.db.models.query import QuerySet from django.db.models.query import QuerySet, Q
from django.utils.timezone import now as timezone_now
from zerver.models import ( from zerver.models import (
Message, Message,
@ -22,6 +25,34 @@ def filter_by_exact_message_topic(query: QuerySet, message: Message) -> QuerySet
def filter_by_topic_name_via_message(query: QuerySet, topic_name: str) -> QuerySet: def filter_by_topic_name_via_message(query: QuerySet, topic_name: str) -> QuerySet:
return query.filter(message__subject__iexact=topic_name) return query.filter(message__subject__iexact=topic_name)
def update_messages_for_topic_edit(message: Message,
propagate_mode: str,
orig_topic_name: str,
topic_name: str) -> List[Message]:
propagate_query = Q(recipient = message.recipient, subject = orig_topic_name)
# We only change messages up to 2 days in the past, to avoid hammering our
# DB by changing an unbounded amount of messages
if propagate_mode == 'change_all':
before_bound = timezone_now() - datetime.timedelta(days=2)
propagate_query = (propagate_query & ~Q(id = message.id) &
Q(pub_date__range=(before_bound, timezone_now())))
if propagate_mode == 'change_later':
propagate_query = propagate_query & Q(id__gt = message.id)
messages = Message.objects.filter(propagate_query).select_related()
# Evaluate the query before running the update
messages_list = list(messages)
messages.update(subject=topic_name)
for m in messages_list:
# The cached ORM object is not changed by messages.update()
# and the remote cache update requires the new value
m.set_topic_name(topic_name)
return messages_list
def generate_topic_history_from_db_rows(rows: List[Tuple[str, int]]) -> List[Dict[str, Any]]: def generate_topic_history_from_db_rows(rows: List[Tuple[str, int]]) -> List[Dict[str, Any]]:
canonical_topic_names = {} # type: Dict[str, Tuple[int, str]] canonical_topic_names = {} # type: Dict[str, Tuple[int, str]]