func (wh *WorkflowHandler) RespondDecisionTaskFailed(
	ctx context.Context,
	failedRequest *types.RespondDecisionTaskFailedRequest,
) (retError error) {
	defer log.CapturePanic(wh.GetLogger(), &retError)

	scope := wh.getDefaultScope(ctx, metrics.FrontendRespondDecisionTaskFailedScope)

	if wh.isShuttingDown() {
		return errShuttingDown
	}

	if err := wh.versionChecker.ClientSupported(ctx, wh.config.EnableClientVersionCheck()); err != nil {
		return wh.error(err, scope)
	}

	if failedRequest == nil {
		return wh.error(errRequestNotSet, scope)
	}

	if failedRequest.TaskToken == nil {
		return wh.error(errTaskTokenNotSet, scope)
	}
	taskToken, err := wh.tokenSerializer.Deserialize(failedRequest.TaskToken)
	if err != nil {
		return wh.error(err, scope)
	}
	if taskToken.DomainID == "" {
		return wh.error(errDomainNotSet, scope)
	}

	domainName, err := wh.GetDomainCache().GetDomainName(taskToken.DomainID)
	if err != nil {
		return wh.error(err, scope)
	}

	dw := domainWrapper{
		domain: domainName,
	}
	scope, sw := wh.startRequestProfileWithDomain(
		ctx,
		metrics.FrontendRespondDecisionTaskFailedScope,
		dw,
	)
	defer sw.Stop()

	// Count the request in the host RPS,
	// but we still accept it even if RPS is exceeded
	wh.allow(false, dw)

	tags := getDomainWfIDRunIDTags(domainName, &types.WorkflowExecution{
		WorkflowID: taskToken.WorkflowID,
		RunID:      taskToken.RunID,
	})

	if !common.ValidIDLength(
		failedRequest.GetIdentity(),
		scope,
		wh.config.MaxIDLengthWarnLimit(),
		wh.config.IdentityMaxLength(domainName),
		metrics.CadenceErrIdentityExceededWarnLimit,
		domainName,
		wh.GetLogger(),
		tag.IDTypeIdentity) {
		return wh.error(errIdentityTooLong, scope, tags...)
	}

	sizeLimitError := wh.config.BlobSizeLimitError(domainName)
	sizeLimitWarn := wh.config.BlobSizeLimitWarn(domainName)

	if err := common.CheckEventBlobSizeLimit(
		len(failedRequest.Details),
		sizeLimitWarn,
		sizeLimitError,
		taskToken.DomainID,
		taskToken.WorkflowID,
		taskToken.RunID,
		scope,
		wh.GetThrottledLogger(),
		tag.BlobSizeViolationOperation("RespondDecisionTaskFailed"),
	); err != nil {
		// details exceed, we would just truncate the size for decision task failed as the details is not used anywhere by client code
		failedRequest.Details = failedRequest.Details[0:sizeLimitError]
	}

	err = wh.GetHistoryClient().RespondDecisionTaskFailed(ctx, &types.HistoryRespondDecisionTaskFailedRequest{
		DomainUUID:    taskToken.DomainID,
		FailedRequest: failedRequest,
	})
	if err != nil {
		return wh.normalizeVersionedErrors(ctx, wh.error(err, scope, tags...))
	}
	return nil
}
// RespondDecisionTaskFailed - failed response to a decision task
failed response to a decision task
// RespondDecisionTaskFailed - failed response to a decision task
func (wh *WorkflowHandler) RespondDecisionTaskFailed(
	ctx context.Context,
	failedRequest *types.RespondDecisionTaskFailedRequest,
) (retError error) {
	defer log.CapturePanic(wh.GetLogger(), &retError)
	scope := wh.getDefaultScope(ctx, metrics.FrontendRespondDecisionTaskFailedScope)
	if wh.isShuttingDown() {
		return errShuttingDown
	}
	if err := wh.versionChecker.ClientSupported(ctx, wh.config.EnableClientVersionCheck()); err != nil {
		return wh.error(err, scope)
	}
	if failedRequest == nil {
		return wh.error(errRequestNotSet, scope)
	}
	if failedRequest.TaskToken == nil {
		return wh.error(errTaskTokenNotSet, scope)
	}
	taskToken, err := wh.tokenSerializer.Deserialize(failedRequest.TaskToken)
	if err != nil {
		return wh.error(err, scope)
	}
	if taskToken.DomainID == "" {
		return wh.error(errDomainNotSet, scope)
	}
	domainName, err := wh.GetDomainCache().GetDomainName(taskToken.DomainID)
	if err != nil {
		return wh.error(err, scope)
	}
	dw := domainWrapper{
		domain: domainName,
	}
	scope, sw := wh.startRequestProfileWithDomain(
		ctx,
		metrics.FrontendRespondDecisionTaskFailedScope,
		dw,
	)
	defer sw.Stop()
	wh.allow(false, dw)
	tags := getDomainWfIDRunIDTags(domainName, &types.WorkflowExecution{
		WorkflowID: taskToken.WorkflowID,
		RunID:      taskToken.RunID,
	})
	if !common.ValidIDLength(
		failedRequest.GetIdentity(),
		scope,
		wh.config.MaxIDLengthWarnLimit(),
		wh.config.IdentityMaxLength(domainName),
		metrics.CadenceErrIdentityExceededWarnLimit,
		domainName,
		wh.GetLogger(),
		tag.IDTypeIdentity) {
		return wh.error(errIdentityTooLong, scope, tags...)
	}
	sizeLimitError := wh.config.BlobSizeLimitError(domainName)
	sizeLimitWarn := wh.config.BlobSizeLimitWarn(domainName)
	if err := common.CheckEventBlobSizeLimit(
		len(failedRequest.Details),
		sizeLimitWarn,
		sizeLimitError,
		taskToken.DomainID,
		taskToken.WorkflowID,
		taskToken.RunID,
		scope,
		wh.GetThrottledLogger(),
		tag.BlobSizeViolationOperation("RespondDecisionTaskFailed"),
	); err != nil {
		failedRequest.Details = failedRequest.Details[0:sizeLimitError]
	}
	err = wh.GetHistoryClient().RespondDecisionTaskFailed(ctx, &types.HistoryRespondDecisionTaskFailedRequest{
		DomainUUID:    taskToken.DomainID,
		FailedRequest: failedRequest,
	})
	if err != nil {
		return wh.normalizeVersionedErrors(ctx, wh.error(err, scope, tags...))
	}
	return nil
}
func ( wh * WorkflowHandler ) RespondDecisionTaskFailed ( ctx context . Context , failedRequest * types . RespondDecisionTaskFailedRequest , ) ( retError error ) { defer log . CapturePanic ( wh . GetLogger ( ) , & retError ) scope := wh . getDefaultScope ( ctx , metrics . FrontendRespondDecisionTaskFailedScope ) if wh . isShuttingDown ( ) { return errShuttingDown } if err := wh . versionChecker . ClientSupported ( ctx , wh . config . EnableClientVersionCheck ( ) ) ; err != nil { return wh . error ( err , scope ) } if failedRequest == nil { return wh . error ( errRequestNotSet , scope ) } if failedRequest . TaskToken == nil { return wh . error ( errTaskTokenNotSet , scope ) } taskToken , err := wh . tokenSerializer . Deserialize ( failedRequest . TaskToken ) if err != nil { return wh . error ( err , scope ) } if taskToken . DomainID == " " { return wh . error ( errDomainNotSet , scope ) } domainName , err := wh . GetDomainCache ( ) . GetDomainName ( taskToken . DomainID ) if err != nil { return wh . error ( err , scope ) } dw := domainWrapper { domain : domainName , } scope , sw := wh . startRequestProfileWithDomain ( ctx , metrics . FrontendRespondDecisionTaskFailedScope , dw , ) defer sw . Stop ( ) wh . allow ( false , dw ) tags := getDomainWfIDRunIDTags ( domainName , & types . WorkflowExecution { WorkflowID : taskToken . WorkflowID , RunID : taskToken . RunID , } ) if ! common . ValidIDLength ( failedRequest . GetIdentity ( ) , scope , wh . config . MaxIDLengthWarnLimit ( ) , wh . config . IdentityMaxLength ( domainName ) , metrics . CadenceErrIdentityExceededWarnLimit , domainName , wh . GetLogger ( ) , tag . IDTypeIdentity ) { return wh . error ( errIdentityTooLong , scope , tags ... ) } sizeLimitError := wh . config . BlobSizeLimitError ( domainName ) sizeLimitWarn := wh . config . BlobSizeLimitWarn ( domainName ) if err := common . CheckEventBlobSizeLimit ( len ( failedRequest . Details ) , sizeLimitWarn , sizeLimitError , taskToken . DomainID , taskToken . WorkflowID , taskToken . RunID , scope , wh . GetThrottledLogger ( ) , tag . BlobSizeViolationOperation ( " " ) , ) ; err != nil { failedRequest . Details = failedRequest . Details [ 0 : sizeLimitError ] } err = wh . GetHistoryClient ( ) . RespondDecisionTaskFailed ( ctx , & types . HistoryRespondDecisionTaskFailedRequest { DomainUUID : taskToken . DomainID , FailedRequest : failedRequest , } ) if err != nil { return wh . normalizeVersionedErrors ( ctx , wh . error ( err , scope , tags ... ) ) } return nil }
failed response to a decision task
failed response to a decision task
// Count the request in the host RPS, // but we still accept it even if RPS is exceeded // details exceed, we would just truncate the size for decision task failed as the details is not used anywhere by client code