1717)
1818from dve .core_engine .backends .base .core import get_entity_type
1919from dve .core_engine .backends .exceptions import render_error
20- from dve .core_engine .backends .metadata .reporting import ReportingConfig
2120from dve .core_engine .backends .metadata .rules import (
2221 AbstractStep ,
2322 Aggregation ,
3635 Notification ,
3736 OneToOneJoin ,
3837 OrphanIdentification ,
39- OrphanRemoval ,
4038 ParentMetadata ,
4139 RenameEntity ,
4240 Rule ,
4745)
4846from dve .core_engine .backends .types import Entities , EntityType , StageSuccessful
4947from dve .core_engine .configuration .v1 .hierarchy import EntityHierarchy , HierarchyNode
50- from dve .core_engine .constants import ORPHANED_RECORD_ENTITY_NAME
5148from dve .core_engine .exceptions import CriticalProcessingError
5249from dve .core_engine .loggers import get_logger
5350from dve .core_engine .message import FeedbackMessage
@@ -317,7 +314,7 @@ def join_header(self, entities: Entities, *, config: HeaderJoin) -> Messages:
317314 @abstractmethod
318315 def identify_orphans (
319316 self , entities : Entities , * , config : OrphanIdentification
320- ) -> tuple [ Messages , int ] :
317+ ) -> Iterable :
321318 """Identify records in an entity which don't have at least one corresponding
322319 match in the target. A new boolean column will be added to `entity` ('IsOrphaned')
323320 indicating whether the condition matched.
@@ -330,18 +327,6 @@ def identify_orphans(
330327 """
331328 raise NotImplementedError
332329
333- @abstractmethod
334- def remove_orphans (self , entities : Entities , * , config : OrphanRemoval ) -> Iterator :
335- """
336- Remove orphaned records from an entity based on the orphans found in
337- identify_orphans method. Returns a generator objects with the records removed
338- for generating feedback messages from.
339-
340- This may not be implemented by some backends.
341-
342- """
343- raise NotImplementedError
344-
345330 @abstractmethod
346331 def check_mandatory_group (self , entities : Entities , * , config : GroupIdentification ) -> Iterator :
347332 """
@@ -395,83 +380,60 @@ def identify_and_remove_orphans(
395380 Processes recursively: removes orphans at each level, then processes children.
396381 """
397382
398- def process_node (node : HierarchyNode ):
383+ def process_node (node : HierarchyNode ) -> bool :
399384 """Identify orphans and remove in a given node"""
400385 issues_found : bool = False
401386 if node .parent_entity is None :
402387 return issues_found
403388
404- self .logger .info (f"Identifying orphans in { node .entity_name } " )
389+ self .logger .info (f"Checking for orphan records in { node .entity_name } " )
405390
406391 join_expr = " AND " .join (
407392 f"{ node .parent_entity } .{ k } = { node .entity_name } .{ v } "
408393 for k , v in node .join_fields .items ()
409394 )
410-
411- _ , no_orphs = self .identify_orphans (
412- entities = entities ,
413- config = OrphanIdentification (
414- id = list (node .join_fields .values ())[0 ],
415- entity_name = node .entity_name ,
416- target_name = node .parent_entity ,
417- join_condition = join_expr ,
418- ),
419- )
420-
421- if no_orphs > 0 :
422- self .logger .info (f"Removing records with missing parent from { node .entity_name } " )
423- issues_found = True
424- location = list (node .join_fields .values ())[0 ]
425- with BackgroundMessageWriter (
426- working_directory = working_directory ,
427- dve_stage = self .__stage_name__ ,
428- key_fields = key_fields ,
429- logger = self .logger ,
430- ) as msg_writer :
431- _orph_records = self .remove_orphans (
432- entities = entities ,
433- config = OrphanRemoval (
434- entity_name = node .entity_name ,
435- reporting = ReportingConfig (
436- emit = "record_failure" ,
437- code = node .missing_parent_id_error_code ,
438- message = node .missing_parent_id_error_message ,
439- location = location ,
440- ),
395+ location = list (node .join_fields .values ())[0 ]
396+ with BackgroundMessageWriter (
397+ working_directory = working_directory ,
398+ dve_stage = self .__stage_name__ ,
399+ key_fields = key_fields ,
400+ logger = self .logger ,
401+ ) as msg_writer :
402+ _orph_records = self .identify_orphans (
403+ entities = entities ,
404+ config = OrphanIdentification (
405+ id = list (node .join_fields .values ())[0 ],
406+ entity_name = node .entity_name ,
407+ target_name = node .parent_entity ,
408+ join_condition = join_expr ,
409+ ),
410+ )
411+ _messages = [
412+ FeedbackMessage (
413+ entity = node .entity_name ,
414+ record = record , # type: ignore
415+ error_location = location ,
416+ error_message = template_object (
417+ node .missing_parent_id_error_message , record
441418 ),
419+ failure_type = "record" ,
420+ error_type = "record" ,
421+ error_code = node .missing_parent_id_error_code ,
422+ reporting_field = location ,
423+ category = "Parent Missing" ,
442424 )
443- # moved to batch the write - risky if large number of
444- msg_writer .write_queue .put (
445- [
446- FeedbackMessage (
447- entity = node .entity_name ,
448- record = record , # type: ignore
449- error_location = location ,
450- error_message = template_object (
451- node .missing_parent_id_error_message , record
452- ),
453- failure_type = "record" ,
454- error_type = "record" ,
455- error_code = node .missing_parent_id_error_code ,
456- reporting_field = location ,
457- category = "Parent Missing" ,
458- )
459- for record in _orph_records
460- ]
461- )
425+ for record in _orph_records
426+ ]
427+ msg_writer .write_queue .put (_messages )
462428
463- return issues_found
429+ return len ( _messages ) > 0
464430
465431 entity_issues_found : dict [EntityName , bool ] = {}
466432
467433 for tree in entity_hierarchy .entity_trees .values ():
468434 for node in tree .iterate_root_down ():
469435 entity_issues_found [node .entity_name ] = process_node (node )
470436
471- _orph_rel = entities .get (ORPHANED_RECORD_ENTITY_NAME )
472- if _orph_rel is not None :
473- del entities [ORPHANED_RECORD_ENTITY_NAME ]
474-
475437 entities .update (entities )
476438
477439 return [], entity_issues_found
0 commit comments