mirror of
https://github.com/hatchet-dev/hatchet.git
synced 2026-05-24 12:28:35 -05:00
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:
@@ -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"`
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user