@@ -27,6 +27,7 @@ import (
27
27
buildBean "github.com/devtron-labs/devtron/pkg/build/pipeline/bean"
28
28
repository2 "github.com/devtron-labs/devtron/pkg/cluster/environment/repository"
29
29
eventProcessorBean "github.com/devtron-labs/devtron/pkg/eventProcessor/bean"
30
+ "github.com/devtron-labs/devtron/pkg/pipeline/adapter"
30
31
"github.com/devtron-labs/devtron/pkg/pipeline/constants"
31
32
"github.com/devtron-labs/devtron/pkg/pipeline/workflowStatus"
32
33
"regexp"
@@ -76,56 +77,59 @@ type CiHandler interface {
76
77
}
77
78
78
79
type CiHandlerImpl struct {
79
- Logger * zap.SugaredLogger
80
- ciPipelineMaterialRepository pipelineConfig.CiPipelineMaterialRepository
81
- ciService CiService
82
- gitSensorClient gitSensor.Client
83
- ciWorkflowRepository pipelineConfig.CiWorkflowRepository
84
- ciArtifactRepository repository.CiArtifactRepository
85
- userService user.UserService
86
- eventClient client.EventClient
87
- eventFactory client.EventFactory
88
- ciPipelineRepository pipelineConfig.CiPipelineRepository
89
- appListingRepository repository.AppListingRepository
90
- cdPipelineRepository pipelineConfig.PipelineRepository
91
- enforcerUtil rbac.EnforcerUtil
92
- resourceGroupService resourceGroup.ResourceGroupService
93
- envRepository repository2.EnvironmentRepository
94
- imageTaggingService imageTagging.ImageTaggingService
95
- customTagService CustomTagService
96
- appWorkflowRepository appWorkflow.AppWorkflowRepository
97
- config * types.CiConfig
98
- k8sCommonService k8sPkg.K8sCommonService
99
- workFlowStageStatusService workflowStatus.WorkFlowStageStatusService
80
+ Logger * zap.SugaredLogger
81
+ ciPipelineMaterialRepository pipelineConfig.CiPipelineMaterialRepository
82
+ ciService CiService
83
+ gitSensorClient gitSensor.Client
84
+ ciWorkflowRepository pipelineConfig.CiWorkflowRepository
85
+ ciArtifactRepository repository.CiArtifactRepository
86
+ userService user.UserService
87
+ eventClient client.EventClient
88
+ eventFactory client.EventFactory
89
+ ciPipelineRepository pipelineConfig.CiPipelineRepository
90
+ appListingRepository repository.AppListingRepository
91
+ cdPipelineRepository pipelineConfig.PipelineRepository
92
+ enforcerUtil rbac.EnforcerUtil
93
+ resourceGroupService resourceGroup.ResourceGroupService
94
+ envRepository repository2.EnvironmentRepository
95
+ imageTaggingService imageTagging.ImageTaggingService
96
+ customTagService CustomTagService
97
+ appWorkflowRepository appWorkflow.AppWorkflowRepository
98
+ config * types.CiConfig
99
+ k8sCommonService k8sPkg.K8sCommonService
100
+ workFlowStageStatusService workflowStatus.WorkFlowStageStatusService
101
+ workflowStatusLatestRepository pipelineConfig.WorkflowStatusLatestRepository
100
102
}
101
103
102
104
func NewCiHandlerImpl (Logger * zap.SugaredLogger , ciService CiService , ciPipelineMaterialRepository pipelineConfig.CiPipelineMaterialRepository , gitSensorClient gitSensor.Client , ciWorkflowRepository pipelineConfig.CiWorkflowRepository ,
103
105
ciArtifactRepository repository.CiArtifactRepository , userService user.UserService , eventClient client.EventClient , eventFactory client.EventFactory , ciPipelineRepository pipelineConfig.CiPipelineRepository ,
104
106
appListingRepository repository.AppListingRepository , cdPipelineRepository pipelineConfig.PipelineRepository , enforcerUtil rbac.EnforcerUtil , resourceGroupService resourceGroup.ResourceGroupService , envRepository repository2.EnvironmentRepository ,
105
107
imageTaggingService imageTagging.ImageTaggingService , k8sCommonService k8sPkg.K8sCommonService , appWorkflowRepository appWorkflow.AppWorkflowRepository , customTagService CustomTagService ,
106
108
workFlowStageStatusService workflowStatus.WorkFlowStageStatusService ,
109
+ workflowStatusLatestRepository pipelineConfig.WorkflowStatusLatestRepository ,
107
110
) * CiHandlerImpl {
108
111
cih := & CiHandlerImpl {
109
- Logger : Logger ,
110
- ciService : ciService ,
111
- ciPipelineMaterialRepository : ciPipelineMaterialRepository ,
112
- gitSensorClient : gitSensorClient ,
113
- ciWorkflowRepository : ciWorkflowRepository ,
114
- ciArtifactRepository : ciArtifactRepository ,
115
- userService : userService ,
116
- eventClient : eventClient ,
117
- eventFactory : eventFactory ,
118
- ciPipelineRepository : ciPipelineRepository ,
119
- appListingRepository : appListingRepository ,
120
- cdPipelineRepository : cdPipelineRepository ,
121
- enforcerUtil : enforcerUtil ,
122
- resourceGroupService : resourceGroupService ,
123
- envRepository : envRepository ,
124
- imageTaggingService : imageTaggingService ,
125
- customTagService : customTagService ,
126
- appWorkflowRepository : appWorkflowRepository ,
127
- k8sCommonService : k8sCommonService ,
128
- workFlowStageStatusService : workFlowStageStatusService ,
112
+ Logger : Logger ,
113
+ ciService : ciService ,
114
+ ciPipelineMaterialRepository : ciPipelineMaterialRepository ,
115
+ gitSensorClient : gitSensorClient ,
116
+ ciWorkflowRepository : ciWorkflowRepository ,
117
+ ciArtifactRepository : ciArtifactRepository ,
118
+ userService : userService ,
119
+ eventClient : eventClient ,
120
+ eventFactory : eventFactory ,
121
+ ciPipelineRepository : ciPipelineRepository ,
122
+ appListingRepository : appListingRepository ,
123
+ cdPipelineRepository : cdPipelineRepository ,
124
+ enforcerUtil : enforcerUtil ,
125
+ resourceGroupService : resourceGroupService ,
126
+ envRepository : envRepository ,
127
+ imageTaggingService : imageTaggingService ,
128
+ customTagService : customTagService ,
129
+ appWorkflowRepository : appWorkflowRepository ,
130
+ k8sCommonService : k8sCommonService ,
131
+ workFlowStageStatusService : workFlowStageStatusService ,
132
+ workflowStatusLatestRepository : workflowStatusLatestRepository ,
129
133
}
130
134
config , err := types .GetCiConfig ()
131
135
if err != nil {
@@ -644,13 +648,155 @@ func (impl *CiHandlerImpl) stateChanged(status string, podStatus string, msg str
644
648
}
645
649
646
650
func (impl * CiHandlerImpl ) FetchCiStatusForTriggerViewV1 (appId int ) ([]* pipelineConfig.CiWorkflowStatus , error ) {
647
- ciWorkflowStatuses , err := impl .ciWorkflowRepository .FIndCiWorkflowStatusesByAppId (appId )
648
- if err != nil && ! util .IsErrNoRows (err ) {
649
- impl .Logger .Errorw ("err in fetching ciWorkflowStatuses from ciWorkflowRepository" , "appId" , appId , "err" , err )
650
- return ciWorkflowStatuses , err
651
+ allPipelineIds , err := impl .ciWorkflowRepository .FindCiPipelineIdsByAppId (appId )
652
+ if err != nil {
653
+ impl .Logger .Errorw ("error in getting ci pipeline ids for app, falling back to old method" , "appId" , appId , "err" , err )
654
+ return impl .ciWorkflowRepository .FIndCiWorkflowStatusesByAppId (appId )
655
+ }
656
+
657
+ if len (allPipelineIds ) == 0 {
658
+ return []* pipelineConfig.CiWorkflowStatus {}, nil
659
+ }
660
+
661
+ latestStatusEntries , err := impl .workflowStatusLatestRepository .GetCiWorkflowStatusLatestByPipelineIds (allPipelineIds )
662
+ if err != nil {
663
+ impl .Logger .Errorw ("error in checking latest status table, falling back to old method" , "appId" , appId , "err" , err )
664
+ return impl .ciWorkflowRepository .FIndCiWorkflowStatusesByAppId (appId )
665
+ }
666
+
667
+ var allStatuses []* pipelineConfig.CiWorkflowStatus
668
+
669
+ if len (latestStatusEntries ) > 0 {
670
+ statusesFromLatestTable , err := impl .fetchCiWorkflowStatusFromLatestEntries (latestStatusEntries )
671
+ if err != nil {
672
+ impl .Logger .Errorw ("error in fetching ci workflow status from latest ci workflow entries " , "latestStatusEntries" , latestStatusEntries , "err" , err )
673
+ return nil , err
674
+ } else {
675
+ allStatuses = append (allStatuses , statusesFromLatestTable ... )
676
+ }
677
+ }
678
+
679
+ pipelinesNotInLatestTable := impl .getPipelineIdsNotInLatestTable (allPipelineIds , latestStatusEntries )
680
+
681
+ if len (pipelinesNotInLatestTable ) > 0 {
682
+ statusesFromOldQuery , err := impl .fetchCiStatusUsingFallbackMethod (pipelinesNotInLatestTable )
683
+ if err != nil {
684
+ impl .Logger .Errorw ("error in fetching using fallback method by pipelineIds" , "pipelineIds" , pipelinesNotInLatestTable , "err" , err )
685
+ return nil , err
686
+ } else {
687
+ allStatuses = append (allStatuses , statusesFromOldQuery ... )
688
+ }
689
+ }
690
+
691
+ return allStatuses , nil
692
+ }
693
+
694
+ // fetchCiWorkflowStatusFromLatestEntries fetches CI status from ci_workflow_status_latest table
695
+ func (impl * CiHandlerImpl ) fetchCiWorkflowStatusFromLatestEntries (latestCiWorkflowStatusEntries []* pipelineConfig.CiWorkflowStatusLatest ) ([]* pipelineConfig.CiWorkflowStatus , error ) {
696
+ var workflowIds []int
697
+ for _ , entry := range latestCiWorkflowStatusEntries {
698
+ workflowIds = append (workflowIds , entry .CiWorkflowId )
699
+ }
700
+
701
+ workflows , err := impl .ciWorkflowRepository .FindWorkflowsByCiWorkflowIds (workflowIds )
702
+ if err != nil {
703
+ impl .Logger .Errorw ("error in fetching ci workflows by ci workflow ids" , "workflowIds" , workflowIds , "err" , err )
704
+ return nil , err
705
+ }
706
+
707
+ var statuses []* pipelineConfig.CiWorkflowStatus
708
+ for _ , workflow := range workflows {
709
+ status := adapter .GetCiWorkflowStatusFromCiWorkflow (workflow )
710
+ statuses = append (statuses , status )
711
+ }
712
+
713
+ return statuses , nil
714
+ }
715
+
716
+ // fetchCiStatusUsingFallbackMethod fetches CI status directly from ci_workflow table
717
+ func (impl * CiHandlerImpl ) fetchCiStatusUsingFallbackMethod (pipelineIds []int ) ([]* pipelineConfig.CiWorkflowStatus , error ) {
718
+ workflows , err := impl .ciWorkflowRepository .FindLastTriggeredWorkflowByCiIds (pipelineIds )
719
+ if err != nil {
720
+ impl .Logger .Errorw ("error in fetching ci workflows by ci ids" , "pipelineIds" , pipelineIds , "err" , err )
721
+ return nil , err
722
+ }
723
+
724
+ var statuses []* pipelineConfig.CiWorkflowStatus
725
+ for _ , workflow := range workflows {
726
+ status := adapter .GetCiWorkflowStatusFromCiWorkflow (workflow )
727
+ statuses = append (statuses , status )
728
+ }
729
+
730
+ return statuses , nil
731
+ }
732
+
733
+ func (impl * CiHandlerImpl ) fetchWorkflowsFromLatestTable (latestStatusEntries []* pipelineConfig.CiWorkflowStatusLatest ) ([]* pipelineConfig.CiWorkflow , error ) {
734
+ var workflowIds []int
735
+ for _ , entry := range latestStatusEntries {
736
+ workflowIds = append (workflowIds , entry .CiWorkflowId )
651
737
}
652
738
653
- return ciWorkflowStatuses , err
739
+ return impl .ciWorkflowRepository .FindWorkflowsByCiWorkflowIds (workflowIds )
740
+ }
741
+
742
+ // fetchLastTriggeredWorkflowsHybrid implements hybrid approach for workflow fetching
743
+ // Uses latest status table for available pipelines, fallback to complex query for missing pipelines
744
+ func (impl * CiHandlerImpl ) fetchLastTriggeredWorkflowsHybrid (pipelineIds []int ) ([]* pipelineConfig.CiWorkflow , error ) {
745
+ if len (pipelineIds ) == 0 {
746
+ return []* pipelineConfig.CiWorkflow {}, nil
747
+ }
748
+
749
+ latestStatusEntries , err := impl .workflowStatusLatestRepository .GetCiWorkflowStatusLatestByPipelineIds (pipelineIds )
750
+ if err != nil {
751
+ impl .Logger .Errorw ("error in checking latest status table, falling back to complex query" , "pipelineIds" , pipelineIds , "err" , err )
752
+ return impl .ciWorkflowRepository .FindLastTriggeredWorkflowByCiIds (pipelineIds )
753
+ }
754
+
755
+ var allWorkflows []* pipelineConfig.CiWorkflow
756
+
757
+ if len (latestStatusEntries ) > 0 {
758
+ workflowsFromLatestTable , err := impl .fetchWorkflowsFromLatestTable (latestStatusEntries )
759
+ if err != nil {
760
+ impl .Logger .Errorw ("error in fetching from latest status table" , "latestStatusEntries" , latestStatusEntries , "err" , err )
761
+ return nil , err
762
+ } else {
763
+ allWorkflows = append (allWorkflows , workflowsFromLatestTable ... )
764
+ }
765
+ }
766
+
767
+ pipelinesNotInLatestTable := impl .getPipelineIdsNotInLatestTable (pipelineIds , latestStatusEntries )
768
+
769
+ if len (pipelinesNotInLatestTable ) > 0 {
770
+ workflowsFromOldQuery , err := impl .ciWorkflowRepository .FindLastTriggeredWorkflowByCiIds (pipelinesNotInLatestTable )
771
+ if err != nil {
772
+ impl .Logger .Errorw ("error in fetching using old query by pipeline ids" , "pipelineIds" , pipelinesNotInLatestTable , "err" , err )
773
+ return nil , err
774
+ } else {
775
+ allWorkflows = append (allWorkflows , workflowsFromOldQuery ... )
776
+ }
777
+ }
778
+
779
+ return allWorkflows , nil
780
+ }
781
+
782
+ // getPipelineIdsNotInLatestTable finds pipeline IDs that are NOT in the latest status table
783
+ func (impl * CiHandlerImpl ) getPipelineIdsNotInLatestTable (allPipelineIds []int , latestStatusEntries []* pipelineConfig.CiWorkflowStatusLatest ) []int {
784
+ var pipelinesInLatestTable []int
785
+ for _ , entry := range latestStatusEntries {
786
+ pipelinesInLatestTable = append (pipelinesInLatestTable , entry .PipelineId )
787
+ }
788
+ pipelineIdMap := make (map [int ]bool )
789
+ for _ , id := range pipelinesInLatestTable {
790
+ pipelineIdMap [id ] = true
791
+ }
792
+
793
+ var missingPipelineIds []int
794
+ for _ , id := range allPipelineIds {
795
+ if ! pipelineIdMap [id ] {
796
+ missingPipelineIds = append (missingPipelineIds , id )
797
+ }
798
+ }
799
+ return missingPipelineIds
654
800
}
655
801
656
802
func (impl * CiHandlerImpl ) FetchCiStatusForTriggerView (appId int ) ([]* pipelineConfig.CiWorkflowStatus , error ) {
@@ -861,9 +1007,9 @@ func (impl *CiHandlerImpl) FetchCiStatusForTriggerViewForEnvironment(request res
861
1007
if len (ciPipelineIds ) == 0 {
862
1008
return ciWorkflowStatuses , nil
863
1009
}
864
- latestCiWorkflows , err := impl .ciWorkflowRepository . FindLastTriggeredWorkflowByCiIds (ciPipelineIds )
1010
+ latestCiWorkflows , err := impl .fetchLastTriggeredWorkflowsHybrid (ciPipelineIds )
865
1011
if err != nil && ! util .IsErrNoRows (err ) {
866
- impl .Logger .Errorw ("err" , "ciPipelineIds" , ciPipelineIds , "err" , err )
1012
+ impl .Logger .Errorw ("err in hybrid ci workflow fetch " , "ciPipelineIds" , ciPipelineIds , "err" , err )
867
1013
return ciWorkflowStatuses , err
868
1014
}
869
1015
0 commit comments