diff --git a/Wire.go b/Wire.go index 08f44eeab9..935ddf7021 100644 --- a/Wire.go +++ b/Wire.go @@ -112,6 +112,7 @@ import ( "github.com/devtron-labs/devtron/pkg/appStore/installedApp/service/FullMode/deploymentTypeChange" "github.com/devtron-labs/devtron/pkg/appStore/installedApp/service/FullMode/resource" "github.com/devtron-labs/devtron/pkg/appWorkflow" + "github.com/devtron-labs/devtron/pkg/asyncProvider" "github.com/devtron-labs/devtron/pkg/attributes" "github.com/devtron-labs/devtron/pkg/build" "github.com/devtron-labs/devtron/pkg/bulkAction" @@ -229,6 +230,10 @@ func InitializeApp() (*App, error) { wire.Bind(new(router.PProfRouter), new(*router.PProfRouterImpl)), // ---- pprof end ---- + // ---- goroutine async wrapper service start ---- + asyncProvider.WireSet, + // ---- goroutine async wrapper service end ---- + sql.NewTransactionUtilImpl, wire.Bind(new(sql.TransactionWrapper), new(*sql.TransactionUtilImpl)), diff --git a/WiringNilCheck.go b/WiringNilCheck.go index 90d719b868..946b154d92 100755 --- a/WiringNilCheck.go +++ b/WiringNilCheck.go @@ -18,6 +18,7 @@ package main import ( "fmt" + "github.com/devtron-labs/devtron/util/reflectUtil" "log" "os" "reflect" @@ -81,14 +82,7 @@ func checkNilFields(obj interface{}, nilObjMap map[string]bool) { } func canFieldTypeBeNil(field reflect.Value) bool { - kind := field.Kind() - switch kind { - case reflect.Chan, reflect.Func, reflect.Map, reflect.Pointer, reflect.UnsafePointer, - reflect.Interface, reflect.Slice: - return true - default: //other types can not be nil - return false - } + return reflectUtil.IsNullableValue(field) } func canSkipFieldStructCheck(fieldName, valName string) bool { diff --git a/client/argocdServer/ArgoClientWrapperService.go b/client/argocdServer/ArgoClientWrapperService.go index 86d316b94d..8e78a0c1cf 100644 --- a/client/argocdServer/ArgoClientWrapperService.go +++ b/client/argocdServer/ArgoClientWrapperService.go @@ -24,6 +24,7 @@ import ( repository2 "github.com/argoproj/argo-cd/v2/pkg/apiclient/repository" "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1" "github.com/caarlos0/env" + "github.com/devtron-labs/common-lib/async" "github.com/devtron-labs/devtron/client/argocdServer/adapter" "github.com/devtron-labs/devtron/client/argocdServer/application" "github.com/devtron-labs/devtron/client/argocdServer/bean" @@ -104,11 +105,12 @@ type ArgoClientWrapperServiceImpl struct { repositoryService repository.ServiceClient gitOpsConfigReadService config.GitOpsConfigReadService gitOperationService git.GitOperationService + asyncRunnable *async.Runnable } func NewArgoClientWrapperServiceImpl(logger *zap.SugaredLogger, acdClient application.ServiceClient, ACDConfig *ACDConfig, repositoryService repository.ServiceClient, gitOpsConfigReadService config.GitOpsConfigReadService, - gitOperationService git.GitOperationService) *ArgoClientWrapperServiceImpl { + gitOperationService git.GitOperationService, asyncRunnable *async.Runnable) *ArgoClientWrapperServiceImpl { return &ArgoClientWrapperServiceImpl{ logger: logger, acdClient: acdClient, @@ -116,13 +118,16 @@ func NewArgoClientWrapperServiceImpl(logger *zap.SugaredLogger, acdClient applic repositoryService: repositoryService, gitOpsConfigReadService: gitOpsConfigReadService, gitOperationService: gitOperationService, + asyncRunnable: asyncRunnable, } } -func (impl *ArgoClientWrapperServiceImpl) GetArgoAppWithNormalRefresh(context context.Context, argoAppName string) error { +func (impl *ArgoClientWrapperServiceImpl) GetArgoAppWithNormalRefresh(ctx context.Context, argoAppName string) error { + newCtx, span := otel.Tracer("orchestrator").Start(ctx, "ArgoClientWrapperServiceImpl.GetArgoAppWithNormalRefresh") + defer span.End() refreshType := bean.RefreshTypeNormal impl.logger.Debugw("trying to normal refresh application through get ", "argoAppName", argoAppName) - _, err := impl.acdClient.Get(context, &application2.ApplicationQuery{Name: &argoAppName, Refresh: &refreshType}) + _, err := impl.acdClient.Get(newCtx, &application2.ApplicationQuery{Name: &argoAppName, Refresh: &refreshType}) if err != nil { internalMsg := fmt.Sprintf("%s, err:- %s", constants.CannotGetAppWithRefreshErrMsg, err.Error()) clientCode, _ := util.GetClientDetailedError(err) @@ -177,10 +182,15 @@ func (impl *ArgoClientWrapperServiceImpl) SyncArgoCDApplicationIfNeededAndRefres } impl.logger.Infow("ArgoCd sync completed", "argoAppName", argoAppName) } - refreshErr := impl.GetArgoAppWithNormalRefresh(newCtx, argoAppName) - if refreshErr != nil { - impl.logger.Errorw("error in refreshing argo app", "err", refreshErr) + + runnableFunc := func() { + // running ArgoCd app refresh in asynchronous mode + refreshErr := impl.GetArgoAppWithNormalRefresh(context.Background(), argoAppName) + if refreshErr != nil { + impl.logger.Errorw("error in refreshing argo app", "argoAppName", argoAppName, "err", refreshErr) + } } + impl.asyncRunnable.Execute(runnableFunc) return nil } diff --git a/client/argocdServer/application/Application.go b/client/argocdServer/application/Application.go index 75dd8750c5..b59c3dc269 100644 --- a/client/argocdServer/application/Application.go +++ b/client/argocdServer/application/Application.go @@ -82,17 +82,17 @@ func (c ServiceClientImpl) Patch(ctxt context.Context, query *application.Applic return resp, err } -func (c ServiceClientImpl) Get(ctxt context.Context, query *application.ApplicationQuery) (*v1alpha1.Application, error) { - ctx, cancel := context.WithTimeout(ctxt, argoApplication.TimeoutFast) - defer cancel() - token, ok := ctxt.Value("token").(string) +func (c ServiceClientImpl) Get(ctx context.Context, query *application.ApplicationQuery) (*v1alpha1.Application, error) { + token, ok := ctx.Value("token").(string) if !ok { return nil, errors.New("Unauthorized") } + newCtx, cancel := context.WithTimeout(ctx, argoApplication.TimeoutFast) + defer cancel() conn := c.argoCDConnectionManager.GetConnection(token) defer util.Close(conn, c.logger) asc := application.NewApplicationServiceClient(conn) - resp, err := asc.Get(ctx, query) + resp, err := asc.Get(newCtx, query) return resp, err } diff --git a/env_gen.md b/env_gen.md index 7a76a63bc3..e2d802c524 100644 --- a/env_gen.md +++ b/env_gen.md @@ -189,6 +189,7 @@ | NATS_MSG_BUFFER_SIZE | -1 | | | NATS_MSG_MAX_AGE | 86400 | | | NATS_MSG_PROCESSING_BATCH_SIZE | 1 | | + | NATS_MSG_REPLICAS | 0 | | | NATS_SERVER_HOST | nats://devtron-nats.devtroncd:4222 | | | NOTIFICATION_MEDIUM | rest | | | ORCH_HOST | http://devtroncd-orchestrator-service-prod.devtroncd/webhook/msg/nats | | @@ -210,7 +211,6 @@ | PRE_CI_CACHE_PATH | /devtroncd-cache | | | PROPAGATE_EXTRA_LABELS | false | | | PROXY_SERVICE_CONFIG | {} | | - | REPLICAS | 0 | | | REQ_CI_CPU | 0.5 | | | REQ_CI_MEM | 3G | | | RESOURCE_LIST_FOR_REPLICAS | Deployment,Rollout,StatefulSet,ReplicaSet | | diff --git a/go.mod b/go.mod index 82b06874bf..aed3a9b10c 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,7 @@ require ( github.com/davecgh/go-spew v1.1.1 github.com/deckarep/golang-set v1.8.0 github.com/devtron-labs/authenticator v0.4.35-0.20240607135426-c86e868ecee1 - github.com/devtron-labs/common-lib v0.0.22-0.20240705073412-32e32c499160 + github.com/devtron-labs/common-lib v0.0.23 github.com/devtron-labs/go-bitbucket v0.9.60-beta github.com/devtron-labs/protos v0.0.3-0.20240527113333-08a3be5ec6c1 github.com/evanphx/json-patch v5.7.0+incompatible diff --git a/go.sum b/go.sum index b5e22bcc2a..d48259a015 100644 --- a/go.sum +++ b/go.sum @@ -197,8 +197,8 @@ github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc h1:VRRKCwnzq github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/devtron-labs/authenticator v0.4.35-0.20240607135426-c86e868ecee1 h1:qdkpTAo2Kr0ZicZIVXfNwsGSshpc9OB9j9RzmKYdIwY= github.com/devtron-labs/authenticator v0.4.35-0.20240607135426-c86e868ecee1/go.mod h1:IkKPPEfgLCMR29he5yv2OCC6iM2R7K5/0AA3k8b9XNc= -github.com/devtron-labs/common-lib v0.0.22-0.20240705073412-32e32c499160 h1:9iumIJmRId91aUcyPkxPb6nvjhHuYDoAgomNSG6OIdE= -github.com/devtron-labs/common-lib v0.0.22-0.20240705073412-32e32c499160/go.mod h1:UZGPt1ep9Tnd9Ak2sibGSiLr7p3ijO2/JLT+h+pqBuU= +github.com/devtron-labs/common-lib v0.0.23 h1:3n9VgJALanjHrb/t0nSaLbLJcJa7sdsdyFf2leE+cN0= +github.com/devtron-labs/common-lib v0.0.23/go.mod h1:UZGPt1ep9Tnd9Ak2sibGSiLr7p3ijO2/JLT+h+pqBuU= github.com/devtron-labs/go-bitbucket v0.9.60-beta h1:VEx1jvDgdtDPS6A1uUFoaEi0l1/oLhbr+90xOwr6sDU= github.com/devtron-labs/go-bitbucket v0.9.60-beta/go.mod h1:GnuiCesvh8xyHeMCb+twm8lBR/kQzJYSKL28ZfObp1Y= github.com/devtron-labs/protos v0.0.3-0.20240527113333-08a3be5ec6c1 h1:R6qVeFaayqstBSu4w+ipWQqJyMKDqBVV3a11qoA2IaM= diff --git a/pkg/appStore/installedApp/service/EAMode/EAModeDeploymentService.go b/pkg/appStore/installedApp/service/EAMode/EAModeDeploymentService.go index 94950702ed..35025a5a41 100644 --- a/pkg/appStore/installedApp/service/EAMode/EAModeDeploymentService.go +++ b/pkg/appStore/installedApp/service/EAMode/EAModeDeploymentService.go @@ -51,7 +51,6 @@ type EAModeDeploymentService interface { GetDeploymentHistory(ctx context.Context, installedApp *appStoreBean.InstallAppVersionDTO) (*gRPC.HelmAppDeploymentHistory, error) GetDeploymentHistoryInfo(ctx context.Context, installedApp *appStoreBean.InstallAppVersionDTO, version int32) (*openapi.HelmAppDeploymentManifestDetail, error) UpgradeDeployment(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, ChartGitAttribute *commonBean.ChartGitAttribute, installedAppVersionHistoryId int, ctx context.Context) error - GetAcdAppGitOpsRepoURL(appName string, environmentName string) (string, error) } type EAModeDeploymentServiceImpl struct { @@ -442,6 +441,7 @@ func (impl *EAModeDeploymentServiceImpl) GetChartBytesForParticularDeployment(in func (impl *EAModeDeploymentServiceImpl) DeleteACD(acdAppName string, ctx context.Context, isNonCascade bool) error { return errors.New("this is not implemented") } + func (impl *EAModeDeploymentServiceImpl) GetAcdAppGitOpsRepoURL(appName string, environmentName string) (string, error) { return "", errors.New("this is not implemented") } diff --git a/pkg/asyncProvider/AsyncProvider.go b/pkg/asyncProvider/AsyncProvider.go new file mode 100644 index 0000000000..f60ed35624 --- /dev/null +++ b/pkg/asyncProvider/AsyncProvider.go @@ -0,0 +1,11 @@ +package asyncProvider + +import ( + "github.com/devtron-labs/common-lib/async" + "github.com/devtron-labs/common-lib/constants" + "go.uber.org/zap" +) + +func NewAsyncRunnable(logger *zap.SugaredLogger) *async.Runnable { + return async.NewAsyncRunnable(logger, constants.Orchestrator) +} diff --git a/pkg/asyncProvider/wire_AsyncProvider.go b/pkg/asyncProvider/wire_AsyncProvider.go new file mode 100644 index 0000000000..44f68301cf --- /dev/null +++ b/pkg/asyncProvider/wire_AsyncProvider.go @@ -0,0 +1,9 @@ +package asyncProvider + +import ( + "github.com/google/wire" +) + +var WireSet = wire.NewSet( + NewAsyncRunnable, +) diff --git a/pkg/deployment/trigger/devtronApps/TriggerService.go b/pkg/deployment/trigger/devtronApps/TriggerService.go index 12f5ad20f7..a662305f07 100644 --- a/pkg/deployment/trigger/devtronApps/TriggerService.go +++ b/pkg/deployment/trigger/devtronApps/TriggerService.go @@ -1170,7 +1170,7 @@ func (impl *TriggerServiceImpl) updateArgoPipeline(ctx context.Context, pipeline impl.logger.Infow("received payload, updateArgoPipeline", "appId", pipeline.AppId, "pipelineName", pipeline.Name, "envId", envOverride.TargetEnvironment, "argoAppName", argoAppName) argoApplication, err := impl.argoClientWrapperService.GetArgoAppByName(newCtx, argoAppName) if err != nil { - impl.logger.Errorw("no argo app exists", "app", argoAppName, "pipeline", pipeline.Name) + impl.logger.Errorw("unable to get ArgoCd app", "app", argoAppName, "pipeline", pipeline.Name, "err", err) return false, err } //if status, ok:=status.FromError(err);ok{ diff --git a/util/reflectUtil/ReflectUtil.go b/util/reflectUtil/ReflectUtil.go new file mode 100644 index 0000000000..bbb378c49a --- /dev/null +++ b/util/reflectUtil/ReflectUtil.go @@ -0,0 +1,14 @@ +package reflectUtil + +import "reflect" + +func IsNullableValue(field reflect.Value) bool { + kind := field.Kind() + switch kind { + case reflect.Chan, reflect.Func, reflect.Map, reflect.Pointer, reflect.UnsafePointer, + reflect.Interface, reflect.Slice: + return true + default: //other types can not be nil + return false + } +} diff --git a/vendor/github.com/devtron-labs/common-lib/async/async.go b/vendor/github.com/devtron-labs/common-lib/async/async.go new file mode 100644 index 0000000000..425af98c4b --- /dev/null +++ b/vendor/github.com/devtron-labs/common-lib/async/async.go @@ -0,0 +1,73 @@ +package async + +import ( + "fmt" + "github.com/devtron-labs/common-lib/constants" + "github.com/devtron-labs/common-lib/pubsub-lib/metrics" + "github.com/devtron-labs/common-lib/utils/runTime" + "go.uber.org/zap" + "runtime/debug" +) + +type Runnable struct { + logger *zap.SugaredLogger + serviceName constants.ServiceName +} + +type RunAsyncMetaData struct { + Method string + Path string +} + +func NewAsyncRunnable(logger *zap.SugaredLogger, serviceName constants.ServiceName) *Runnable { + return &Runnable{ + logger: logger, + serviceName: serviceName, + } +} + +func NewRunAsyncMetaData() *RunAsyncMetaData { + return &RunAsyncMetaData{} +} + +func CallerMethod(methodName string) NewUpdateMetaData { + return func(m *RunAsyncMetaData) { + m.Method = methodName + } +} + +func CallerPath(pathName string) NewUpdateMetaData { + return func(m *RunAsyncMetaData) { + m.Path = pathName + } +} + +type NewUpdateMetaData func(*RunAsyncMetaData) + +func (impl *Runnable) Execute(runnableFunc func()) { + impl.run(runnableFunc, + CallerMethod(runTime.GetCallerFunctionName()), + CallerPath(fmt.Sprintf("%s:%d", runTime.GetCallerFileName(), runTime.GetCallerLineNumber())), + ) +} + +func (impl *Runnable) run(fn func(), metadataOpts ...NewUpdateMetaData) { + metaData := NewRunAsyncMetaData() + for _, metadataOpt := range metadataOpts { + // updating meta data + if metadataOpt != nil { + metadataOpt(metaData) + } + } + go func() { + defer func() { + if r := recover(); r != nil { + metrics.IncPanicRecoveryCount("go-routine", impl.serviceName.ToString(), metaData.Method, metaData.Path) + impl.logger.Errorw(fmt.Sprintf("%s %s", constants.GoRoutinePanicMsgLogPrefix, "go-routine recovered from panic"), "err", r, "stack", string(debug.Stack())) + } + }() + if fn != nil { + fn() + } + }() +} diff --git a/vendor/github.com/devtron-labs/common-lib/constants/constants.go b/vendor/github.com/devtron-labs/common-lib/constants/constants.go index 7a51abeb85..9d319c623e 100644 --- a/vendor/github.com/devtron-labs/common-lib/constants/constants.go +++ b/vendor/github.com/devtron-labs/common-lib/constants/constants.go @@ -16,7 +16,22 @@ package constants -const PanicLogIdentifier = "DEVTRON_PANIC_RECOVER" +const ( + PanicLogIdentifier = "DEVTRON_PANIC_RECOVER" + GoRoutinePanicMsgLogPrefix = "GO_ROUTINE_PANIC_LOG:" +) + +// service names constant + +type ServiceName string + +func (m ServiceName) ToString() string { + return string(m) +} + +const ( + Orchestrator ServiceName = "ORCHESTRATOR" +) // metrics name constants diff --git a/vendor/github.com/devtron-labs/common-lib/pubsub-lib/NatsClient.go b/vendor/github.com/devtron-labs/common-lib/pubsub-lib/NatsClient.go index 43bb011cac..1da3710cd4 100644 --- a/vendor/github.com/devtron-labs/common-lib/pubsub-lib/NatsClient.go +++ b/vendor/github.com/devtron-labs/common-lib/pubsub-lib/NatsClient.go @@ -48,7 +48,7 @@ type NatsClientConfig struct { NatsMsgBufferSize int `env:"NATS_MSG_BUFFER_SIZE" envDefault:"-1"` NatsMsgMaxAge int `env:"NATS_MSG_MAX_AGE" envDefault:"86400"` NatsMsgAckWaitInSecs int `env:"NATS_MSG_ACK_WAIT_IN_SECS" envDefault:"120"` - Replicas int `env:"REPLICAS" envDefault:"0"` + NatsMsgReplicas int `env:"NATS_MSG_REPLICAS" envDefault:"0"` } func (ncc NatsClientConfig) GetNatsMsgBufferSize() int { @@ -72,7 +72,7 @@ func (ncc NatsClientConfig) GetDefaultNatsStreamConfig() NatsStreamConfig { return NatsStreamConfig{ StreamConfig: StreamConfig{ MaxAge: time.Duration(ncc.NatsMsgMaxAge) * time.Second, - Replicas: ncc.Replicas, + Replicas: ncc.NatsMsgReplicas, }, } } diff --git a/vendor/github.com/devtron-labs/common-lib/utils/runTime/GetCallerFrames.go b/vendor/github.com/devtron-labs/common-lib/utils/runTime/GetCallerFrames.go new file mode 100644 index 0000000000..ff54cba4a8 --- /dev/null +++ b/vendor/github.com/devtron-labs/common-lib/utils/runTime/GetCallerFrames.go @@ -0,0 +1,50 @@ +package runTime + +import ( + "runtime" +) + +// GetCallerFileName - returns the file name of the invoked func +func GetCallerFileName() string { + // Skip GetCurrentFunctionName + return getFrame(1).File +} + +// GetCallerLineNumber - returns the line number of the invoked func +func GetCallerLineNumber() int { + // Skip GetCurrentFunctionName + return getFrame(1).Line +} + +// GetCallerFunctionName - returns the function name of the invoked func +func GetCallerFunctionName() string { + // Skip GetCallerFunctionName and the function to get the caller of + return getFrame(2).Function +} + +// getFrame returns the runtime.Frame for the targetFrameIndex from the runtime caller stack +// +// examples: +// 1. getFrame(0) -> returns current method frame +// 2. getFrame(1) -> returns caller method frame +// 3. getFrame(2) -> returns caller's caller method frame +func getFrame(targetFrameIndex int) runtime.Frame { + // Set size to targetFrameIndex + 2 to ensure we have room for function runtime.Callers and getFrame + programCounters := make([]uintptr, targetFrameIndex+2) + // We need the frame at index targetFrameIndex + 2, since we never want function runtime.Callers and getFrame + n := runtime.Callers(2, programCounters) + + frame := runtime.Frame{Function: "unknown"} + if n > 0 { + frames := runtime.CallersFrames(programCounters[:n]) + for more, frameIndex := true, 0; more && frameIndex <= targetFrameIndex; frameIndex++ { + var frameCandidate runtime.Frame + frameCandidate, more = frames.Next() + if frameIndex == targetFrameIndex { + frame = frameCandidate + } + } + } + + return frame +} diff --git a/vendor/modules.txt b/vendor/modules.txt index abb817a97e..337f2ab91b 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -402,8 +402,9 @@ github.com/devtron-labs/authenticator/jwt github.com/devtron-labs/authenticator/middleware github.com/devtron-labs/authenticator/oidc github.com/devtron-labs/authenticator/password -# github.com/devtron-labs/common-lib v0.0.22-0.20240705073412-32e32c499160 +# github.com/devtron-labs/common-lib v0.0.23 ## explicit; go 1.21 +github.com/devtron-labs/common-lib/async github.com/devtron-labs/common-lib/blob-storage github.com/devtron-labs/common-lib/cloud-provider-identifier github.com/devtron-labs/common-lib/cloud-provider-identifier/bean @@ -422,6 +423,7 @@ github.com/devtron-labs/common-lib/utils/k8s/commonBean github.com/devtron-labs/common-lib/utils/k8s/health github.com/devtron-labs/common-lib/utils/k8sObjectsUtil github.com/devtron-labs/common-lib/utils/remoteConnection/bean +github.com/devtron-labs/common-lib/utils/runTime github.com/devtron-labs/common-lib/utils/yaml # github.com/devtron-labs/go-bitbucket v0.9.60-beta ## explicit; go 1.14 diff --git a/wire_gen.go b/wire_gen.go index 3a56b8c70b..8d8a57a870 100644 --- a/wire_gen.go +++ b/wire_gen.go @@ -115,6 +115,7 @@ import ( service3 "github.com/devtron-labs/devtron/pkg/appStore/values/service" appWorkflow2 "github.com/devtron-labs/devtron/pkg/appWorkflow" "github.com/devtron-labs/devtron/pkg/argoApplication" + "github.com/devtron-labs/devtron/pkg/asyncProvider" "github.com/devtron-labs/devtron/pkg/attributes" "github.com/devtron-labs/devtron/pkg/auth/authentication" "github.com/devtron-labs/devtron/pkg/auth/authorisation/casbin" @@ -584,7 +585,8 @@ func InitializeApp() (*App, error) { pipelineStrategyHistoryServiceImpl := history.NewPipelineStrategyHistoryServiceImpl(sugaredLogger, pipelineStrategyHistoryRepositoryImpl, userServiceImpl) propertiesConfigServiceImpl := pipeline.NewPropertiesConfigServiceImpl(sugaredLogger, envConfigOverrideRepositoryImpl, chartRepositoryImpl, environmentRepositoryImpl, deploymentTemplateHistoryServiceImpl, scopedVariableManagerImpl, deployedAppMetricsServiceImpl) repositoryServiceClientImpl := repository14.NewServiceClientImpl(sugaredLogger, argoCDConnectionManagerImpl) - argoClientWrapperServiceImpl := argocdServer.NewArgoClientWrapperServiceImpl(sugaredLogger, applicationServiceClientImpl, acdConfig, repositoryServiceClientImpl, gitOpsConfigReadServiceImpl, gitOperationServiceImpl) + runnable := asyncProvider.NewAsyncRunnable(sugaredLogger) + argoClientWrapperServiceImpl := argocdServer.NewArgoClientWrapperServiceImpl(sugaredLogger, applicationServiceClientImpl, acdConfig, repositoryServiceClientImpl, gitOpsConfigReadServiceImpl, gitOperationServiceImpl, runnable) imageDigestPolicyServiceImpl := imageDigestPolicy.NewImageDigestPolicyServiceImpl(sugaredLogger, qualifierMappingServiceImpl, devtronResourceSearchableKeyServiceImpl) pipelineConfigEventPublishServiceImpl := out.NewPipelineConfigEventPublishServiceImpl(sugaredLogger, pubSubClientServiceImpl) deploymentTypeOverrideServiceImpl := providerConfig.NewDeploymentTypeOverrideServiceImpl(sugaredLogger, environmentVariables, attributesServiceImpl)