Skip to content

Commit

Permalink
service: update error types to make them more logicless, simplify val…
Browse files Browse the repository at this point in the history
…idations. closes #350, related with #348, a part of #337

* error types now doesn't call methods from its struct fields for validation.
* remove isValid and Validate methods from types and adapt generic service.ValidateParametersSchema() method.
* TestValidParameters removed from service package. no longer needed.
  • Loading branch information
ilgooz committed Aug 28, 2018
1 parent 9961a3b commit ca32d86
Show file tree
Hide file tree
Showing 10 changed files with 218 additions and 237 deletions.
4 changes: 2 additions & 2 deletions api/emit_event_emitter.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ func newEventEmitter(api *API) *eventEmitter {

// Emit emits a MESG event eventKey with eventData for service token.
func (e *eventEmitter) Emit(token, eventKey string, eventData map[string]interface{}) error {
service, err := services.Get(token)
s, err := services.Get(token)
if err != nil {
return err
}
event, err := event.Create(&service, eventKey, eventData)
event, err := event.Create(&s, eventKey, eventData)
if err != nil {
return err
}
Expand Down
12 changes: 6 additions & 6 deletions event/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@ func Create(serviceForEvent *service.Service, eventKey string, data map[string]i
serviceEvent, eventFound := serviceForEvent.Events[eventKey]
if !eventFound {
return nil, &service.EventNotFoundError{
Service: serviceForEvent,
EventKey: eventKey,
EventKey: eventKey,
ServiceName: serviceForEvent.Name,
}
}
if !serviceEvent.IsValid(data) {
warnings := serviceForEvent.ValidateParametersSchema(serviceEvent.Data, data)
if len(warnings) > 0 {
return nil, &service.InvalidEventDataError{
Event: serviceEvent,
EventKey: eventKey,
EventData: data,
EventKey: eventKey,
Warnings: warnings,
}
}
return &Event{
Expand Down
20 changes: 10 additions & 10 deletions execution/complete.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,18 @@ import (
func (execution *Execution) Complete(output string, data map[string]interface{}) error {
serviceOutput, outputFound := execution.Service.Tasks[execution.Task].Outputs[output]
if !outputFound {
return &service.OutputNotFoundError{
Service: execution.Service,
OutputKey: output,
TaskKey: execution.Task,
return &service.TaskOutputNotFoundError{
TaskKey: execution.Task,
TaskOutputKey: output,
ServiceName: execution.Service.Name,
}
}
if !serviceOutput.IsValid(data) {
return &service.InvalidOutputDataError{
Output: serviceOutput,
TaskKey: execution.Task,
OutputKey: output,
OutputData: data,
warnings := execution.Service.ValidateParametersSchema(serviceOutput.Data, data)
if len(warnings) > 0 {
return &service.InvalidTaskOutputError{
TaskKey: execution.Task,
TaskOutputKey: output,
Warnings: warnings,
}
}
err := execution.moveFromInProgressToProcessed()
Expand Down
8 changes: 4 additions & 4 deletions execution/complete_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ func TestCompleteNotFound(t *testing.T) {
var outputs map[string]interface{}
err := execution.Complete("output", outputs)
require.NotNil(t, err)
x, missingOutputError := err.(*service.OutputNotFoundError)
x, missingOutputError := err.(*service.TaskOutputNotFoundError)
require.True(t, missingOutputError)
require.Equal(t, "output", x.OutputKey)
require.Equal(t, "output", x.TaskOutputKey)
}

func TestCompleteInvalidOutputs(t *testing.T) {
Expand All @@ -68,9 +68,9 @@ func TestCompleteInvalidOutputs(t *testing.T) {
var outputs map[string]interface{}
err := execution.Complete("output", outputs)
require.NotNil(t, err)
x, invalidOutputError := err.(*service.InvalidOutputDataError)
x, invalidOutputError := err.(*service.InvalidTaskOutputError)
require.True(t, invalidOutputError)
require.Equal(t, "output", x.OutputKey)
require.Equal(t, "output", x.TaskOutputKey)
}

func TestCompleteNotProcessed(t *testing.T) {
Expand Down
12 changes: 6 additions & 6 deletions execution/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ func Create(serviceForExecution *service.Service, task string, inputs map[string
serviceTask, taskFound := serviceForExecution.Tasks[task]
if !taskFound {
return nil, &service.TaskNotFoundError{
Service: serviceForExecution,
TaskKey: task,
TaskKey: task,
ServiceName: serviceForExecution.Name,
}
}
if !serviceTask.IsValid(inputs) {
warnings := serviceForExecution.ValidateParametersSchema(serviceTask.Inputs, inputs)
if len(warnings) > 0 {
return nil, &service.InvalidTaskInputError{
Task: serviceTask,
TaskKey: task,
InputData: inputs,
TaskKey: task,
Warnings: warnings,
}
}
execution := &Execution{
Expand Down
14 changes: 9 additions & 5 deletions service/cast.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ type caster func(value string) (interface{}, error)
func castString(value string) (interface{}, error) {
return value, nil
}

func castNumber(value string) (interface{}, error) {
i, err := strconv.ParseInt(value, 10, 64)
if err == nil {
Expand Down Expand Up @@ -48,17 +49,20 @@ var casters = map[string]caster{
func (s *Service) Cast(taskKey string, taskData map[string]string) (map[string]interface{}, error) {
task, ok := s.Tasks[taskKey]
if !ok {
return nil, &TaskNotFoundError{Service: s, TaskKey: taskKey}
return nil, &TaskNotFoundError{
TaskKey: taskKey,
ServiceName: s.Name,
}
}

m := make(map[string]interface{}, len(taskData))
for key, value := range taskData {
inputType, ok := task.Inputs[key]
if !ok {
return nil, &InputNotFoundError{
Service: s,
TaskKey: taskKey,
InputKey: key,
return nil, &TaskInputNotFoundError{
TaskKey: taskKey,
TaskInputKey: key,
ServiceName: s.Name,
}
}

Expand Down
113 changes: 56 additions & 57 deletions service/error.go
Original file line number Diff line number Diff line change
@@ -1,89 +1,88 @@
package service

// EventNotFoundError is an error when an event cannot be found in a service.
import "fmt"

// EventNotFoundError is an error returned when corresponding event cannot be found in service.
type EventNotFoundError struct {
Service *Service
EventKey string
EventKey string
ServiceName string
}

func (e *EventNotFoundError) Error() string {
return "Event '" + e.EventKey + "' not found in service '" + e.Service.Name + "'"
return fmt.Sprintf("Event %q not found in service %q", e.EventKey, e.ServiceName)
}

// InvalidEventDataError is an error when the data of an event are not valid.
type InvalidEventDataError struct {
Event *Event
EventKey string
EventData map[string]interface{}
// TaskNotFoundError is an error returned when corresponding task cannot be found in service.
type TaskNotFoundError struct {
TaskKey string
ServiceName string
}

func (e *InvalidEventDataError) Error() string {
errorString := "Data of event '" + e.EventKey + "' is invalid"
for _, warning := range e.Event.Validate(e.EventData) {
errorString = errorString + ". " + warning.String()
}
return errorString
func (e *TaskNotFoundError) Error() string {
return fmt.Sprintf("Task %q not found in service %q", e.TaskKey, e.ServiceName)
}

// TaskNotFoundError is an error when a task cannot be found in a service.
type TaskNotFoundError struct {
Service *Service
TaskKey string
// TaskInputNotFoundError is an error returned when service doesn't contain corresponding input.
type TaskInputNotFoundError struct {
TaskKey string
TaskInputKey string
ServiceName string
}

func (e *TaskNotFoundError) Error() string {
return "Task '" + e.TaskKey + "' not found in service '" + e.Service.Name + "'"
func (e *TaskInputNotFoundError) Error() string {
return fmt.Sprintf("Input %q of task %q not found in service %q", e.TaskInputKey, e.TaskKey, e.ServiceName)
}

// InvalidTaskInputError is an error when the inputs of a task are not valid.
type InvalidTaskInputError struct {
Task *Task
TaskKey string
InputData map[string]interface{}
// TaskOutputNotFoundError is an error returned when service doesn't contain corresponding output.
type TaskOutputNotFoundError struct {
TaskKey string
TaskOutputKey string
ServiceName string
}

func (e *InvalidTaskInputError) Error() string {
errorString := "Inputs of task '" + e.TaskKey + "' are invalid"
for _, warning := range e.Task.Validate(e.InputData) {
errorString = errorString + ". " + warning.String()
}
return errorString
func (e *TaskOutputNotFoundError) Error() string {
return fmt.Sprintf("Output %q of task %q not found in service %q", e.TaskOutputKey, e.TaskKey, e.ServiceName)
}

// InputNotFoundError is an error when a service doesn't contains a specific input.
type InputNotFoundError struct {
Service *Service
TaskKey string
InputKey string
// InvalidEventDataError is an error returned when the data of corresponding event is not valid.
type InvalidEventDataError struct {
EventKey string
Warnings []*ParameterWarning
}

func (e *InputNotFoundError) Error() string {
return "Input '" + e.InputKey + "' of task '" + e.TaskKey + "' not found in service '" + e.Service.Name + "'"
func (e *InvalidEventDataError) Error() string {
s := fmt.Sprintf("Data of event %q is invalid", e.EventKey)
for _, warning := range e.Warnings {
s = fmt.Sprintf("%s. %s", s, warning)
}
return s
}

// OutputNotFoundError is an error when a service doesn't contain a specific output.
type OutputNotFoundError struct {
Service *Service
TaskKey string
OutputKey string
// InvalidTaskInputError is an error returned when the inputs of corresponding task are not valid.
type InvalidTaskInputError struct {
TaskKey string
Warnings []*ParameterWarning
}

func (e *OutputNotFoundError) Error() string {
return "Output '" + e.OutputKey + "' of task '" + e.TaskKey + "' not found in service '" + e.Service.Name + "'"
func (e *InvalidTaskInputError) Error() string {
s := fmt.Sprintf("Inputs of task %q are invalid", e.TaskKey)
for _, warning := range e.Warnings {
s = fmt.Sprintf("%s. %s", s, warning)
}
return s
}

// InvalidOutputDataError is an error when the outputs for one task result are not valid.
type InvalidOutputDataError struct {
Output *Output
TaskKey string
OutputKey string
OutputData map[string]interface{}
// InvalidTaskOutputError is an error returned when the outputs of corresponding task are not valid.
type InvalidTaskOutputError struct {
TaskKey string
TaskOutputKey string
Warnings []*ParameterWarning
}

func (e *InvalidOutputDataError) Error() string {
errorString := "Outputs '" + e.OutputKey + "' of task '" + e.TaskKey + "' are invalid"
for _, warning := range e.Output.Validate(e.OutputData) {
errorString = errorString + ". " + warning.String()
func (e *InvalidTaskOutputError) Error() string {
s := fmt.Sprintf("Outputs %q of task %q are invalid", e.TaskOutputKey, e.TaskKey)
for _, warning := range e.Warnings {
s = fmt.Sprintf("%s. %s", s, warning)
}
return errorString
return s
}
Loading

0 comments on commit ca32d86

Please sign in to comment.