Skip to content

Commit

Permalink
fix(translation): move completion detection from task
Browse files Browse the repository at this point in the history
Doing that in task makes it subject to race condition - if translation
is completed before previous tasks are handled, the completed event is
fired multiple times. Doing the check at the end of transaction makes it
both faster and more reliable.

Fixes #12638
  • Loading branch information
nijel committed Oct 1, 2024
1 parent e6753be commit 5cc41c9
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 25 deletions.
18 changes: 18 additions & 0 deletions weblate/trans/models/translation.py
Original file line number Diff line number Diff line change
Expand Up @@ -1318,6 +1318,24 @@ def invalidate_cache(self) -> None:
self._invalidate_scheduled = True
transaction.on_commit(self._invalidate_triger)

def detect_completed_translation(self, change: Change, old_translated: int) -> None:
translated = self.stats.translated
if old_translated < translated and translated == self.stats.all:
self.change_set.create(
action=Change.ACTION_COMPLETE,
user=change.user,
author=change.author,
)

# check if component is fully translated
component = self.component
if component.stats.translated == component.stats.all:
self.component.change_set.create(
action=Change.ACTION_COMPLETED_COMPONENT,
user=change.user,
author=change.author,
)

@property
def keys_cache_key(self) -> str:
return f"translation-keys-{self.pk}"
Expand Down
11 changes: 8 additions & 3 deletions weblate/trans/models/unit.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from __future__ import annotations

import re
from functools import partial
from typing import TYPE_CHECKING, Any, TypedDict

import sentry_sdk
Expand Down Expand Up @@ -1095,8 +1096,6 @@ def save_backend(
This should be always called in a transaction with updated unit
locked for update.
"""
from weblate.trans.tasks import detect_completed_translation

# For case when authorship specified, use user
author = author or user

Expand Down Expand Up @@ -1158,7 +1157,13 @@ def save_backend(
self.translation.invalidate_cache()

# Postpone completed translation detection
detect_completed_translation.delay_on_commit(change.pk, old_translated)
transaction.on_commit(
partial(
self.translation.detect_completed_translation,
change,
old_translated,
)
)

# Update user stats
change.author.profile.increase_count("translated")
Expand Down
22 changes: 0 additions & 22 deletions weblate/trans/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -692,28 +692,6 @@ def cleanup_project_backup_download() -> None:
staticfiles_storage.delete(full_name)


@app.task(trail=False)
def detect_completed_translation(change_id: int, old_translated: int) -> None:
change = Change.objects.get(pk=change_id)

translated = change.translation.stats.translated
if old_translated < translated and translated == change.translation.stats.all:
change.translation.change_set.create(
action=Change.ACTION_COMPLETE,
user=change.user,
author=change.author,
)

# check if component is fully translated
component = change.translation.component
if component.stats.translated == component.stats.all:
change.translation.component.change_set.create(
action=Change.ACTION_COMPLETED_COMPONENT,
user=change.user,
author=change.author,
)


@app.on_after_finalize.connect
def setup_periodic_tasks(sender, **kwargs) -> None:
sender.add_periodic_task(3600, commit_pending.s(), name="commit-pending")
Expand Down

0 comments on commit 5cc41c9

Please sign in to comment.