fix: pass external error on PutWorkflow (#401)

* fix: pass external error on PutWorkflow

* fix: don't set duration as pointer to empty string
This commit is contained in:
abelanger5
2024-04-22 11:35:17 +02:00
committed by GitHub
parent 23a5709b88
commit fcdbfbf0ab
5 changed files with 51 additions and 7 deletions
+1 -1
View File
@@ -106,7 +106,7 @@ type CreateWorkflowStepOpts struct {
Action string `validate:"required,actionId"`
// (optional) the step timeout
Timeout *string
Timeout *string `validate:"omitempty,duration"`
// (optional) the parents that this step depends on
Parents []string `validate:"dive,hatchetName"`
+15 -1
View File
@@ -6,6 +6,7 @@ import (
"github.com/hatchet-dev/hatchet/internal/msgqueue"
"github.com/hatchet-dev/hatchet/internal/repository"
"github.com/hatchet-dev/hatchet/internal/services/admin/contracts"
"github.com/hatchet-dev/hatchet/internal/validator"
)
type AdminService interface {
@@ -17,6 +18,7 @@ type AdminServiceImpl struct {
repo repository.EngineRepository
mq msgqueue.MessageQueue
v validator.Validator
}
type AdminServiceOpt func(*AdminServiceOpts)
@@ -24,10 +26,15 @@ type AdminServiceOpt func(*AdminServiceOpts)
type AdminServiceOpts struct {
repo repository.EngineRepository
mq msgqueue.MessageQueue
v validator.Validator
}
func defaultAdminServiceOpts() *AdminServiceOpts {
return &AdminServiceOpts{}
v := validator.NewDefaultValidator()
return &AdminServiceOpts{
v: v,
}
}
func WithRepository(r repository.EngineRepository) AdminServiceOpt {
@@ -42,6 +49,12 @@ func WithMessageQueue(mq msgqueue.MessageQueue) AdminServiceOpt {
}
}
func WithValidator(v validator.Validator) AdminServiceOpt {
return func(opts *AdminServiceOpts) {
opts.v = v
}
}
func NewAdminService(fs ...AdminServiceOpt) (AdminService, error) {
opts := defaultAdminServiceOpts()
@@ -60,5 +73,6 @@ func NewAdminService(fs ...AdminServiceOpt) (AdminService, error) {
return &AdminServiceImpl{
repo: opts.repo,
mq: opts.mq,
v: opts.v,
}, nil
}
+14 -1
View File
@@ -142,6 +142,16 @@ func (a *AdminServiceImpl) PutWorkflow(ctx context.Context, req *contracts.PutWo
return nil, err
}
// validate createOpts
if apiErrors, err := a.v.ValidateAPI(createOpts); err != nil {
return nil, err
} else if apiErrors != nil {
return nil, status.Error(
codes.InvalidArgument,
apiErrors.String(),
)
}
// determine if workflow already exists
var workflowVersion *dbsqlc.GetWorkflowVersionForEngineRow
var oldWorkflowVersion *dbsqlc.GetWorkflowVersionForEngineRow
@@ -355,11 +365,14 @@ func getCreateWorkflowOpts(req *contracts.PutWorkflowRequest) (*repository.Creat
steps[j] = repository.CreateWorkflowStepOpts{
ReadableId: stepCp.ReadableId,
Action: parsedAction.String(),
Timeout: &stepCp.Timeout,
Parents: stepCp.Parents,
Retries: &retries,
}
if stepCp.Timeout != "" {
steps[j].Timeout = &stepCp.Timeout
}
for _, rateLimit := range stepCp.RateLimits {
steps[j].RateLimits = append(steps[j].RateLimits, repository.CreateWorkflowStepRateLimitOpts{
Key: rateLimit.Key,
+20 -3
View File
@@ -18,8 +18,23 @@ const (
HatchetNameErr = "Hatchet names must match the regex ^[a-zA-Z0-9\\.\\-_]+$"
ActionIDErr = "Invalid action ID. Action IDs must be in the format <integrationId>:<verb>"
CronErr = "Invalid cron expression"
DurationErr = "Invalid duration. Durations must be in the format <number><unit>, where unit is one of: 's', 'm', 'h', 'd', 'w', 'M', 'y'"
)
type APIErrors gen.APIErrors
func (a *APIErrors) String() string {
var sb strings.Builder
sb.WriteString("Validation failed with the following errors:\n")
for i, err := range a.Errors {
sb.WriteString(fmt.Sprintf("%d: %s\n", i, err.Description))
}
return sb.String()
}
// Validator will validate the fields for a request object to ensure that
// the request is well-formed. For example, it searches for required fields
// or verifies that fields are of a semantic type (like email)
@@ -28,7 +43,7 @@ type Validator interface {
// error that is meant to be shown to the end user as a readable string.
Validate(s interface{}) error
ValidateAPI(s interface{}) (*gen.APIErrors, error)
ValidateAPI(s interface{}) (*APIErrors, error)
}
// DefaultValidator uses the go-playground v10 validator for verifying that
@@ -43,7 +58,7 @@ func NewDefaultValidator() Validator {
return &DefaultValidator{newValidator()}
}
func (v *DefaultValidator) ValidateAPI(s interface{}) (*gen.APIErrors, error) {
func (v *DefaultValidator) ValidateAPI(s interface{}) (*APIErrors, error) {
err := v.v10.Struct(s)
if err == nil {
@@ -68,7 +83,7 @@ func (v *DefaultValidator) ValidateAPI(s interface{}) (*gen.APIErrors, error) {
apiErrors[i].Field = &fieldStr
}
return &gen.APIErrors{
return &APIErrors{
Errors: apiErrors,
}, nil
}
@@ -115,6 +130,8 @@ func getErrorStr(errObj *ValidationErrObject) string {
return errObj.SafeExternalError(ActionIDErr)
case "cron":
return errObj.SafeExternalError(CronErr)
case "duration":
return errObj.SafeExternalError(DurationErr)
default:
return errObj.SafeExternalError("")
}
+1 -1
View File
@@ -78,7 +78,7 @@ func (a *adminClientImpl) PutWorkflow(workflow *types.Workflow, fs ...PutOptFunc
_, err = a.client.PutWorkflow(a.ctx.newContext(context.Background()), req)
if err != nil {
return fmt.Errorf("could not create workflow: %w", err)
return fmt.Errorf("could not create workflow %s: %w", workflow.Name, err)
}
return nil