init task
parent
e2e29db2d1
commit
8be1a8ff3b
|
@ -0,0 +1,398 @@
|
|||
/*
|
||||
* Tencent is pleased to support the open source community by making Blueking Container Service available.
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under
|
||||
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// Package task is a package for task management
|
||||
package task
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/RichardKnop/machinery/v2"
|
||||
"github.com/RichardKnop/machinery/v2/backends/mongo"
|
||||
"github.com/RichardKnop/machinery/v2/brokers/amqp"
|
||||
"github.com/RichardKnop/machinery/v2/config"
|
||||
"github.com/RichardKnop/machinery/v2/locks/eager"
|
||||
"github.com/RichardKnop/machinery/v2/tasks"
|
||||
|
||||
types "git.ifooth.com/common/machinery-plugins/task/types"
|
||||
)
|
||||
|
||||
const (
|
||||
// DefaultWorkerConcurrency default worker concurrency
|
||||
DefaultWorkerConcurrency = 10
|
||||
)
|
||||
|
||||
// BrokerConfig config for go-machinery broker
|
||||
type BrokerConfig struct {
|
||||
QueueAddress string `json:"address"`
|
||||
Exchange string `json:"exchange"`
|
||||
}
|
||||
|
||||
// Manager manager for task server
|
||||
type Manager struct {
|
||||
moduleName string
|
||||
lock sync.Locker
|
||||
server *machinery.Server
|
||||
worker *machinery.Worker
|
||||
|
||||
brokerConfig *BrokerConfig
|
||||
|
||||
workerNum int
|
||||
stepWorkers map[string]StepWorkerInterface
|
||||
callBackFuncs map[string]CallbackInterface
|
||||
}
|
||||
|
||||
// ManagerConfig options for manager
|
||||
type ManagerConfig struct {
|
||||
ModuleName string
|
||||
StepWorkers []StepWorkerInterface
|
||||
CallBacks []CallbackInterface
|
||||
WorkerNum int
|
||||
Broker *BrokerConfig
|
||||
}
|
||||
|
||||
// NewManager create new manager
|
||||
func NewManager() *Manager {
|
||||
m := &Manager{
|
||||
lock: &sync.Mutex{},
|
||||
workerNum: DefaultWorkerConcurrency,
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// Init init machinery server and worker
|
||||
func (m *Manager) Init(cfg *ManagerConfig) error {
|
||||
err := m.validate(cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m.brokerConfig = cfg.Broker
|
||||
m.moduleName = cfg.ModuleName
|
||||
if cfg.WorkerNum != 0 {
|
||||
m.workerNum = cfg.WorkerNum
|
||||
}
|
||||
|
||||
// save step workers and check duplicate
|
||||
for _, w := range cfg.StepWorkers {
|
||||
if _, ok := m.stepWorkers[w.GetName()]; ok {
|
||||
return fmt.Errorf("step [%s] already exists", w.GetName())
|
||||
}
|
||||
m.stepWorkers[w.GetName()] = w
|
||||
}
|
||||
|
||||
// save callbacks and check duplicate
|
||||
for _, c := range cfg.CallBacks {
|
||||
if _, ok := m.callBackFuncs[c.GetName()]; ok {
|
||||
return fmt.Errorf("callback func [%s] already exists", c.GetName())
|
||||
}
|
||||
m.callBackFuncs[c.GetName()] = c
|
||||
}
|
||||
|
||||
if err := m.initServer(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := m.initWorker(cfg.WorkerNum); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Manager) validate(c *ManagerConfig) error {
|
||||
// module name check
|
||||
if c.ModuleName == "" {
|
||||
return fmt.Errorf("module name is empty")
|
||||
}
|
||||
|
||||
// step worker check
|
||||
if c.StepWorkers == nil || len(c.StepWorkers) == 0 {
|
||||
return fmt.Errorf("step worker is empty")
|
||||
}
|
||||
|
||||
// broker config check
|
||||
if c.Broker == nil || c.Broker.Exchange == "" || c.Broker.QueueAddress == "" {
|
||||
return fmt.Errorf("broker config is empty")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Manager) initServer() error {
|
||||
|
||||
config := &config.Config{
|
||||
Broker: m.brokerConfig.QueueAddress,
|
||||
DefaultQueue: m.brokerConfig.Exchange,
|
||||
ResultsExpireIn: 3600 * 48,
|
||||
|
||||
AMQP: &config.AMQPConfig{
|
||||
Exchange: m.brokerConfig.Exchange,
|
||||
ExchangeType: "direct",
|
||||
BindingKey: m.brokerConfig.Exchange,
|
||||
PrefetchCount: 50,
|
||||
},
|
||||
}
|
||||
broker := amqp.New(config)
|
||||
backend, err := mongo.New(config)
|
||||
if err != nil {
|
||||
return fmt.Errorf("task server init mongo backend failed, %s", err.Error())
|
||||
}
|
||||
lock := eager.New()
|
||||
m.server = machinery.NewServer(config, broker, backend, lock)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// register step workers and init workers
|
||||
func (m *Manager) initWorker(workerNum int) error {
|
||||
// register all workers
|
||||
if err := m.registerStepWorkers(); err != nil {
|
||||
return fmt.Errorf("register workers failed, err: %s", err.Error())
|
||||
}
|
||||
|
||||
m.worker = m.server.NewWorker("", workerNum)
|
||||
|
||||
preTaskHandler := func(signature *tasks.Signature) {
|
||||
fmt.Printf("start task handler for: %s", signature.Name)
|
||||
}
|
||||
postTaskHandler := func(signature *tasks.Signature) {
|
||||
fmt.Printf("end task handler for: %s", signature.Name)
|
||||
}
|
||||
errorHandler := func(err error) {
|
||||
fmt.Printf("task error handler: %s", err)
|
||||
}
|
||||
|
||||
m.worker.SetPreTaskHandler(preTaskHandler)
|
||||
m.worker.SetPostTaskHandler(postTaskHandler)
|
||||
m.worker.SetErrorHandler(errorHandler)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Run start worker
|
||||
func (m *Manager) Run() {
|
||||
// start worker
|
||||
go func() {
|
||||
if err := m.worker.Launch(); err != nil {
|
||||
errMsg := fmt.Sprintf("task server worker launch failed, %s", err.Error())
|
||||
panic(errMsg)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// GetTaskWithID get task by taskid
|
||||
func (m *Manager) GetTaskWithID(ctx context.Context, taskid string) (*types.Task, error) {
|
||||
return getGlobalStorage().GetTask(ctx, taskid)
|
||||
}
|
||||
|
||||
// UpdateTask update task
|
||||
// ! warning: modify task status will cause task status not consistent
|
||||
func (m *Manager) UpdateTask(ctx context.Context, task *types.Task) error {
|
||||
return getGlobalStorage().UpdateTask(ctx, task)
|
||||
}
|
||||
|
||||
// PatchTaskInfo update task info
|
||||
// ! warning: modify task status will cause task status not consistent
|
||||
func (m *Manager) PatchTaskInfo(ctx context.Context, taskID string, patchs map[string]interface{}) error {
|
||||
// warning:
|
||||
return getGlobalStorage().PatchTask(ctx, taskID, patchs)
|
||||
}
|
||||
|
||||
// RetryAll reset status to running and dispatch all tasks
|
||||
func (m *Manager) RetryAll(task *types.Task) error {
|
||||
task.SetStatus(types.TaskStatusRunning)
|
||||
task.SetMessage("task retrying")
|
||||
|
||||
if err := getGlobalStorage().UpdateTask(context.Background(), task); err != nil {
|
||||
return err
|
||||
}
|
||||
return m.dispatchAt(task, "")
|
||||
}
|
||||
|
||||
// RetryAt reset status to running and dispatch tasks which begin with stepName
|
||||
func (m *Manager) RetryAt(task *types.Task, stepName string) error {
|
||||
task.SetStatus(types.TaskStatusRunning)
|
||||
task.SetMessage("task retrying")
|
||||
|
||||
if err := getGlobalStorage().UpdateTask(context.Background(), task); err != nil {
|
||||
return err
|
||||
}
|
||||
return m.dispatchAt(task, stepName)
|
||||
}
|
||||
|
||||
// Dispatch dispatch task
|
||||
func (m *Manager) Dispatch(task *types.Task) error {
|
||||
if err := getGlobalStorage().CreateTask(context.Background(), task); err != nil {
|
||||
return err
|
||||
}
|
||||
return m.dispatchAt(task, "")
|
||||
}
|
||||
|
||||
// dispatchAt task to machinery
|
||||
func (m *Manager) dispatchAt(task *types.Task, stepNameBegin string) error {
|
||||
var signatures []*tasks.Signature
|
||||
for _, stepName := range task.StepSequence {
|
||||
// skip steps which before begin step, empty str not skip any steps
|
||||
if stepName != "" && stepName != stepNameBegin {
|
||||
continue
|
||||
}
|
||||
signature := &tasks.Signature{
|
||||
UUID: fmt.Sprintf("task-%s-%s", task.GetTaskID(), stepName),
|
||||
Name: stepName,
|
||||
// two parameters: taskID, stepName
|
||||
Args: []tasks.Arg{{Type: "string", Value: task.GetTaskID()}, {Type: "string", Value: stepName}},
|
||||
IgnoreWhenTaskNotRegistered: true,
|
||||
}
|
||||
signatures = append(signatures, signature)
|
||||
}
|
||||
|
||||
m.lock.Lock()
|
||||
defer m.lock.Unlock()
|
||||
|
||||
// create chain
|
||||
chain, _ := tasks.NewChain(signatures...)
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
if task.GetMaxExecutionSeconds() != time.Duration(0) {
|
||||
ctx, cancelFunc = context.WithTimeout(ctx, task.GetMaxExecutionSeconds())
|
||||
}
|
||||
defer cancelFunc()
|
||||
|
||||
//send chain to machinery
|
||||
asyncResult, err := m.server.SendChainWithContext(ctx, chain)
|
||||
if err != nil {
|
||||
return fmt.Errorf("send chain to machinery failed: %s", err.Error())
|
||||
}
|
||||
|
||||
// get results
|
||||
go func(t *types.Task, c *tasks.Chain) {
|
||||
// check async results
|
||||
for retry := 3; retry > 0; retry-- {
|
||||
results, err := asyncResult.Get(time.Second * 5)
|
||||
if err != nil {
|
||||
fmt.Printf("tracing task %s result failed, %s. retry %d", t.GetTaskID(), err.Error(), retry)
|
||||
continue
|
||||
}
|
||||
// check results
|
||||
fmt.Printf("tracing task %s result %s", t.GetTaskID(), tasks.HumanReadableResults(results))
|
||||
}
|
||||
}(task, chain)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// registerStepWorkers build machinery workers for all step worker
|
||||
func (m *Manager) registerStepWorkers() error {
|
||||
allTasks := make(map[string]interface{}, 0)
|
||||
for stepName, stepWorker := range m.stepWorkers {
|
||||
do := stepWorker.DoWork
|
||||
|
||||
t := func(taskID string, stepName string) error {
|
||||
start := time.Now()
|
||||
state, step, err := m.getTaskStateAndCurrentStep(taskID, stepName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// step executed success
|
||||
if step == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), step.GetMaxExecutionSeconds())
|
||||
defer cancel()
|
||||
stepDone := make(chan bool, 1)
|
||||
|
||||
go func() {
|
||||
// call step worker
|
||||
if err = do(state); err != nil {
|
||||
if err := state.updateStepFailure(start, step.GetStepName(), err); err != nil {
|
||||
fmt.Printf("update step %s to failure failed: %s", step.GetStepName(), err.Error())
|
||||
}
|
||||
|
||||
// step done
|
||||
stepDone <- true
|
||||
return
|
||||
}
|
||||
|
||||
if err := state.updateStepSuccess(start, step.GetStepName()); err != nil {
|
||||
fmt.Printf("update step %s to success failed: %s", step.GetStepName(), err.Error())
|
||||
}
|
||||
|
||||
// step done
|
||||
stepDone <- true
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
retErr := fmt.Errorf("step %s timeout", step.GetStepName())
|
||||
if err := state.updateStepFailure(start, step.GetStepName(), retErr); err != nil {
|
||||
fmt.Printf("update step %s to failure failed: %s", step.GetStepName(), err.Error())
|
||||
}
|
||||
if !step.GetSkipOnFailed() {
|
||||
return retErr
|
||||
}
|
||||
return nil
|
||||
case <-stepDone:
|
||||
// step done
|
||||
if err != nil && !step.GetSkipOnFailed() {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
if _, ok := allTasks[stepName]; ok {
|
||||
return fmt.Errorf("task %s already exists", stepName)
|
||||
}
|
||||
allTasks[stepName] = t
|
||||
}
|
||||
err := m.server.RegisterTasks(allTasks)
|
||||
return err
|
||||
}
|
||||
|
||||
// getTaskStateAndCurrentStep get task state and current step
|
||||
func (m *Manager) getTaskStateAndCurrentStep(taskid, stepName string) (*State, *types.Step, error) {
|
||||
task, err := getGlobalStorage().GetTask(context.Background(), taskid)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("get task %s information failed, %s", taskid, err.Error())
|
||||
}
|
||||
|
||||
if task.CommonParams == nil {
|
||||
task.CommonParams = make(map[string]string, 0)
|
||||
}
|
||||
|
||||
state := NewState(task, stepName)
|
||||
if state.isTaskTerminated() {
|
||||
return nil, nil, fmt.Errorf("task %s is terminated, step %s skip", taskid, stepName)
|
||||
}
|
||||
step, err := state.isReadyToStep(stepName)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("task %s step %s is not ready, %s", taskid, stepName, err.Error())
|
||||
}
|
||||
if step == nil {
|
||||
// step successful and skip
|
||||
return state, nil, nil
|
||||
}
|
||||
|
||||
// inject call back func
|
||||
if state.task.GetCallback() != "" {
|
||||
if callback, ok := m.callBackFuncs[state.task.GetCallback()]; ok {
|
||||
state.callBack = callback.Callback
|
||||
}
|
||||
}
|
||||
|
||||
return state, nil, nil
|
||||
}
|
|
@ -0,0 +1,285 @@
|
|||
/*
|
||||
* Tencent is pleased to support the open source community by making Blueking Container Service available.
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under
|
||||
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// Package task is a package for task management
|
||||
package task
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
types "git.ifooth.com/common/machinery-plugins/task/types"
|
||||
)
|
||||
|
||||
// State is a struct for task state
|
||||
type State struct {
|
||||
task *types.Task
|
||||
currentStep string
|
||||
callBack func(isSuccess bool, task *types.Task)
|
||||
}
|
||||
|
||||
// NewState return state relative to task
|
||||
func NewState(task *types.Task, currentStep string) *State {
|
||||
return &State{
|
||||
task: task,
|
||||
currentStep: currentStep,
|
||||
}
|
||||
}
|
||||
|
||||
// isTaskTerminated is terminated
|
||||
func (s *State) isTaskTerminated() bool {
|
||||
status := s.task.GetStatus()
|
||||
if status == types.TaskStatusFailure || status == types.TaskStatusForceTerminate ||
|
||||
status == types.TaskStatusTimeout || status == types.TaskStatusSuccess {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// isReadyToStep check if step is ready to step
|
||||
func (s *State) isReadyToStep(stepName string) (*types.Step, error) {
|
||||
switch s.task.GetStatus() {
|
||||
case types.TaskStatusRunning, types.TaskStatusInit:
|
||||
case types.TaskStatusForceTerminate:
|
||||
return nil, fmt.Errorf("task %s state for terminate", s.task.GetTaskID())
|
||||
default:
|
||||
return nil, fmt.Errorf("task %s is not running, state is %s", s.task.GetTaskID(), s.task.GetStatus())
|
||||
}
|
||||
|
||||
// validate step existence
|
||||
curStep, ok := s.task.GetStep(stepName)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("step %s is not exist", stepName)
|
||||
}
|
||||
|
||||
// return nil & nil means step had been executed
|
||||
if curStep.GetStatus() == types.TaskStatusSuccess {
|
||||
// step is success, skip
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// not first time to execute current step
|
||||
if stepName == s.task.GetCurrentStep() {
|
||||
if curStep.GetStatus() == types.TaskStatusFailure {
|
||||
curStep.AddRetryCount(1)
|
||||
}
|
||||
|
||||
nowTime := time.Now()
|
||||
curStep = curStep.SetStartTime(nowTime).
|
||||
SetStatus(types.TaskStatusRunning).
|
||||
SetMessage("step ready to run").
|
||||
SetLastUpdate(nowTime)
|
||||
|
||||
// update Task in storage
|
||||
if err := getGlobalStorage().UpdateTask(context.Background(), s.task); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return curStep, nil
|
||||
}
|
||||
|
||||
// first time to execute step
|
||||
for _, name := range s.task.StepSequence {
|
||||
step, ok := s.task.GetStep(name)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("step %s is not exist", stepName)
|
||||
}
|
||||
|
||||
// find current step
|
||||
if name == stepName {
|
||||
// step already success
|
||||
if step.GetStatus() == types.TaskStatusSuccess {
|
||||
return nil, fmt.Errorf("task %s step %s already success", s.task.GetTaskID(), stepName)
|
||||
}
|
||||
// set current step
|
||||
nowTime := time.Now()
|
||||
s.task.SetCurrentStep(stepName)
|
||||
step = step.SetStartTime(nowTime).
|
||||
SetStatus(types.TaskStatusRunning).
|
||||
SetMessage("step ready to run").
|
||||
SetLastUpdate(nowTime)
|
||||
|
||||
// update Task in storage
|
||||
if err := getGlobalStorage().UpdateTask(context.Background(), s.task); err != nil {
|
||||
return nil, fmt.Errorf("update task %s step %s status error", s.task.GetTaskID(), stepName)
|
||||
}
|
||||
return step, nil
|
||||
}
|
||||
|
||||
// skip step if step allow skipOnFailed
|
||||
if step.SkipOnFailed {
|
||||
continue
|
||||
}
|
||||
// previous step execute failure
|
||||
if step.GetStatus() != types.TaskStatusSuccess {
|
||||
break
|
||||
}
|
||||
}
|
||||
// previous step execute failure
|
||||
return nil, fmt.Errorf("step %s is not ready", stepName)
|
||||
}
|
||||
|
||||
// updateStepSuccess update step status to success
|
||||
func (s *State) updateStepSuccess(start time.Time, stepName string) error {
|
||||
step, ok := s.task.GetStep(stepName)
|
||||
if !ok {
|
||||
return fmt.Errorf("step %s is not exist", stepName)
|
||||
}
|
||||
endTime := time.Now()
|
||||
|
||||
step.SetStartTime(start).
|
||||
SetEndTime(endTime).
|
||||
SetExecutionTime(start, endTime).
|
||||
SetStatus(types.TaskStatusSuccess).
|
||||
SetMessage(fmt.Sprintf("step %s running successfully", step.Name)).
|
||||
SetLastUpdate(endTime)
|
||||
|
||||
s.task.SetStatus(types.TaskStatusRunning).
|
||||
SetMessage(fmt.Sprintf("step %s running successfully", step.Name)).
|
||||
SetLastUpdate(endTime)
|
||||
|
||||
// last step
|
||||
if s.isLastStep(stepName) {
|
||||
taskStartTime, err := s.task.GetStartTime()
|
||||
if err != nil {
|
||||
return fmt.Errorf(fmt.Sprintf("get task %s start time error", s.task.GetTaskID()))
|
||||
}
|
||||
s.task.SetEndTime(endTime).
|
||||
SetExecutionTime(taskStartTime, endTime).
|
||||
SetStatus(types.TaskStatusSuccess).
|
||||
SetMessage("task finished successfully")
|
||||
|
||||
// callback
|
||||
if s.callBack != nil {
|
||||
s.callBack(true, s.task)
|
||||
}
|
||||
}
|
||||
|
||||
// update Task in storage
|
||||
if err := getGlobalStorage().UpdateTask(context.Background(), s.task); err != nil {
|
||||
return fmt.Errorf("update task %s status error", s.task.GetTaskID())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// updateStepFailure update step status to failure
|
||||
func (s *State) updateStepFailure(start time.Time, stepName string, stepErr error) error {
|
||||
step, ok := s.task.GetStep(stepName)
|
||||
if !ok {
|
||||
return fmt.Errorf("step %s is not exist", stepName)
|
||||
}
|
||||
endTime := time.Now()
|
||||
|
||||
step.SetStartTime(start).
|
||||
SetEndTime(endTime).
|
||||
SetExecutionTime(start, endTime).
|
||||
SetStatus(types.TaskStatusFailure).
|
||||
SetMessage(fmt.Sprintf("running failed, %s", stepErr.Error())).
|
||||
SetLastUpdate(endTime)
|
||||
|
||||
// if step SkipOnFailed, update task status to running
|
||||
if step.GetSkipOnFailed() {
|
||||
// skip, set task running or success
|
||||
s.task.SetStatus(types.TaskStatusRunning).
|
||||
SetMessage(fmt.Sprintf("step %s running failed", step.Name)).
|
||||
SetLastUpdate(endTime)
|
||||
|
||||
// last step failed and skipOnFailed is true, update task status to success
|
||||
if s.isLastStep(stepName) {
|
||||
// last step
|
||||
taskStartTime, err := s.task.GetStartTime()
|
||||
if err != nil {
|
||||
return fmt.Errorf(fmt.Sprintf("get task %s start time error", s.task.GetTaskID()))
|
||||
}
|
||||
s.task.SetStatus(types.TaskStatusSuccess).
|
||||
SetMessage("task finished successfully").
|
||||
SetLastUpdate(endTime).
|
||||
SetEndTime(endTime).
|
||||
SetExecutionTime(taskStartTime, endTime)
|
||||
|
||||
// callback
|
||||
if s.callBack != nil {
|
||||
s.callBack(true, s.task)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// not skip, set task faile
|
||||
s.task.SetStatus(types.TaskStatusFailure).
|
||||
SetMessage(fmt.Sprintf("step %s running failed", step.Name)).
|
||||
SetLastUpdate(endTime).
|
||||
SetEndTime(endTime).
|
||||
SetExecutionTime(start, endTime)
|
||||
|
||||
// callback
|
||||
if s.callBack != nil {
|
||||
s.callBack(false, s.task)
|
||||
}
|
||||
}
|
||||
|
||||
// update Task in storage
|
||||
if err := getGlobalStorage().UpdateTask(context.Background(), s.task); err != nil {
|
||||
return fmt.Errorf("update task %s status error", s.task.GetTaskID())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *State) isLastStep(stepName string) bool {
|
||||
return stepName == s.task.StepSequence[len(s.task.StepSequence)-1]
|
||||
}
|
||||
|
||||
// GetCommonParams get common params by key
|
||||
func (s *State) GetCommonParams(key string) (string, bool) {
|
||||
return s.task.GetCommonParams(key)
|
||||
}
|
||||
|
||||
// AddCommonParams add common params
|
||||
func (s *State) AddCommonParams(key, value string) *State {
|
||||
s.task.AddCommonParams(key, value)
|
||||
return s
|
||||
}
|
||||
|
||||
// GetExtraParams get extra params by obj
|
||||
func (s *State) GetExtraParams(obj interface{}) error {
|
||||
return s.task.GetExtra(obj)
|
||||
}
|
||||
|
||||
// SetExtraAll set extra params by obj
|
||||
func (s *State) SetExtraAll(obj interface{}) error {
|
||||
return s.task.SetExtraAll(obj)
|
||||
}
|
||||
|
||||
// GetStepParam get step params by key
|
||||
func (s *State) GetStepParam(stepName, key string) (string, bool) {
|
||||
return s.task.GetStepParam(stepName, key)
|
||||
}
|
||||
|
||||
// AddStepParams add step params
|
||||
func (s *State) AddStepParams(stepName, key, value string) error {
|
||||
return s.task.AddStepParams(stepName, key, value)
|
||||
}
|
||||
|
||||
// GetTask get task
|
||||
func (s *State) GetTask() *types.Task {
|
||||
return s.task
|
||||
}
|
||||
|
||||
// GetCurrentStep get current step
|
||||
func (s *State) GetCurrentStep() (*types.Step, bool) {
|
||||
return s.task.GetStep(s.currentStep)
|
||||
}
|
||||
|
||||
// GetStep get step by stepName
|
||||
func (s *State) GetStep(stepName string) (*types.Step, bool) {
|
||||
return s.task.GetStep(stepName)
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Tencent is pleased to support the open source community by making Blueking Container Service available.
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under
|
||||
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// Package task is a package for task management
|
||||
package task
|
||||
|
||||
import store "git.ifooth.com/common/machinery-plugins/task/store"
|
||||
|
||||
var (
|
||||
// globalStorage used for state and task manager
|
||||
globalStorage store.TaskManagerModel
|
||||
)
|
||||
|
||||
// GetStorageModel for cluster manager storage tools
|
||||
func getGlobalStorage() store.TaskManagerModel {
|
||||
return globalStorage
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Tencent is pleased to support the open source community by making Blueking Container Service available.
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under
|
||||
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// Package store implements task storage
|
||||
package store
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.ifooth.com/common/machinery-plugins/task/types"
|
||||
)
|
||||
|
||||
// ListOption options for list task
|
||||
type ListOption struct {
|
||||
// Sort map for sort list results
|
||||
Sort map[string]int
|
||||
// Offset offset for list results
|
||||
Offset int64
|
||||
// Limit limit for list results
|
||||
Limit int64
|
||||
// All for all results
|
||||
All bool
|
||||
// Count for index
|
||||
Count bool
|
||||
// SkipDecrypt skip data decrypt
|
||||
SkipDecrypt bool
|
||||
}
|
||||
|
||||
// TaskManagerModel model for TaskManager
|
||||
type TaskManagerModel interface {
|
||||
// task information storage management
|
||||
CreateTask(ctx context.Context, task *types.Task) error
|
||||
UpdateTask(ctx context.Context, task *types.Task) error
|
||||
PatchTask(ctx context.Context, taskID string, patchs map[string]interface{}) error
|
||||
DeleteTask(ctx context.Context, taskID string) error
|
||||
GetTask(ctx context.Context, taskID string) (*types.Task, error)
|
||||
ListTask(ctx context.Context, cond any, opt *ListOption) ([]types.Task, error)
|
||||
}
|
||||
|
||||
// ModelSet model for task
|
||||
type ModelSet struct {
|
||||
}
|
|
@ -0,0 +1,236 @@
|
|||
/*
|
||||
* Tencent is pleased to support the open source community by making Blueking Container Service available.
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under
|
||||
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// Package types for task
|
||||
package types
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Step step definition
|
||||
type Step struct {
|
||||
Name string `json:"name" bson:"name"`
|
||||
TaskName string `json:"taskname" bson:"taskname"`
|
||||
Params map[string]string `json:"params" bson:"params"`
|
||||
Extras string `json:"extras" bson:"extras"`
|
||||
Status string `json:"status" bson:"status"`
|
||||
Message string `json:"message" bson:"message"`
|
||||
SkipOnFailed bool `json:"skipOnFailed" bson:"skipOnFailed"`
|
||||
RetryCount uint32 `json:"retryCount" bson:"retryCount"`
|
||||
|
||||
Start string `json:"start" bson:"start"`
|
||||
End string `json:"end" bson:"end"`
|
||||
ExecutionTime uint32 `json:"executionTime" bson:"executionTime"`
|
||||
MaxExecutionSeconds uint32 `json:"maxExecutionSeconds" bson:"maxExecutionSeconds"`
|
||||
LastUpdate string `json:"lastUpdate" bson:"lastUpdate"`
|
||||
}
|
||||
|
||||
// NewStep return a new step by default params
|
||||
func NewStep(stepName string, taskName string) *Step {
|
||||
return &Step{
|
||||
Name: stepName,
|
||||
TaskName: taskName,
|
||||
Params: map[string]string{},
|
||||
Extras: DefaultJsonExtrasContent,
|
||||
Status: TaskStatusNotStarted,
|
||||
Message: "",
|
||||
SkipOnFailed: false,
|
||||
RetryCount: 0,
|
||||
MaxExecutionSeconds: DefaultMaxExecuteTimeSeconds,
|
||||
}
|
||||
}
|
||||
|
||||
// GetStepName return step name
|
||||
func (s *Step) GetStepName() string {
|
||||
return s.Name
|
||||
}
|
||||
|
||||
// SetStepName set step name
|
||||
func (s *Step) SetStepName(name string) *Step {
|
||||
s.Name = name
|
||||
return s
|
||||
}
|
||||
|
||||
// GetTaskName return task name
|
||||
func (s *Step) GetTaskName() string {
|
||||
return s.TaskName
|
||||
}
|
||||
|
||||
// SetTaskName set task name
|
||||
func (s *Step) SetTaskName(taskName string) *Step {
|
||||
s.TaskName = taskName
|
||||
return s
|
||||
}
|
||||
|
||||
// GetParam return step param by key
|
||||
func (s *Step) GetParam(key string) (string, bool) {
|
||||
if value, ok := s.Params[key]; ok {
|
||||
return value, true
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
// AddParam set step param by key,value
|
||||
func (s *Step) AddParam(key, value string) *Step {
|
||||
if s.Params == nil {
|
||||
s.Params = make(map[string]string, 0)
|
||||
}
|
||||
s.Params[key] = value
|
||||
return s
|
||||
}
|
||||
|
||||
// GetParamsAll return all step params
|
||||
func (s *Step) GetParamsAll() map[string]string {
|
||||
if s.Params == nil {
|
||||
s.Params = make(map[string]string, 0)
|
||||
}
|
||||
return s.Params
|
||||
}
|
||||
|
||||
// SetParamMulti set step params by map
|
||||
func (s *Step) SetParamMulti(params map[string]string) {
|
||||
if s.Params == nil {
|
||||
s.Params = make(map[string]string, 0)
|
||||
}
|
||||
for key, value := range params {
|
||||
s.Params[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
// SetNewParams replace all params by new params
|
||||
func (s *Step) SetNewParams(params map[string]string) *Step {
|
||||
s.Params = params
|
||||
return s
|
||||
}
|
||||
|
||||
// GetExtras return unmarshal step extras
|
||||
func (s *Step) GetExtras(obj interface{}) error {
|
||||
if s.Extras == "" {
|
||||
s.Extras = DefaultJsonExtrasContent
|
||||
}
|
||||
return json.Unmarshal([]byte(s.Extras), obj)
|
||||
}
|
||||
|
||||
// SetExtrasAll set step extras by json string
|
||||
func (s *Step) SetExtrasAll(obj interface{}) error {
|
||||
result, err := json.Marshal(obj)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.Extras = string(result)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetStatus return step status
|
||||
func (s *Step) GetStatus() string {
|
||||
return s.Status
|
||||
}
|
||||
|
||||
// SetStatus set status
|
||||
func (s *Step) SetStatus(stat string) *Step {
|
||||
s.Status = stat
|
||||
return s
|
||||
}
|
||||
|
||||
// GetMessage get step message
|
||||
func (s *Step) GetMessage() string {
|
||||
if s.Message == "" {
|
||||
return ""
|
||||
}
|
||||
return s.Message
|
||||
}
|
||||
|
||||
// SetMessage set step message
|
||||
func (s *Step) SetMessage(msg string) *Step {
|
||||
s.Message = msg
|
||||
return s
|
||||
}
|
||||
|
||||
// GetSkipOnFailed get step skipOnFailed
|
||||
func (s *Step) GetSkipOnFailed() bool {
|
||||
return s.SkipOnFailed
|
||||
}
|
||||
|
||||
// SetSkipOnFailed set step skipOnFailed
|
||||
func (s *Step) SetSkipOnFailed(skipOnFailed bool) *Step {
|
||||
s.SkipOnFailed = skipOnFailed
|
||||
return s
|
||||
}
|
||||
|
||||
// GetRetryCount get step retry count
|
||||
func (s *Step) GetRetryCount() uint32 {
|
||||
return s.RetryCount
|
||||
}
|
||||
|
||||
// AddRetryCount add step retry count
|
||||
func (s *Step) AddRetryCount(count uint32) *Step {
|
||||
s.RetryCount += count
|
||||
return s
|
||||
}
|
||||
|
||||
// GetStartTime get start time
|
||||
func (s *Step) GetStartTime() (time.Time, error) {
|
||||
return time.Parse(TaskTimeFormat, s.Start)
|
||||
}
|
||||
|
||||
// SetStartTime update start time
|
||||
func (s *Step) SetStartTime(t time.Time) *Step {
|
||||
s.Start = t.Format(TaskTimeFormat)
|
||||
return s
|
||||
}
|
||||
|
||||
// GetEndTime get end time
|
||||
func (s *Step) GetEndTime() (time.Time, error) {
|
||||
return time.Parse(TaskTimeFormat, s.End)
|
||||
}
|
||||
|
||||
// SetEndTime set end time
|
||||
func (s *Step) SetEndTime(t time.Time) *Step {
|
||||
// set end time
|
||||
s.End = t.Format(TaskTimeFormat)
|
||||
return s
|
||||
}
|
||||
|
||||
// GetExecutionTime set execution time
|
||||
func (s *Step) GetExecutionTime() time.Duration {
|
||||
return time.Duration(time.Duration(s.ExecutionTime) * time.Millisecond)
|
||||
}
|
||||
|
||||
// SetExecutionTime set execution time
|
||||
func (s *Step) SetExecutionTime(start time.Time, end time.Time) *Step {
|
||||
s.ExecutionTime = uint32(end.Sub(start).Milliseconds())
|
||||
return s
|
||||
}
|
||||
|
||||
// GetMaxExecutionSeconds get max execution seconds
|
||||
func (s *Step) GetMaxExecutionSeconds() time.Duration {
|
||||
return time.Duration(time.Duration(s.MaxExecutionSeconds) * time.Second)
|
||||
}
|
||||
|
||||
// SetMaxExecutionSeconds set max execution seconds
|
||||
func (s *Step) SetMaxExecutionSeconds(maxExecutionSeconds time.Duration) *Step {
|
||||
s.MaxExecutionSeconds = uint32(maxExecutionSeconds.Seconds())
|
||||
return s
|
||||
}
|
||||
|
||||
// GetLastUpdate get last update time
|
||||
func (s *Step) GetLastUpdate() (time.Time, error) {
|
||||
return time.Parse(TaskTimeFormat, s.LastUpdate)
|
||||
}
|
||||
|
||||
// SetLastUpdate set last update time
|
||||
func (s *Step) SetLastUpdate(t time.Time) *Step {
|
||||
s.LastUpdate = t.Format(TaskTimeFormat)
|
||||
return s
|
||||
}
|
|
@ -0,0 +1,323 @@
|
|||
/*
|
||||
* Tencent is pleased to support the open source community by making Blueking Container Service available.
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under
|
||||
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// Package types for task
|
||||
package types
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// Task task definition
|
||||
type Task struct {
|
||||
// index for task, client should set this field
|
||||
Index string `json:"index" bson:"index"`
|
||||
TaskID string `json:"taskId" bson:"taskId"`
|
||||
TaskType string `json:"taskType" bson:"taskType"`
|
||||
TaskName string `json:"taskName" bson:"taskName"`
|
||||
// steps and params
|
||||
CurrentStep string `json:"currentStep" bson:"currentStep"`
|
||||
StepSequence []string `json:"stepSequence" bson:"stepSequence"`
|
||||
Steps map[string]*Step `json:"steps" bson:"steps"`
|
||||
CallBackFuncName string `json:"callBackFuncName" bson:"callBackFuncName"`
|
||||
CommonParams map[string]string `json:"commonParams" bson:"commonParams"`
|
||||
ExtraJson string `json:"extraJson" bson:"extraJson"`
|
||||
|
||||
Status string `json:"status" bson:"status"`
|
||||
Message string `json:"message" bson:"message"`
|
||||
ForceTerminate bool `json:"forceTerminate" bson:"forceTerminate"`
|
||||
Start string `json:"start" bson:"start"`
|
||||
End string `json:"end" bson:"end"`
|
||||
ExecutionTime uint32 `json:"executionTime" bson:"executionTime"`
|
||||
MaxExecutionSeconds uint32 `json:"maxExecutionSeconds" bson:"maxExecutionSeconds"`
|
||||
Creator string `json:"creator" bson:"creator"`
|
||||
LastUpdate string `json:"lastUpdate" bson:"lastUpdate"`
|
||||
Updater string `json:"updater" bson:"updater"`
|
||||
}
|
||||
|
||||
// TaskOptions task options definition
|
||||
type TaskOptions struct {
|
||||
TaskIndex string
|
||||
TaskType string
|
||||
TaskName string
|
||||
Creator string
|
||||
CallBackFuncName string
|
||||
}
|
||||
|
||||
// NewTask create new task by default
|
||||
func NewTask(o *TaskOptions) *Task {
|
||||
nowTime := time.Now().Format(TaskTimeFormat)
|
||||
return &Task{
|
||||
Index: o.TaskIndex,
|
||||
TaskID: uuid.NewString(),
|
||||
TaskType: o.TaskType,
|
||||
TaskName: o.TaskName,
|
||||
Status: TaskStatusInit,
|
||||
ForceTerminate: false,
|
||||
Start: nowTime,
|
||||
Steps: make(map[string]*Step, 0),
|
||||
StepSequence: make([]string, 0),
|
||||
Creator: o.Creator,
|
||||
Updater: o.Creator,
|
||||
LastUpdate: nowTime,
|
||||
CommonParams: make(map[string]string, 0),
|
||||
ExtraJson: DefaultJsonExtrasContent,
|
||||
CallBackFuncName: o.CallBackFuncName,
|
||||
}
|
||||
}
|
||||
|
||||
// GetTaskID get task id
|
||||
func (t *Task) GetTaskID() string {
|
||||
return t.TaskID
|
||||
}
|
||||
|
||||
// GetIndex get task id
|
||||
func (t *Task) GetIndex() string {
|
||||
return t.Index
|
||||
}
|
||||
|
||||
// GetTaskType get task type
|
||||
func (t *Task) GetTaskType() string {
|
||||
return t.TaskType
|
||||
}
|
||||
|
||||
// GetTaskName get task name
|
||||
func (t *Task) GetTaskName() string {
|
||||
return t.TaskName
|
||||
}
|
||||
|
||||
// GetStep get step by name
|
||||
func (t *Task) GetStep(stepName string) (*Step, bool) {
|
||||
if _, ok := t.Steps[stepName]; !ok {
|
||||
return nil, false
|
||||
}
|
||||
return t.Steps[stepName], true
|
||||
}
|
||||
|
||||
// AddStep add step to task
|
||||
func (t *Task) AddStep(step *Step) *Task {
|
||||
if step == nil {
|
||||
return t
|
||||
}
|
||||
|
||||
if t.StepSequence == nil {
|
||||
t.StepSequence = make([]string, 0)
|
||||
}
|
||||
t.StepSequence = append(t.StepSequence, step.GetStepName())
|
||||
t.Steps[step.GetStepName()] = step
|
||||
return t
|
||||
}
|
||||
|
||||
// GetCommonParams get common params
|
||||
func (t *Task) GetCommonParams(key string) (string, bool) {
|
||||
if t.CommonParams == nil {
|
||||
t.CommonParams = make(map[string]string, 0)
|
||||
return "", false
|
||||
}
|
||||
if value, ok := t.CommonParams[key]; ok {
|
||||
return value, true
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
// AddCommonParams add common params
|
||||
func (t *Task) AddCommonParams(k, v string) *Task {
|
||||
if t.CommonParams == nil {
|
||||
t.CommonParams = make(map[string]string, 0)
|
||||
}
|
||||
t.CommonParams[k] = v
|
||||
return t
|
||||
}
|
||||
|
||||
// GetCallback set callback function name
|
||||
func (t *Task) GetCallback() string {
|
||||
return t.CallBackFuncName
|
||||
}
|
||||
|
||||
// SetCallback set callback function name
|
||||
func (t *Task) SetCallback(callBackFuncName string) *Task {
|
||||
t.CallBackFuncName = callBackFuncName
|
||||
return t
|
||||
}
|
||||
|
||||
// GetExtra get extra json
|
||||
func (t *Task) GetExtra(obj interface{}) error {
|
||||
if t.ExtraJson == "" {
|
||||
t.ExtraJson = DefaultJsonExtrasContent
|
||||
}
|
||||
return json.Unmarshal([]byte(t.ExtraJson), obj)
|
||||
}
|
||||
|
||||
// SetExtraAll set extra json
|
||||
func (t *Task) SetExtraAll(obj interface{}) error {
|
||||
result, err := json.Marshal(obj)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
t.ExtraJson = string(result)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetStatus get status
|
||||
func (t *Task) GetStatus() string {
|
||||
return t.Status
|
||||
}
|
||||
|
||||
// SetStatus set status
|
||||
func (t *Task) SetStatus(status string) *Task {
|
||||
t.Status = status
|
||||
return t
|
||||
}
|
||||
|
||||
// GetMessage set message
|
||||
func (t *Task) GetMessage(msg string) string {
|
||||
return t.Message
|
||||
}
|
||||
|
||||
// SetMessage set message
|
||||
func (t *Task) SetMessage(msg string) *Task {
|
||||
t.Message = msg
|
||||
return t
|
||||
}
|
||||
|
||||
// GetForceTerminate get force terminate
|
||||
func (t *Task) GetForceTerminate() bool {
|
||||
return t.ForceTerminate
|
||||
}
|
||||
|
||||
// SetForceTerminate set force terminate
|
||||
func (t *Task) SetForceTerminate(f bool) *Task {
|
||||
t.ForceTerminate = f
|
||||
return t
|
||||
}
|
||||
|
||||
// GetStartTime get start time
|
||||
func (t *Task) GetStartTime() (time.Time, error) {
|
||||
return time.Parse(TaskTimeFormat, t.Start)
|
||||
}
|
||||
|
||||
// SetStartTime set start time
|
||||
func (t *Task) SetStartTime(time time.Time) *Task {
|
||||
t.Start = time.Format(TaskTimeFormat)
|
||||
return t
|
||||
}
|
||||
|
||||
// GetEndTime get end time
|
||||
func (t *Task) GetEndTime() (time.Time, error) {
|
||||
return time.Parse(TaskTimeFormat, t.End)
|
||||
}
|
||||
|
||||
// SetEndTime set end time
|
||||
func (t *Task) SetEndTime(time time.Time) *Task {
|
||||
t.End = time.Format(TaskTimeFormat)
|
||||
return t
|
||||
}
|
||||
|
||||
// GetExecutionTime get execution time
|
||||
func (t *Task) GetExecutionTime() time.Duration {
|
||||
return time.Duration(time.Duration(t.ExecutionTime) * time.Millisecond)
|
||||
}
|
||||
|
||||
// SetExecutionTime set execution time
|
||||
func (t *Task) SetExecutionTime(start time.Time, end time.Time) *Task {
|
||||
t.ExecutionTime = uint32(end.Sub(start).Milliseconds())
|
||||
return t
|
||||
}
|
||||
|
||||
// GetMaxExecutionSeconds get max execution seconds
|
||||
func (t *Task) GetMaxExecutionSeconds() time.Duration {
|
||||
return time.Duration(time.Duration(t.MaxExecutionSeconds) * time.Second)
|
||||
}
|
||||
|
||||
// SetMaxExecutionSeconds set max execution seconds
|
||||
func (t *Task) SetMaxExecutionSeconds(maxExecutionSeconds time.Duration) *Task {
|
||||
t.MaxExecutionSeconds = uint32(maxExecutionSeconds.Seconds())
|
||||
return t
|
||||
}
|
||||
|
||||
// GetCreator get creator
|
||||
func (t *Task) GetCreator() string {
|
||||
return t.Creator
|
||||
}
|
||||
|
||||
// SetCreator set creator
|
||||
func (t *Task) SetCreator(creator string) *Task {
|
||||
t.Creator = creator
|
||||
return t
|
||||
}
|
||||
|
||||
// GetUpdater get updater
|
||||
func (t *Task) GetUpdater() string {
|
||||
return t.Updater
|
||||
}
|
||||
|
||||
// SetUpdater set updater
|
||||
func (t *Task) SetUpdater(updater string) *Task {
|
||||
t.Updater = updater
|
||||
return t
|
||||
}
|
||||
|
||||
// GetLastUpdate get last update time
|
||||
func (t *Task) GetLastUpdate() (time.Time, error) {
|
||||
return time.Parse(TaskTimeFormat, t.LastUpdate)
|
||||
}
|
||||
|
||||
// SetLastUpdate set last update time
|
||||
func (t *Task) SetLastUpdate(lastUpdate time.Time) *Task {
|
||||
t.LastUpdate = lastUpdate.Format(TaskTimeFormat)
|
||||
return t
|
||||
}
|
||||
|
||||
// GetCurrentStep get current step
|
||||
func (t *Task) GetCurrentStep() string {
|
||||
return t.CurrentStep
|
||||
}
|
||||
|
||||
// SetCurrentStep set current step
|
||||
func (t *Task) SetCurrentStep(stepName string) *Task {
|
||||
t.CurrentStep = stepName
|
||||
return t
|
||||
}
|
||||
|
||||
// GetStepParam get step params
|
||||
func (t *Task) GetStepParam(stepName, key string) (string, bool) {
|
||||
step, ok := t.GetStep(stepName)
|
||||
if !ok {
|
||||
return "", false
|
||||
}
|
||||
return step.GetParam(key)
|
||||
}
|
||||
|
||||
// AddStepParams add step params
|
||||
func (t *Task) AddStepParams(stepName string, k, v string) error {
|
||||
step, ok := t.GetStep(stepName)
|
||||
if !ok {
|
||||
return fmt.Errorf("step %s not exist", stepName)
|
||||
}
|
||||
step.AddParam(k, v)
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddStepParamsBatch add step params batch
|
||||
func (t *Task) AddStepParamsBatch(stepName string, params map[string]string) error {
|
||||
if _, ok := t.Steps[stepName]; !ok {
|
||||
return fmt.Errorf("step %s not exist", stepName)
|
||||
}
|
||||
for k, v := range params {
|
||||
t.Steps[stepName].AddParam(k, v)
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Tencent is pleased to support the open source community by making Blueking Container Service available.
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under
|
||||
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// Package types for task
|
||||
package types
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
// TaskTimeFormat task time format, e.g. 2006-01-02T15:04:05Z07:00
|
||||
TaskTimeFormat = time.RFC3339
|
||||
// DefaultJsonExtrasContent default json extras content
|
||||
DefaultJsonExtrasContent = "{}"
|
||||
// DefaultMaxExecuteTime default max execute time for 1 hour
|
||||
DefaultMaxExecuteTimeSeconds = 3600
|
||||
)
|
||||
|
||||
const (
|
||||
// TaskStatusInit INIT task status
|
||||
TaskStatusInit = "INITIALIZING"
|
||||
// TaskStatusRunning running task status
|
||||
TaskStatusRunning = "RUNNING"
|
||||
// TaskStatusSuccess task success
|
||||
TaskStatusSuccess = "SUCCESS"
|
||||
// TaskStatusFailure task failed
|
||||
TaskStatusFailure = "FAILURE"
|
||||
// TaskStatusTimeout task run timeout
|
||||
TaskStatusTimeout = "TIMEOUT"
|
||||
// TaskStatusForceTerminate force task terminate
|
||||
TaskStatusForceTerminate = "FORCETERMINATE"
|
||||
// TaskStatusNotStarted force task terminate
|
||||
TaskStatusNotStarted = "NOTSTARTED"
|
||||
)
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Tencent is pleased to support the open source community by making Blueking Container Service available.
|
||||
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* Licensed under the MIT License (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
* http://opensource.org/licenses/MIT
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under
|
||||
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// Package task is a package for task management
|
||||
package task
|
||||
|
||||
import types "git.ifooth.com/common/machinery-plugins/task/types"
|
||||
|
||||
// StepWorkerInterface that client must implement
|
||||
type StepWorkerInterface interface {
|
||||
GetName() string
|
||||
DoWork(state *State) error
|
||||
}
|
||||
|
||||
// CallbackInterface that client must implement
|
||||
type CallbackInterface interface {
|
||||
GetName() string
|
||||
Callback(isSuccess bool, task *types.Task)
|
||||
}
|
Loading…
Reference in New Issue