feat(translate,scheduler,trace): new-key-only mode, stale PENDING protection, trace_id propagation
Translations: - FR-045: new-key-only execution mode — translate only rows with unseen keys - Compare source row keys against TranslationRecord.source_data from last succeeded run - Baseline expired (>90 days) fallback to full mode with baseline_expired event - run_noop early return when zero new keys (skip LLM + SQL) Scheduler reliability: - Stale PENDING protection: runs older than 1h auto-marked FAILED, no longer block schedule - load_schedules() reloads active translation schedules from DB on restart - add_translation_job/remove_translation_job register/unregister with APScheduler - execution_mode column on translation_schedules with additive DB migration Automation view: - GET /settings/automation/translation-schedules endpoint - Translation schedules displayed on Automation page below validation policies Trace propagation: - seed_trace_id() in all background entry points: TaskManager._run_task/_flusher_loop, SchedulerService._trigger_backup, websocket_endpoint, IdMappingService, all standalone scripts Migrations: - dictionary_entries: origin_run_id, origin_row_key, origin_user_id - translation_schedules: execution_mode Tests: - 3 new test modules (22 tests): core_scheduler, executor_filter, scheduler_execution+guard - Fix pre-existing translate test isolation (conftest.py) - Fix test_list_runs_filter_status parameter
This commit is contained in:
@@ -10,6 +10,7 @@ import json
|
||||
from datetime import date, datetime, timezone
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
from ..core.cot_logger import seed_trace_id
|
||||
from ..models.clean_release import CandidateArtifact, ReleaseCandidate
|
||||
from ..services.clean_release.approval_service import (
|
||||
approve_candidate,
|
||||
@@ -468,6 +469,7 @@ def run_revoke(args: argparse.Namespace) -> int:
|
||||
# #region main [TYPE Function]
|
||||
# @BRIEF CLI entrypoint for clean release commands.
|
||||
def main(argv: Optional[List[str]] = None) -> int:
|
||||
seed_trace_id()
|
||||
parser = build_parser()
|
||||
args = parser.parse_args(argv)
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ BACKEND_ROOT = os.path.abspath(os.path.join(SCRIPT_DIR, "..", ".."))
|
||||
if BACKEND_ROOT not in sys.path:
|
||||
sys.path.insert(0, BACKEND_ROOT)
|
||||
|
||||
from src.core.cot_logger import seed_trace_id
|
||||
from src.models.clean_release import (
|
||||
CandidateArtifact,
|
||||
CheckFinalStatus,
|
||||
@@ -662,6 +663,7 @@ def tui_main(stdscr: curses.window):
|
||||
|
||||
|
||||
def main() -> int:
|
||||
seed_trace_id()
|
||||
# TUI requires interactive terminal; headless mode must use CLI/API flow.
|
||||
if not sys.stdout.isatty():
|
||||
print(
|
||||
|
||||
@@ -19,6 +19,7 @@ from src.core.database import AuthSessionLocal, init_db
|
||||
from src.core.auth.security import get_password_hash
|
||||
from src.models.auth import User, Role
|
||||
from src.core.logger import logger, belief_scope
|
||||
from src.core.cot_logger import seed_trace_id
|
||||
|
||||
|
||||
# #region create_admin [TYPE Function]
|
||||
@@ -27,6 +28,7 @@ from src.core.logger import logger, belief_scope
|
||||
# @POST: Admin user exists in auth.db.
|
||||
#
|
||||
def create_admin(username, password, email=None):
|
||||
seed_trace_id()
|
||||
with belief_scope("create_admin"):
|
||||
db = AuthSessionLocal()
|
||||
try:
|
||||
|
||||
@@ -17,6 +17,7 @@ sys.path.append(str(Path(__file__).parent.parent.parent))
|
||||
from src.core.database import init_db
|
||||
from src.core.encryption_key import ensure_encryption_key
|
||||
from src.core.logger import logger, belief_scope
|
||||
from src.core.cot_logger import seed_trace_id
|
||||
from src.scripts.seed_permissions import seed_permissions
|
||||
|
||||
|
||||
@@ -27,6 +28,7 @@ from src.scripts.seed_permissions import seed_permissions
|
||||
# @RELATION CALLS -> init_db
|
||||
# @RELATION CALLS -> seed_permissions
|
||||
def run_init():
|
||||
seed_trace_id()
|
||||
with belief_scope("init_auth_db"):
|
||||
logger.info("Initializing authentication database...")
|
||||
try:
|
||||
|
||||
@@ -21,6 +21,7 @@ from sqlalchemy import create_engine, text
|
||||
from sqlalchemy.exc import SQLAlchemyError
|
||||
|
||||
from src.core.logger import belief_scope, logger
|
||||
from src.core.cot_logger import seed_trace_id
|
||||
|
||||
|
||||
# #region Constants [TYPE Section]
|
||||
@@ -327,6 +328,7 @@ def _migrate_tasks_and_logs(engine, sqlite_conn: sqlite3.Connection) -> Dict[str
|
||||
def run_migration(
|
||||
sqlite_path: Path, target_url: str, legacy_config_path: Optional[Path]
|
||||
) -> Dict[str, int]:
|
||||
seed_trace_id()
|
||||
with belief_scope("run_migration"):
|
||||
logger.reason(
|
||||
f"sqlite={sqlite_path} target={target_url}",
|
||||
|
||||
@@ -19,6 +19,7 @@ from src.core.database import AuthSessionLocal
|
||||
from src.models.auth import Permission, Role
|
||||
from src.core.auth.repository import AuthRepository
|
||||
from src.core.logger import logger, belief_scope
|
||||
from src.core.cot_logger import seed_trace_id
|
||||
|
||||
# #region INITIAL_PERMISSIONS [C:3] [TYPE Constant]
|
||||
# @BRIEF Canonical bootstrap permission tuples seeded into auth storage.
|
||||
@@ -66,6 +67,7 @@ INITIAL_PERMISSIONS = [
|
||||
# @RELATION DEPENDS_ON -> AuthRepository
|
||||
# @RELATION DEPENDS_ON -> INITIAL_PERMISSIONS
|
||||
def seed_permissions():
|
||||
seed_trace_id()
|
||||
with belief_scope("seed_permissions"):
|
||||
db = AuthSessionLocal()
|
||||
try:
|
||||
|
||||
@@ -19,6 +19,7 @@ sys.path.append(str(Path(__file__).parent.parent.parent))
|
||||
from src.core.config_manager import ConfigManager
|
||||
from src.core.config_models import Environment
|
||||
from src.core.logger import belief_scope, logger
|
||||
from src.core.cot_logger import seed_trace_id
|
||||
from src.core.superset_client import SupersetClient
|
||||
|
||||
|
||||
@@ -255,6 +256,7 @@ def _build_chart_template_pool(
|
||||
# @POST: Returns execution statistics dictionary.
|
||||
# @SIDE_EFFECT: Creates objects in Superset environments.
|
||||
def seed_superset_load_data(args: argparse.Namespace) -> Dict:
|
||||
seed_trace_id()
|
||||
rng = random.Random(args.seed)
|
||||
env_map = _resolve_target_envs(args.envs)
|
||||
|
||||
@@ -381,6 +383,7 @@ def seed_superset_load_data(args: argparse.Namespace) -> Dict:
|
||||
# @PRE: Command line arguments are valid.
|
||||
# @POST: Prints summary and exits with non-zero status on failure.
|
||||
def main() -> None:
|
||||
seed_trace_id()
|
||||
with belief_scope("seed_superset_load_test.main"):
|
||||
args = _parse_args()
|
||||
result = seed_superset_load_data(args)
|
||||
|
||||
@@ -18,10 +18,12 @@ sys.path.append(str(Path(__file__).parent.parent.parent))
|
||||
from src.core.superset_client import SupersetClient
|
||||
from src.core.config_manager import ConfigManager
|
||||
from src.core.logger import logger
|
||||
from src.core.cot_logger import seed_trace_id
|
||||
|
||||
|
||||
def test_dashboard_dataset_relations():
|
||||
"""Test fetching dataset-to-dashboard relationships."""
|
||||
seed_trace_id()
|
||||
|
||||
# Load environment from existing config
|
||||
config_manager = ConfigManager()
|
||||
|
||||
Reference in New Issue
Block a user