- frontend: add to reload job data on param change after goto - frontend: set existingJob from createJob response for immediate tabs - frontend: suppress error toasts for schedule 404 (normal state) - frontend: conditional ScheduleConfig mount to avoid 'new' job loading - backend: skip preview check for jobs with direct Superset datasource - backend: add orthogonal test for datasource+no-preview success case
62 lines
2.5 KiB
Python
62 lines
2.5 KiB
Python
# #region validate_job_preconditions [C:3] [TYPE Function] [SEMANTICS validation, preconditions, translate]
|
|
# @BRIEF Validate preconditions before starting a translation run.
|
|
# @PRE Job exists and db session is valid.
|
|
# @POST Raises ValueError if any precondition fails.
|
|
# @RELATION DEPENDS_ON -> [TranslationJob]
|
|
def validate_job_preconditions(
|
|
job,
|
|
db_session,
|
|
is_scheduled: bool = False,
|
|
) -> None:
|
|
"""Validate preconditions before starting a translation run.
|
|
|
|
Args:
|
|
job: TranslationJob instance.
|
|
db_session: SQLAlchemy Session for querying preview sessions.
|
|
is_scheduled: Whether this is a scheduled (vs manual) run.
|
|
|
|
Raises:
|
|
ValueError: If any precondition fails.
|
|
"""
|
|
if job.status in ("DRAFT",):
|
|
raise ValueError(
|
|
f"Cannot run job '{job.id}' in status '{job.status}'. "
|
|
f"Job must be READY, ACTIVE, or COMPLETED."
|
|
)
|
|
if not job.target_table:
|
|
raise ValueError(
|
|
f"Job '{job.id}' has no target table configured. "
|
|
"Configure a target table before running."
|
|
)
|
|
if not job.provider_id:
|
|
raise ValueError(
|
|
f"Job '{job.id}' has no LLM provider configured. "
|
|
"Select an LLM provider before running."
|
|
)
|
|
if not job.translation_column:
|
|
raise ValueError(
|
|
f"Job '{job.id}' has no translation column configured. "
|
|
"Select a translation column before running."
|
|
)
|
|
if not is_scheduled:
|
|
# Jobs with a direct Superset datasource can fetch rows from Superset directly
|
|
# (see RunSourceFetcher.fetch_source_rows), so they don't need a preview session.
|
|
# Only require an accepted preview for jobs without a configured datasource.
|
|
if not bool(job.source_datasource_id):
|
|
from ...models.translate import TranslationPreviewSession
|
|
accepted_session = (
|
|
db_session.query(TranslationPreviewSession)
|
|
.filter(
|
|
TranslationPreviewSession.job_id == job.id,
|
|
TranslationPreviewSession.status == "APPLIED",
|
|
)
|
|
.order_by(TranslationPreviewSession.created_at.desc())
|
|
.first()
|
|
)
|
|
if not accepted_session:
|
|
raise ValueError(
|
|
f"Job '{job.id}' has no accepted preview session. "
|
|
"Run and accept a preview before executing a manual translation run."
|
|
)
|
|
# #endregion validate_job_preconditions
|