package model import ( "encoding/json" "github.com/loveuer/nfflow/internal/sqlType" "github.com/samber/lo" "github.com/sirupsen/logrus" "gorm.io/gorm" ) type InputType int64 const ( InputTypeES InputType = iota + 1 InputTypePG InputTypeMQ ) type OutputType int64 const ( OutputTypeES OutputType = iota + 1 OutputTypeFile OutputTypeMQ ) type PipeType int64 func (p PipeType) Value() int64 { return int64(p) } func (p PipeType) Code() string { switch p { case PipeTypeLoadashMap: return "pipe_map" default: return "unknown" } } func (p PipeType) Label() string { switch p { case PipeTypeLoadashMap: return "Map" default: return "未知" } } func (p PipeType) MarshalJSON() ([]byte, error) { return json.Marshal(map[string]any{"value": p.Value(), "code": p.Code(), "label": p.Label()}) } func (p PipeType) All() []Enum { return []Enum{PipeTypeLoadashMap} } const ( PipeTypeLoadashMap PipeType = iota + 1 ) var _ Enum = PipeType(0) type TaskStatus int64 func (t TaskStatus) MarshalJSON() ([]byte, error) { return json.Marshal(map[string]any{ "value": t.Value(), "code": t.Code(), "label": t.Label(), }) } func (t TaskStatus) All() []Enum { return []Enum{ TaskStatusNotReady, TaskStatusReady, TaskStatusRunning, TaskStatusSucceed, TaskStatusFailed, } } var _ Enum = TaskStatus(0) const ( TaskStatusNotReady TaskStatus = iota TaskStatusReady TaskStatusRunning TaskStatusSucceed TaskStatusFailed ) func (t TaskStatus) Value() int64 { return int64(t) } func (t TaskStatus) Code() string { switch t { case TaskStatusNotReady: return "not_ready" case TaskStatusReady: return "ready" case TaskStatusRunning: return "running" case TaskStatusSucceed: return "succeed" case TaskStatusFailed: return "failed" default: return "unknown" } } func (t TaskStatus) Label() string { switch t { case TaskStatusNotReady: return "未完善" case TaskStatusReady: return "等待执行" case TaskStatusRunning: return "执行中" case TaskStatusSucceed: return "执行成功" case TaskStatusFailed: return "执行失败" default: return "未知" } } type TaskRunType int64 const ( TaskRunTypeOnce TaskRunType = iota TaskRunTypeTiming TaskRunTypeCron ) func (t TaskRunType) Value() int64 { return int64(t) } func (t TaskRunType) Code() string { switch t { case TaskRunTypeOnce: return "once" case TaskRunTypeTiming: return "timing" case TaskRunTypeCron: return "cron" default: return "unknown" } } func (t TaskRunType) Label() string { switch t { case TaskRunTypeOnce: return "手动执行" case TaskRunTypeTiming: return "定时执行" case TaskRunTypeCron: return "周期执行" default: return "未知" } } func (t TaskRunType) MarshalJSON() ([]byte, error) { return json.Marshal(map[string]any{"code": t.Code(), "value": t.Value(), "label": t.Label()}) } func (t TaskRunType) All() []Enum { return []Enum{TaskRunTypeOnce, TaskRunTypeTiming, TaskRunTypeCron} } var _ Enum = TaskRunType(0) type Task struct { Id uint64 `json:"id" gorm:"primaryKey;column:id"` CreatedAt int64 `json:"created_at" gorm:"column:created_at;autoCreateTime:milli"` UpdatedAt int64 `json:"updated_at" gorm:"column:updated_at;autoUpdateTime:milli"` DeletedAt int64 `json:"deleted_at" gorm:"index;column:deleted_at;default:0"` TaskName string `json:"task_name" gorm:"column:task_name;type:varchar(256)"` TaskRunType TaskRunType `json:"task_run_type" gorm:"column:task_run_type;type:varchar(16);default:0"` // cron: C-"cron syntax", "once", timestamp: T-1234567890123 毫秒时间戳 TaskRunAt int64 `json:"task_run_at" gorm:"column:task_run_at"` TaskCron string `json:"task_cron" gorm:"column:task_cron;type:varchar(32)"` TaskTimeout int `json:"task_timeout" gorm:"column:task_timeout"` TaskStatus TaskStatus `json:"task_status" gorm:"column:task_status"` TaskLog string `json:"task_log" gorm:"task_log"` } type TaskInput struct { Id uint64 `json:"id" gorm:"primaryKey;column:id"` TaskId uint64 `json:"task_id" gorm:"column:task_id"` Type InputType `json:"type" gorm:"column:type"` Config sqlType.JSONB `json:"config" gorm:"config"` } func (t *Task) GetInput(tx *gorm.DB) (*TaskInput, error) { var ( err error ti = new(TaskInput) ) if err = tx.Model(&TaskInput{}). Where("task_id", t.Id). Take(ti). Error; err != nil { return nil, err } return ti, nil } type TaskOutput struct { Id uint64 `json:"id" gorm:"primaryKey;column:id"` TaskId uint64 `json:"task_id" gorm:"column:task_id"` Type OutputType `json:"type" gorm:"column:type"` Config sqlType.JSONB `json:"config" gorm:"config"` } func (t *Task) GetOutputs(tx *gorm.DB) ([]*TaskOutput, error) { var ( err error outputs = make([]*TaskOutput, 0) ) if err = tx.Model(&TaskOutput{}). Where("task_id", t.Id). Find(&outputs). Error; err != nil { return nil, err } return outputs, nil } type TaskPipe struct { Id uint64 `json:"id" gorm:"primaryKey;column:id"` TaskId uint64 `json:"task_id" gorm:"column:task_id"` Pid uint64 `json:"pid" gorm:"column:pid"` Type PipeType `json:"type" gorm:"column:type"` Config sqlType.JSONB `json:"config" gorm:"config"` Next []*TaskPipe `json:"next" gorm:"-"` } func (t *Task) GetPipes(tx *gorm.DB) ([]*TaskPipe, error) { var ( err error list = make([]*TaskPipe, 0) ) if err = tx.Model(&TaskPipe{}). Where("task_id", t.Id). Find(&list). Error; err != nil { return nil, err } m := lo.SliceToMap(list, func(item *TaskPipe) (uint64, *TaskPipe) { item.Next = make([]*TaskPipe, 0) return item.Id, item }) m[0] = &TaskPipe{Next: make([]*TaskPipe, 0)} for idx := range list { x := list[idx] if _, exist := m[x.Pid]; !exist { logrus.Warnf("GetPipes: pipe=[task_id=%d id=%d pid=%d type=%s] pid not found", x.TaskId, x.Id, x.Pid, x.Type.Code()) continue } m[x.Pid].Next = append(m[x.Pid].Next, x) } return m[0].Next, nil }