github.com/kaydxh/golang@v0.0.131/pkg/scheduler/task/task.go (about)

     1  /*
     2   *Copyright (c) 2022, kaydxh
     3   *
     4   *Permission is hereby granted, free of charge, to any person obtaining a copy
     5   *of this software and associated documentation files (the "Software"), to deal
     6   *in the Software without restriction, including without limitation the rights
     7   *to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     8   *copies of the Software, and to permit persons to whom the Software is
     9   *furnished to do so, subject to the following conditions:
    10   *
    11   *The above copyright notice and this permission notice shall be included in all
    12   *copies or substantial portions of the Software.
    13   *
    14   *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    15   *IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    16   *FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    17   *AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    18   *LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    19   *OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    20   *SOFTWARE.
    21   */
    22  package task
    23  
    24  import (
    25  	"reflect"
    26  
    27  	reflect_ "github.com/kaydxh/golang/go/reflect"
    28  )
    29  
    30  type Task struct {
    31  	TaskId   string
    32  	TaskFunc interface{}
    33  	Args     []TaskArgument
    34  	//	TaskStatus
    35  	PreTaskHandler  func(*Task) error
    36  	PostTaskHandler func(*Task) error
    37  }
    38  
    39  // Types which can be used: bool, string, int int8 int16 int32 int64, uint uint8 uint16 uint32 uint64, float32 float64
    40  type TaskArgument struct {
    41  	Type  string      `json:"type"`
    42  	Value interface{} `json:"value"`
    43  }
    44  
    45  func (t *Task) Run() ([]*TaskResult, error) {
    46  
    47  	reflectTaskFunc := reflect.ValueOf(t.TaskFunc)
    48  	reflectTaskArgs, err := reflectTaskArgs(t.Args)
    49  	if err != nil {
    50  		return nil, err
    51  	}
    52  
    53  	results := reflectTaskFunc.Call(reflectTaskArgs)
    54  	return reflectTaskResults(results)
    55  }
    56  
    57  func reflectTaskArgs(args []TaskArgument) ([]reflect.Value, error) {
    58  	argValues := make([]reflect.Value, len(args))
    59  
    60  	for i, arg := range args {
    61  		argValue, err := reflect_.ReflectValue(arg.Type, arg.Value)
    62  		if err != nil {
    63  			return nil, err
    64  		}
    65  		argValues[i] = argValue
    66  	}
    67  
    68  	return argValues, nil
    69  }
    70  
    71  func reflectTaskResults(results []reflect.Value) ([]*TaskResult, error) {
    72  	// Task must return at least a value
    73  	if len(results) == 0 {
    74  		return nil, ErrTaskReturnsNoValue
    75  	}
    76  
    77  	// Last returned value
    78  	lastResult := results[len(results)-1]
    79  	if !lastResult.IsNil() {
    80  		// check that the result implements the standard error interface,
    81  		// if not, return ErrLastReturnValueMustBeError error
    82  		errorInterface := reflect.TypeOf((*error)(nil)).Elem()
    83  		if !lastResult.Type().Implements(errorInterface) {
    84  			return nil, ErrLastReturnValueMustBeError
    85  		}
    86  
    87  		// Return the standard error
    88  		return nil, lastResult.Interface().(error)
    89  	}
    90  
    91  	// Convert reflect values to task results
    92  	taskResults := make([]*TaskResult, len(results)-1)
    93  	for i := 0; i < len(results)-1; i++ {
    94  		val := results[i].Interface()
    95  		typeStr := reflect.TypeOf(val).String()
    96  		taskResults[i] = &TaskResult{
    97  			Type:  typeStr,
    98  			Value: val,
    99  		}
   100  	}
   101  
   102  	return taskResults, nil
   103  }