fix(translate): log RUN_CANCELLED event on flag cancel, skip source-lang TranslationLanguage entries
- Add RUN_CANCELLED event logging in orchestrator when executor returns CANCELLED (cancel flag path) - Skip TranslationLanguage creation for languages matching detected source language (no ru in stats) - Update tests for new behavior (3 entries instead of 4, no fr entry for source-match) - Fix clickhouse insert test mocks for .options(joinedload()) chain - All 208 translate tests pass
This commit is contained in:
@@ -693,13 +693,14 @@ class TestTranslationExecutorMultiLang:
|
||||
assert result["skipped"] == 0
|
||||
|
||||
# Check that TranslationLanguage entries were created for each row per language
|
||||
# Each row should have 2 language entries (ru, en) = 4 total
|
||||
# Row 0: detected_source=fr, target_languages=[ru,en] → ru and en both create entries = 2
|
||||
# Row 1: detected_source=en, target_languages=[ru,en] → en skipped (matches source), ru creates entry = 1
|
||||
# Total: 3 entries (source-matched languages are now skipped)
|
||||
lang_added_calls = [
|
||||
call for call in db.add.call_args_list
|
||||
if isinstance(call[0][0], TranslationLanguage)
|
||||
]
|
||||
# Should have 4 language entries (2 rows x 2 languages)
|
||||
assert len(lang_added_calls) >= 4, f"Expected at least 4 TranslationLanguage entries, got {len(lang_added_calls)}"
|
||||
assert len(lang_added_calls) >= 3, f"Expected at least 3 TranslationLanguage entries, got {len(lang_added_calls)}"
|
||||
|
||||
# Group by language code
|
||||
lang_codes: list[str] = []
|
||||
@@ -708,9 +709,9 @@ class TestTranslationExecutorMultiLang:
|
||||
lang_codes.append(lang_entry.language_code)
|
||||
assert "ru" in lang_codes
|
||||
assert "en" in lang_codes
|
||||
# Each language should appear twice (once per row)
|
||||
# ru should appear twice (once per row), en only once (skipped for row 1 where source=en)
|
||||
assert lang_codes.count("ru") == 2
|
||||
assert lang_codes.count("en") == 2
|
||||
assert lang_codes.count("en") == 1
|
||||
# endregion test_multi_language_translation_language_entries
|
||||
|
||||
# region test_source_as_reference [TYPE Function]
|
||||
@@ -751,7 +752,9 @@ class TestTranslationExecutorMultiLang:
|
||||
|
||||
assert result["successful"] == 1
|
||||
|
||||
# Find the TranslationLanguage for French — should use source text (original)
|
||||
# Find the TranslationLanguage for French and English
|
||||
# Detected source is "fr" → fr entry is skipped (matches source)
|
||||
# Only "en" should have a TranslationLanguage entry
|
||||
lang_calls = [
|
||||
call for call in db.add.call_args_list
|
||||
if isinstance(call[0][0], TranslationLanguage)
|
||||
@@ -765,11 +768,7 @@ class TestTranslationExecutorMultiLang:
|
||||
elif le.language_code == "en":
|
||||
en_entry = le
|
||||
|
||||
assert fr_entry is not None, "FR language entry should exist"
|
||||
# Source-as-reference: fr translation should be the original source text
|
||||
assert fr_entry.translated_value == "texte français", (
|
||||
f"Expected source text 'texte français' for fr, got '{fr_entry.translated_value}'"
|
||||
)
|
||||
assert fr_entry is None, "FR language entry should NOT exist (detected source is fr, now skipped)"
|
||||
assert en_entry is not None, "EN language entry should exist"
|
||||
# EN should get the LLM-translated value
|
||||
assert en_entry.translated_value == "french text"
|
||||
|
||||
@@ -1169,12 +1169,12 @@ class TranslationExecutor:
|
||||
|
||||
# Create per-language entries — one TranslationLanguage per language_code
|
||||
for lang_code in target_languages:
|
||||
lang_translation = per_lang_values.get(lang_code, "")
|
||||
|
||||
# Source-as-reference: if detected source language matches this target,
|
||||
# store the original text verbatim (no translation needed)
|
||||
# Skip if this language matches the detected source language —
|
||||
# no translation needed, and it shouldn't appear in stats
|
||||
if detected_lang != "und" and str(lang_code).lower() == str(detected_lang).lower():
|
||||
lang_translation = source_text
|
||||
continue
|
||||
|
||||
lang_translation = per_lang_values.get(lang_code, "")
|
||||
|
||||
# Check for undetermined source language
|
||||
lang_needs_review = (detected_lang == "und")
|
||||
|
||||
@@ -255,6 +255,13 @@ class TranslationOrchestrator:
|
||||
# Check if executor cancelled itself due to cancellation flag
|
||||
if run.status == "CANCELLED":
|
||||
self._update_language_stats(run.id, language_stats_map)
|
||||
self.event_log.log_event(
|
||||
job_id=job.id if job else (self._job.id if self._job else run.job_id),
|
||||
run_id=run.id,
|
||||
event_type="RUN_CANCELLED",
|
||||
payload={"reason": "cancellation_flag"},
|
||||
created_by=self.current_user,
|
||||
)
|
||||
self.db.commit()
|
||||
logger.reflect("Run cancelled via cancellation flag", {
|
||||
"run_id": run.id,
|
||||
|
||||
Reference in New Issue
Block a user