@@ -374,16 +374,12 @@ def auto_publish_composites!(component_task_id)
374374 when :scheduled
375375 Rails . logger . info ( "Composite CV #{ composite_cv . name } publish already scheduled, skipping duplicate" )
376376 next
377- when :running
378- # A composite publish is currently running - we need to schedule another one
379- # after it finishes to include this new component version
380- Rails . logger . info ( "Composite CV #{ composite_cv . name } publish running, scheduling event for retry " )
381- schedule_auto_publish_event ( composite_cv , description )
377+ when :running , nil
378+ # Either composite is running or no composite activity detected
379+ # Schedule event to trigger composite publish with proper coordination
380+ Rails . logger . info ( "Composite CV #{ composite_cv . name } scheduling auto-publish event " )
381+ schedule_auto_publish_event ( composite_cv , description , component_task_id )
382382 next
383- when nil
384- # No composite publish running or scheduled - trigger one now
385- sibling_task_ids = find_sibling_component_publish_tasks ( composite_cv , component_task_id )
386- trigger_composite_publish ( composite_cv , sibling_task_ids , description )
387383 end
388384 end
389385 end
@@ -411,9 +407,9 @@ def composite_publish_status(composite_cv)
411407 end
412408
413409 # Schedule an event to retry composite publish after current one finishes
414- def schedule_auto_publish_event ( composite_cv , description )
410+ def schedule_auto_publish_event ( composite_cv , description , component_task_id )
415411 ::Katello ::EventQueue . push_event ( ::Katello ::Events ::AutoPublishCompositeView ::EVENT_TYPE , composite_cv . id ) do |attrs |
416- attrs [ :metadata ] = { description : description , version_id : self . id }
412+ attrs [ :metadata ] = { description : description , version_id : self . id , calling_task_id : component_task_id }
417413 end
418414 end
419415
@@ -429,65 +425,55 @@ def scheduled_task_for_composite?(task, composite_cv)
429425 false
430426 end
431427
432- # Trigger a composite publish, either immediately or chained to sibling tasks
433- def trigger_composite_publish ( composite_cv , sibling_task_ids , description )
434- if sibling_task_ids . any?
435- trigger_chained_composite_publish ( composite_cv , sibling_task_ids , description )
436- else
437- trigger_immediate_composite_publish ( composite_cv , description )
438- end
428+ # Trigger a composite publish with coordination for sibling tasks.
429+ # Checks for running component CV publishes and chains if necessary.
430+ def self . trigger_composite_publish_with_coordination ( composite_cv , description , triggered_by_version_id , calling_task_id : nil )
431+ # Find currently running component CV publish tasks
432+ component_cv_ids = composite_cv . components . pluck ( :content_view_id )
433+ running_tasks = ForemanTasks ::Task ::DynflowTask
434+ . for_action ( ::Actions ::Katello ::ContentView ::Publish )
435+ . where ( state : [ 'planning' , 'planned' , 'running' ] )
436+ . select do |task |
437+ task_input = task . input
438+ task_input && component_cv_ids . include? ( task_input . dig ( 'content_view' , 'id' ) )
439+ end
440+
441+ sibling_task_ids = running_tasks . map ( &:external_id )
442+ # Exclude current task if provided (when called from auto_publish_composites!)
443+ sibling_task_ids . reject! { |id | id == calling_task_id } if calling_task_id
444+
445+ trigger_publish_with_sibling_tasks ( composite_cv , sibling_task_ids , description , triggered_by_version_id )
439446 rescue ForemanTasks ::Lock ::LockConflict => e
440447 Rails . logger . info ( "Composite CV #{ composite_cv . name } publish lock conflict: #{ e . class } - #{ e . message } " )
441448 ::Katello ::UINotifications ::ContentView ::AutoPublishFailure . deliver! ( composite_cv )
449+ raise
442450 rescue StandardError => e
443451 Rails . logger . error ( "Failed to auto-publish composite CV #{ composite_cv . name } : #{ e . class } - #{ e . message } " )
444452 Rails . logger . debug ( e . backtrace . join ( "\n " ) ) if e . backtrace
445453 ::Katello ::UINotifications ::ContentView ::AutoPublishFailure . deliver! ( composite_cv )
446454 raise
447455 end
448456
449- # Trigger a chained composite publish that waits for sibling tasks
450- def trigger_chained_composite_publish ( composite_cv , sibling_task_ids , description )
451- ForemanTasks . dynflow . world . chain (
452- sibling_task_ids ,
453- ::Actions ::Katello ::ContentView ::Publish ,
454- composite_cv ,
455- description ,
456- triggered_by_id : self . id
457- )
458- end
459-
460- # Trigger an immediate composite publish
461- def trigger_immediate_composite_publish ( composite_cv , description )
462- ForemanTasks . async_task (
463- ::Actions ::Katello ::ContentView ::Publish ,
464- composite_cv ,
465- description ,
466- triggered_by_id : self . id
467- )
457+ # Trigger a composite publish, chaining to sibling tasks if any exist
458+ def self . trigger_publish_with_sibling_tasks ( composite_cv , sibling_task_ids , description , triggered_by_version_id )
459+ if sibling_task_ids . any?
460+ ForemanTasks . dynflow . world . chain (
461+ sibling_task_ids ,
462+ ::Actions ::Katello ::ContentView ::Publish ,
463+ composite_cv ,
464+ description ,
465+ triggered_by_id : triggered_by_version_id
466+ )
467+ else
468+ ForemanTasks . async_task (
469+ ::Actions ::Katello ::ContentView ::Publish ,
470+ composite_cv ,
471+ description ,
472+ triggered_by_id : triggered_by_version_id
473+ )
474+ end
468475 end
469476
470- # Find sibling component publish tasks that should be waited for
471- def find_sibling_component_publish_tasks ( composite_cv , current_task_id )
472- # Get all component CV IDs for this composite
473- component_cv_ids = composite_cv . components . pluck ( :content_view_id )
474-
475- # Find all currently running publish tasks for these component CVs
476- running_tasks = ForemanTasks ::Task ::DynflowTask
477- . for_action ( ::Actions ::Katello ::ContentView ::Publish )
478- . where ( state : [ 'planning' , 'planned' , 'running' ] )
479- . select do |task |
480- # Check if task is publishing one of the component CVs
481- task_input = task . input
482- task_input && component_cv_ids . include? ( task_input . dig ( 'content_view' , 'id' ) )
483- end
484-
485- task_ids = running_tasks . map ( &:external_id )
486-
487- # Exclude the current task - if we're running this code, the current task
488- # has already reached its Finalize step and doesn't need to be waited for
489- task_ids . reject { |id | id == current_task_id }
490- end
491477
492478 # Find active (planning/planned/running) composite publish tasks (does NOT check scheduled tasks)
493479 def find_active_composite_publish_tasks ( composite_cv )
0 commit comments