Trace pipeline pool isolation: - Switch event_fetcher and lineage_engine to read_sql_df_slow (non-pooled) - Reduce EVENT_FETCHER_MAX_WORKERS 4→2, TRACE_EVENTS_MAX_WORKERS 4→2 - Add 60s timeout per batch query, cache skip for CID>10K - Early del raw_domain_results + gc.collect() for large queries - Increase DB_SLOW_MAX_CONCURRENT: base 3→5, dev 2→3, prod 3→5 Test fixes (51 pre-existing failures → 0): - reject_history: WORKFLOW CSV header, strict bool validation, pareto mock path - portal shell: remove non-existent /tmtt-defect route from tests - conftest: add --run-stress option to skip stress/load tests by default - migration tests: skipif baseline directory missing - performance test: update Vite asset assertion - wip hold: add firstname/waferdesc mock params - template integration: add /reject-history canonical route Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
4.6 KiB
lineage-engine-core Specification
Purpose
TBD - created by archiving change unified-lineage-engine. Update Purpose after archive.
Requirements
Requirement: LineageEngine SHALL provide unified split ancestor resolution via CONNECT BY NOCYCLE
LineageEngine.resolve_split_ancestors() SHALL accept a list of container IDs and return the complete split ancestry graph using a single Oracle CONNECT BY NOCYCLE query on DW_MES_CONTAINER.SPLITFROMID.
Scenario: Normal split chain resolution
- WHEN
resolve_split_ancestors()is called with a list of container IDs - THEN a single SQL query using
CONNECT BY NOCYCLESHALL be executed againstDW_MES_CONTAINER - THEN the result SHALL include a
child_to_parentmapping and acid_to_namemapping for all discovered ancestor nodes - THEN the traversal depth SHALL be limited to
LEVEL <= 20(equivalent to existing BFSbfs_round > 20guard)
Scenario: Large input batch exceeding Oracle IN clause limit
- WHEN the input
container_idslist exceedsORACLE_IN_BATCH_SIZE(1000) - THEN
QueryBuilder.add_in_condition()SHALL batch the IDs and combine results - THEN all bind parameters SHALL use
QueryBuilder.params(no string concatenation)
Scenario: Cyclic split references in data
- WHEN
DW_MES_CONTAINER.SPLITFROMIDcontains cyclic references - THEN
NOCYCLESHALL prevent infinite traversal - THEN the query SHALL return all non-cyclic ancestors up to
LEVEL <= 20
Scenario: CONNECT BY performance regression
- WHEN Oracle 19c execution plan for
CONNECT BY NOCYCLEperforms worse than expected - THEN the SQL file SHALL contain a commented-out recursive
WITH(recursive subquery factoring) alternative that can be swapped in without code changes
Requirement: LineageEngine SHALL provide unified merge source resolution
LineageEngine.resolve_merge_sources() SHALL accept a list of container IDs and return merge source mappings from DW_MES_PJ_COMBINEDASSYLOTS.
Scenario: Merge source lookup
- WHEN
resolve_merge_sources()is called with container IDs - THEN the result SHALL include
{cid: [merge_source_cid, ...]}for all containers that have merge sources - THEN all queries SHALL use
QueryBuilderbind params
Requirement: LineageEngine SHALL provide combined genealogy resolution
LineageEngine.resolve_full_genealogy() SHALL combine split ancestors and merge sources into a complete genealogy graph.
Scenario: Full genealogy for a set of seed lots
- WHEN
resolve_full_genealogy()is called with seed container IDs - THEN split ancestors SHALL be resolved first via
resolve_split_ancestors() - THEN merge sources SHALL be resolved for all discovered ancestor nodes
- THEN the combined result SHALL be equivalent to the existing
_resolve_full_genealogy()output inmid_section_defect_service.py
Requirement: LineageEngine functions SHALL be profile-agnostic
All LineageEngine public functions SHALL accept container_ids: List[str] and return dictionary structures without binding to any specific page logic.
Scenario: Reuse from different pages
- WHEN a new page (e.g., wip-detail) needs lineage resolution
- THEN it SHALL be able to call
LineageEnginefunctions directly without modification - THEN no page-specific logic (profile, TMTT detection, etc.) SHALL exist in
LineageEngine
Requirement: LineageEngine SQL files SHALL reside in sql/lineage/ directory
New SQL files SHALL follow the existing SQLLoader convention under src/mes_dashboard/sql/lineage/.
Scenario: SQL file organization
- WHEN
LineageEngineexecutes queries - THEN
split_ancestors.sqlandmerge_sources.sqlSHALL be loaded viaSQLLoader.load_with_params("lineage/split_ancestors", ...) - THEN the SQL files SHALL NOT reference
HM_LOTMOVEOUT(48M row table no longer needed for genealogy)
Requirement: LineageEngine SHALL use non-pooled database connections
All Oracle queries executed by LineageEngine SHALL use read_sql_df_slow() (dedicated non-pooled connections) instead of read_sql_df() (connection pool).
Scenario: Lineage query does not consume pool connections
- WHEN
LineageEngineexecutes split ancestor, merge source, or other Oracle queries - THEN queries SHALL use
read_sql_df_slow()with the default slow query timeout (300s) - THEN the shared connection pool SHALL NOT be consumed by lineage queries
Scenario: Lineage queries respect slow query semaphore
- WHEN
LineageEngineexecutes queries viaread_sql_df_slow() - THEN each query SHALL acquire and release a slot from the slow query semaphore (
DB_SLOW_MAX_CONCURRENT)