in service/frontend/api/handler.go [1823:1962]
func (wh *WorkflowHandler) validateStartWorkflowExecutionRequest(ctx context.Context, startRequest *types.StartWorkflowExecutionRequest, scope metrics.Scope) error {
if startRequest == nil {
return validate.ErrRequestNotSet
}
domainName := startRequest.GetDomain()
if domainName == "" {
return validate.ErrDomainNotSet
}
if startRequest.GetWorkflowID() == "" {
return validate.ErrWorkflowIDNotSet
}
if _, err := uuid.Parse(startRequest.RequestID); err != nil {
return &types.BadRequestError{Message: fmt.Sprintf("requestId %q is not a valid UUID", startRequest.RequestID)}
}
if startRequest.WorkflowType == nil || startRequest.WorkflowType.GetName() == "" {
return validate.ErrWorkflowTypeNotSet
}
if err := wh.versionChecker.ClientSupported(ctx, wh.config.EnableClientVersionCheck()); err != nil {
return err
}
idLengthWarnLimit := wh.config.MaxIDLengthWarnLimit()
if !common.IsValidIDLength(
domainName,
scope,
idLengthWarnLimit,
wh.config.DomainNameMaxLength(domainName),
metrics.CadenceErrDomainNameExceededWarnLimit,
domainName,
wh.GetLogger(),
tag.IDTypeDomainName) {
return validate.ErrDomainTooLong
}
if !common.IsValidIDLength(
startRequest.GetWorkflowID(),
scope,
idLengthWarnLimit,
wh.config.WorkflowIDMaxLength(domainName),
metrics.CadenceErrWorkflowIDExceededWarnLimit,
domainName,
wh.GetLogger(),
tag.IDTypeWorkflowID) {
return validate.ErrWorkflowIDTooLong
}
if err := common.ValidateRetryPolicy(startRequest.RetryPolicy); err != nil {
return err
}
wh.GetLogger().Debug(
"Received StartWorkflowExecution. WorkflowID",
tag.WorkflowID(startRequest.GetWorkflowID()))
if !common.IsValidIDLength(
startRequest.WorkflowType.GetName(),
scope,
idLengthWarnLimit,
wh.config.WorkflowTypeMaxLength(domainName),
metrics.CadenceErrWorkflowTypeExceededWarnLimit,
domainName,
wh.GetLogger(),
tag.IDTypeWorkflowType) {
return validate.ErrWorkflowTypeTooLong
}
if err := wh.validateTaskList(startRequest.TaskList, scope, domainName); err != nil {
return err
}
if startRequest.GetExecutionStartToCloseTimeoutSeconds() <= 0 {
return validate.ErrInvalidExecutionStartToCloseTimeoutSeconds
}
if startRequest.GetTaskStartToCloseTimeoutSeconds() <= 0 {
return validate.ErrInvalidTaskStartToCloseTimeoutSeconds
}
if startRequest.GetDelayStartSeconds() < 0 {
return validate.ErrInvalidDelayStartSeconds
}
if startRequest.GetJitterStartSeconds() < 0 {
return validate.ErrInvalidJitterStartSeconds
}
jitter := startRequest.GetJitterStartSeconds()
cron := startRequest.GetCronSchedule()
if cron != "" {
if _, err := backoff.ValidateSchedule(startRequest.GetCronSchedule()); err != nil {
return err
}
}
if jitter > 0 && cron != "" {
// Calculate the cron duration and ensure that jitter is not greater than the cron duration,
// because that would be confusing to users.
// Request using start/end time zero value, which will get us an exact answer (i.e. its not in the
// middle of a minute)
backoffSeconds, err := backoff.GetBackoffForNextScheduleInSeconds(cron, time.Time{}, time.Time{}, jitter)
if err != nil {
return err
}
if jitter > backoffSeconds {
return validate.ErrInvalidJitterStartSeconds2
}
}
if !common.IsValidIDLength(
startRequest.GetRequestID(),
scope,
idLengthWarnLimit,
wh.config.RequestIDMaxLength(domainName),
metrics.CadenceErrRequestIDExceededWarnLimit,
domainName,
wh.GetLogger(),
tag.IDTypeRequestID) {
return validate.ErrRequestIDTooLong
}
if err := wh.searchAttributesValidator.ValidateSearchAttributes(startRequest.SearchAttributes, domainName); err != nil {
return err
}
wh.GetLogger().Debug("Start workflow execution request domain", tag.WorkflowDomainName(domainName))
domainID, err := wh.GetDomainCache().GetDomainID(domainName)
if err != nil {
return err
}
sizeLimitError := wh.config.BlobSizeLimitError(domainName)
sizeLimitWarn := wh.config.BlobSizeLimitWarn(domainName)
actualSize := len(startRequest.Input)
if startRequest.Memo != nil {
actualSize += common.GetSizeOfMapStringToByteArray(startRequest.Memo.GetFields())
}
if err := common.CheckEventBlobSizeLimit(
actualSize,
sizeLimitWarn,
sizeLimitError,
domainID,
startRequest.GetWorkflowID(),
"",
scope,
wh.GetThrottledLogger(),
tag.BlobSizeViolationOperation("StartWorkflowExecution"),
); err != nil {
return err
}
isolationGroup := wh.getIsolationGroup(ctx, domainName)
if !wh.isIsolationGroupHealthy(ctx, domainName, isolationGroup) {
return &types.BadRequestError{fmt.Sprintf("Domain %s is drained from isolation group %s.", domainName, isolationGroup)}
}
return nil
}