github.com/songzhibin97/gkit@v1.2.13/distributed/backend/result/async_result.go (about)

     1  package result
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"reflect"
     7  	"time"
     8  
     9  	"github.com/songzhibin97/gkit/distributed/backend"
    10  	"github.com/songzhibin97/gkit/distributed/task"
    11  )
    12  
    13  // ErrBackendEmpty ...
    14  var ErrBackendEmpty = errors.New("backend is empty")
    15  
    16  // AsyncResult 异步结果
    17  type AsyncResult struct {
    18  	Signature *task.Signature // Signature 任务签名
    19  	state     *task.Status    // state 任务状态
    20  	backend   backend.Backend // backend 执行的实现
    21  }
    22  
    23  // ChainAsyncResult 链式调用任务结果返回
    24  type ChainAsyncResult struct {
    25  	asyncResult []*AsyncResult
    26  	backend     backend.Backend // backend 执行的实现
    27  }
    28  
    29  // GroupCallbackAsyncResult 具有回调任务的个任务组异步结果
    30  type GroupCallbackAsyncResult struct {
    31  	groupAsyncResult    []*AsyncResult
    32  	callbackAsyncResult *AsyncResult
    33  	backend             backend.Backend // backend 执行的实现
    34  }
    35  
    36  // NewAsyncResult 创建异步任务返回结果
    37  func NewAsyncResult(signature *task.Signature, backend backend.Backend) *AsyncResult {
    38  	return &AsyncResult{
    39  		Signature: signature,
    40  		state:     &task.Status{},
    41  		backend:   backend,
    42  	}
    43  }
    44  
    45  // NewChainAsyncResult 创建链式调用任务返回结果
    46  func NewChainAsyncResult(chainAsyncResult []*task.Signature, backend backend.Backend) *ChainAsyncResult {
    47  	asyncResults := make([]*AsyncResult, 0, len(chainAsyncResult))
    48  	for _, signature := range chainAsyncResult {
    49  		asyncResults = append(asyncResults, NewAsyncResult(signature, backend))
    50  	}
    51  	return &ChainAsyncResult{
    52  		asyncResult: asyncResults,
    53  		backend:     backend,
    54  	}
    55  }
    56  
    57  // NewGroupCallbackAsyncResult 创建具有回调任务组的异步返回结果
    58  func NewGroupCallbackAsyncResult(groupAsyncResult []*task.Signature, callbackAsyncResult *task.Signature, backend backend.Backend) *GroupCallbackAsyncResult {
    59  	asyncResults := make([]*AsyncResult, 0, len(groupAsyncResult))
    60  	for _, signature := range groupAsyncResult {
    61  		asyncResults = append(asyncResults, NewAsyncResult(signature, backend))
    62  	}
    63  	return &GroupCallbackAsyncResult{
    64  		groupAsyncResult:    asyncResults,
    65  		callbackAsyncResult: NewAsyncResult(callbackAsyncResult, backend),
    66  		backend:             backend,
    67  	}
    68  }
    69  
    70  // Get 返回结果
    71  func (asyncResult *AsyncResult) Get(sleepDuration time.Duration) ([]reflect.Value, error) {
    72  	for {
    73  		results, err := asyncResult.Monitor()
    74  		if results == nil && err == nil {
    75  			time.Sleep(sleepDuration)
    76  		} else {
    77  			return results, err
    78  		}
    79  	}
    80  }
    81  
    82  // GetWithTimeout 返回结果 带有超时时间
    83  func (asyncResult *AsyncResult) GetWithTimeout(timeoutDuration, sleepDuration time.Duration) ([]reflect.Value, error) {
    84  	ctx, cancer := context.WithTimeout(context.Background(), timeoutDuration)
    85  	defer cancer()
    86  	for {
    87  		select {
    88  		case <-ctx.Done():
    89  			return nil, ctx.Err()
    90  		default:
    91  			results, err := asyncResult.Monitor()
    92  			if results == nil && err == nil {
    93  				time.Sleep(sleepDuration)
    94  			} else {
    95  				return results, err
    96  			}
    97  		}
    98  	}
    99  }
   100  
   101  // Monitor 监视任务
   102  func (asyncResult *AsyncResult) Monitor() ([]reflect.Value, error) {
   103  	if asyncResult.backend == nil {
   104  		return nil, ErrBackendEmpty
   105  	}
   106  
   107  	asyncResult.GetState()
   108  	if asyncResult.state.IsFailure() {
   109  		return nil, errors.New(asyncResult.state.Error)
   110  	}
   111  	if asyncResult.state.IsSuccess() {
   112  		return task.ReflectTaskResults(asyncResult.state.Results)
   113  	}
   114  	return nil, nil
   115  }
   116  
   117  // GetState 获取任务状态
   118  func (asyncResult *AsyncResult) GetState() *task.Status {
   119  	if asyncResult.state.IsCompleted() {
   120  		return asyncResult.state
   121  	}
   122  	taskState, err := asyncResult.backend.GetStatus(asyncResult.Signature.ID)
   123  	if err == nil {
   124  		asyncResult.state = taskState
   125  	}
   126  	return asyncResult.state
   127  }
   128  
   129  // Get 返回结果
   130  func (chainAsyncResult *ChainAsyncResult) Get(sleepDuration time.Duration) ([]reflect.Value, error) {
   131  	if chainAsyncResult.backend == nil {
   132  		return nil, ErrBackendEmpty
   133  	}
   134  	var (
   135  		results []reflect.Value
   136  		err     error
   137  	)
   138  	for _, result := range chainAsyncResult.asyncResult {
   139  		results, err = result.Get(sleepDuration)
   140  		if err != nil {
   141  			return nil, err
   142  		}
   143  	}
   144  	return results, err
   145  }
   146  
   147  // GetWithTimeout 返回结果 带有超时时间
   148  func (chainAsyncResult *ChainAsyncResult) GetWithTimeout(timeoutDuration, sleepDuration time.Duration) ([]reflect.Value, error) {
   149  	if chainAsyncResult.backend == nil {
   150  		return nil, ErrBackendEmpty
   151  	}
   152  	var (
   153  		results    []reflect.Value
   154  		err        error
   155  		ln         = len(chainAsyncResult.asyncResult)
   156  		lastResult = chainAsyncResult.asyncResult[ln-1]
   157  	)
   158  	ctx, cancel := context.WithTimeout(context.Background(), timeoutDuration)
   159  	defer cancel()
   160  	for {
   161  		select {
   162  		case <-ctx.Done():
   163  			return nil, ctx.Err()
   164  		default:
   165  			for _, result := range chainAsyncResult.asyncResult {
   166  				_, err = result.Monitor()
   167  				if err != nil {
   168  					return nil, err
   169  				}
   170  			}
   171  			results, err = lastResult.Monitor()
   172  			if err != nil {
   173  				return nil, err
   174  			}
   175  			if results != nil {
   176  				return results, err
   177  			}
   178  			time.Sleep(sleepDuration)
   179  		}
   180  	}
   181  }
   182  
   183  // Get 返回结果
   184  func (groupCallbackAsyncResult *GroupCallbackAsyncResult) Get(sleepDuration time.Duration) ([]reflect.Value, error) {
   185  	if groupCallbackAsyncResult.backend == nil {
   186  		return nil, ErrBackendEmpty
   187  	}
   188  	var err error
   189  	for _, result := range groupCallbackAsyncResult.groupAsyncResult {
   190  		_, err = result.Get(sleepDuration)
   191  		if err != nil {
   192  			return nil, err
   193  		}
   194  	}
   195  	return groupCallbackAsyncResult.callbackAsyncResult.Get(sleepDuration)
   196  }
   197  
   198  // GetWithTimeout 返回结果 带有超时时间
   199  func (groupCallbackAsyncResult *GroupCallbackAsyncResult) GetWithTimeout(timeoutDuration, sleepDuration time.Duration) ([]reflect.Value, error) {
   200  	if groupCallbackAsyncResult.backend == nil {
   201  		return nil, ErrBackendEmpty
   202  	}
   203  	var (
   204  		results []reflect.Value
   205  		err     error
   206  	)
   207  	ctx, cancel := context.WithTimeout(context.Background(), timeoutDuration)
   208  	defer cancel()
   209  	for {
   210  		select {
   211  		case <-ctx.Done():
   212  			return nil, ctx.Err()
   213  		default:
   214  			for _, result := range groupCallbackAsyncResult.groupAsyncResult {
   215  				_, err = result.Monitor()
   216  				if err != nil {
   217  					return nil, err
   218  				}
   219  			}
   220  			results, err = groupCallbackAsyncResult.callbackAsyncResult.Monitor()
   221  			if err != nil {
   222  				return nil, err
   223  			}
   224  			if results != nil {
   225  				return results, err
   226  			}
   227  			time.Sleep(sleepDuration)
   228  		}
   229  	}
   230  }