parent
5947e93c93
commit
88978c9039
@ -0,0 +1,22 @@
|
|||||||
|
package gojobs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/go-redis/redis/v8"
|
||||||
|
"go.etcd.io/etcd/client/v3"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetDb 数据库驱动
|
||||||
|
func (j *JobsGorm) GetDb() *gorm.DB {
|
||||||
|
return j.service.gormClient
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRedis 缓存数据库驱动
|
||||||
|
func (j *JobsGorm) GetRedis() *redis.Client {
|
||||||
|
return j.db.redisClient
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetEtcd 分布式缓存驱动
|
||||||
|
func (j *JobsGorm) GetEtcd() *clientv3.Client {
|
||||||
|
return j.db.etcdClient
|
||||||
|
}
|
@ -1,36 +1,67 @@
|
|||||||
package gojobs
|
package gojobs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go.dtapp.net/library/utils/dorm"
|
|
||||||
"go.dtapp.net/library/utils/gojobs/jobs_gorm_model"
|
"go.dtapp.net/library/utils/gojobs/jobs_gorm_model"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Lock 上锁
|
// Lock 上锁
|
||||||
func (j *JobsGorm) Lock(info jobs_gorm_model.Task, id any) string {
|
func (j *JobsGorm) Lock(info jobs_gorm_model.Task, id any) (string, error) {
|
||||||
cacheName := fmt.Sprintf("cron:%v:%v", info.Type, id)
|
|
||||||
judgeCache := j.redis.NewStringOperation().Get(cacheName).UnwrapOr("")
|
if j.config.lockType == "" {
|
||||||
if judgeCache != "" {
|
return "", errors.New("没有配置")
|
||||||
return judgeCache
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
redisKey = fmt.Sprintf("%s:%v:%v", j.config.lockPrefix, info.Type, id)
|
||||||
|
etcdKey = fmt.Sprintf("%s/%v/%v", j.config.lockPrefix, info.Type, id)
|
||||||
|
val = fmt.Sprintf("已在%s@%s机器上锁成功", j.config.insideIp, j.config.outsideIp)
|
||||||
|
ttl = info.Frequency * 3
|
||||||
|
)
|
||||||
|
|
||||||
|
if j.config.lockType == lockTypeRedis {
|
||||||
|
return j.service.lockRedisClient.Lock(redisKey, val, ttl)
|
||||||
}
|
}
|
||||||
j.redis.NewStringOperation().Set(cacheName, fmt.Sprintf("已在%v机器上锁成功", j.config.OutsideIp), dorm.WithExpire(time.Millisecond*time.Duration(info.Frequency)*3))
|
|
||||||
return ""
|
return j.service.lockEtcdClient.Lock(etcdKey, val, ttl)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unlock Lock 解锁
|
// Unlock Lock 解锁
|
||||||
func (j *JobsGorm) Unlock(info jobs_gorm_model.Task, id any) {
|
func (j *JobsGorm) Unlock(info jobs_gorm_model.Task, id any) error {
|
||||||
cacheName := fmt.Sprintf("cron:%v:%v", info.Type, id)
|
|
||||||
j.redis.NewStringOperation().Del(cacheName)
|
if j.config.lockType == "" {
|
||||||
|
return errors.New("没有配置")
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
redisKey = fmt.Sprintf("%s:%v:%v", j.config.lockPrefix, info.Type, id)
|
||||||
|
etcdKey = fmt.Sprintf("%s/%v/%v", j.config.lockPrefix, info.Type, id)
|
||||||
|
)
|
||||||
|
|
||||||
|
if j.config.lockType == lockTypeRedis {
|
||||||
|
return j.service.lockRedisClient.Unlock(redisKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
return j.service.lockEtcdClient.Unlock(etcdKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
// LockForever 永远上锁
|
// LockForever 永远上锁
|
||||||
func (j *JobsGorm) LockForever(info jobs_gorm_model.Task, id any) string {
|
func (j *JobsGorm) LockForever(info jobs_gorm_model.Task, id any) (string, error) {
|
||||||
cacheName := fmt.Sprintf("cron:%v:%v", info.Type, id)
|
|
||||||
judgeCache := j.redis.NewStringOperation().Get(cacheName).UnwrapOr("")
|
if j.config.lockType == "" {
|
||||||
if judgeCache != "" {
|
return "", errors.New("没有配置")
|
||||||
return judgeCache
|
|
||||||
}
|
}
|
||||||
j.redis.NewStringOperation().Set(cacheName, fmt.Sprintf("已在%v机器永远上锁成功", j.config.OutsideIp))
|
|
||||||
return ""
|
var (
|
||||||
|
redisKey = fmt.Sprintf("%s:%v:%v", j.config.lockPrefix, info.Type, id)
|
||||||
|
etcdKey = fmt.Sprintf("%s/%v/%v", j.config.lockPrefix, info.Type, id)
|
||||||
|
val = fmt.Sprintf("已在%s@%s机器永远上锁成功", j.config.insideIp, j.config.outsideIp)
|
||||||
|
)
|
||||||
|
|
||||||
|
if j.config.lockType == lockTypeRedis {
|
||||||
|
return j.service.lockRedisClient.LockForever(redisKey, val)
|
||||||
|
}
|
||||||
|
|
||||||
|
return j.service.lockEtcdClient.LockForever(etcdKey, val)
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,249 @@
|
|||||||
|
package gojobs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"go.dtapp.net/library/utils/gojobs/jobs_gorm_model"
|
||||||
|
"go.dtapp.net/library/utils/only"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
"log"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Run 运行
|
||||||
|
func (j *JobsGorm) Run(info jobs_gorm_model.Task, status int, desc string) {
|
||||||
|
// 请求函数记录
|
||||||
|
statusCreate := j.service.gormClient.Create(&jobs_gorm_model.TaskLog{
|
||||||
|
TaskId: info.Id,
|
||||||
|
StatusCode: status,
|
||||||
|
Desc: desc,
|
||||||
|
Version: j.config.runVersion,
|
||||||
|
})
|
||||||
|
if statusCreate.RowsAffected == 0 {
|
||||||
|
log.Println("statusCreate", statusCreate.Error)
|
||||||
|
}
|
||||||
|
if status == 0 {
|
||||||
|
statusEdit := j.EditTask(j.service.gormClient, info.Id).
|
||||||
|
Select("run_id").
|
||||||
|
Updates(jobs_gorm_model.Task{
|
||||||
|
RunId: only.GetUuId(),
|
||||||
|
})
|
||||||
|
if statusEdit.RowsAffected == 0 {
|
||||||
|
log.Println("statusEdit", statusEdit.Error)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 任务
|
||||||
|
if status == CodeSuccess {
|
||||||
|
// 执行成功
|
||||||
|
statusEdit := j.EditTask(j.service.gormClient, info.Id).
|
||||||
|
Select("status_desc", "number", "run_id", "updated_ip", "result").
|
||||||
|
Updates(jobs_gorm_model.Task{
|
||||||
|
StatusDesc: "执行成功",
|
||||||
|
Number: info.Number + 1,
|
||||||
|
RunId: only.GetUuId(),
|
||||||
|
UpdatedIp: j.config.outsideIp,
|
||||||
|
Result: desc,
|
||||||
|
})
|
||||||
|
if statusEdit.RowsAffected == 0 {
|
||||||
|
log.Println("statusEdit", statusEdit.Error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if status == CodeEnd {
|
||||||
|
// 执行成功、提前结束
|
||||||
|
statusEdit := j.EditTask(j.service.gormClient, info.Id).
|
||||||
|
Select("status", "status_desc", "number", "updated_ip", "result").
|
||||||
|
Updates(jobs_gorm_model.Task{
|
||||||
|
Status: TASK_SUCCESS,
|
||||||
|
StatusDesc: "结束执行",
|
||||||
|
Number: info.Number + 1,
|
||||||
|
UpdatedIp: j.config.outsideIp,
|
||||||
|
Result: desc,
|
||||||
|
})
|
||||||
|
if statusEdit.RowsAffected == 0 {
|
||||||
|
log.Println("statusEdit", statusEdit.Error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if status == CodeError {
|
||||||
|
// 执行失败
|
||||||
|
statusEdit := j.EditTask(j.service.gormClient, info.Id).
|
||||||
|
Select("status_desc", "number", "run_id", "updated_ip", "result").
|
||||||
|
Updates(jobs_gorm_model.Task{
|
||||||
|
StatusDesc: "执行失败",
|
||||||
|
Number: info.Number + 1,
|
||||||
|
RunId: only.GetUuId(),
|
||||||
|
UpdatedIp: j.config.outsideIp,
|
||||||
|
Result: desc,
|
||||||
|
})
|
||||||
|
if statusEdit.RowsAffected == 0 {
|
||||||
|
log.Println("statusEdit", statusEdit.Error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if info.MaxNumber != 0 {
|
||||||
|
if info.Number+1 >= info.MaxNumber {
|
||||||
|
// 关闭执行
|
||||||
|
statusEdit := j.EditTask(j.service.gormClient, info.Id).
|
||||||
|
Select("status").
|
||||||
|
Updates(jobs_gorm_model.Task{
|
||||||
|
Status: TASK_TIMEOUT,
|
||||||
|
})
|
||||||
|
if statusEdit.RowsAffected == 0 {
|
||||||
|
log.Println("statusEdit", statusEdit.Error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RunAddLog 任务执行日志
|
||||||
|
func (j *JobsGorm) RunAddLog(id uint, runId string) *gorm.DB {
|
||||||
|
return j.service.gormClient.Create(&jobs_gorm_model.TaskLogRun{
|
||||||
|
TaskId: id,
|
||||||
|
RunId: runId,
|
||||||
|
InsideIp: j.config.insideIp,
|
||||||
|
OutsideIp: j.config.outsideIp,
|
||||||
|
Os: j.config.os,
|
||||||
|
Arch: j.config.arch,
|
||||||
|
Gomaxprocs: j.config.maxProCs,
|
||||||
|
GoVersion: j.config.version,
|
||||||
|
MacAddrs: j.config.macAddrS,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConfigCreateInCustomId 创建正在运行任务
|
||||||
|
type ConfigCreateInCustomId struct {
|
||||||
|
Tx *gorm.DB // 驱动
|
||||||
|
Params string // 参数
|
||||||
|
Frequency int64 // 频率(秒单位)
|
||||||
|
CustomId string // 自定义编号
|
||||||
|
CustomSequence int64 // 自定义顺序
|
||||||
|
Type string // 类型
|
||||||
|
SpecifyIp string // 指定外网IP
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateInCustomId 创建正在运行任务
|
||||||
|
func (j *JobsGorm) CreateInCustomId(config *ConfigCreateInCustomId) error {
|
||||||
|
createStatus := config.Tx.Create(&jobs_gorm_model.Task{
|
||||||
|
Status: TASK_IN,
|
||||||
|
Params: config.Params,
|
||||||
|
StatusDesc: "首次添加任务",
|
||||||
|
Frequency: config.Frequency,
|
||||||
|
RunId: only.GetUuId(),
|
||||||
|
CustomId: config.CustomId,
|
||||||
|
CustomSequence: config.CustomSequence,
|
||||||
|
Type: config.Type,
|
||||||
|
CreatedIp: j.config.outsideIp,
|
||||||
|
SpecifyIp: config.SpecifyIp,
|
||||||
|
UpdatedIp: j.config.outsideIp,
|
||||||
|
})
|
||||||
|
if createStatus.RowsAffected == 0 {
|
||||||
|
return errors.New(fmt.Sprintf("创建[%s@%s]任务失败:%s", config.CustomId, config.Type, createStatus.Error))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConfigCreateInCustomIdOnly 创建正在运行唯一任务
|
||||||
|
type ConfigCreateInCustomIdOnly struct {
|
||||||
|
Tx *gorm.DB // 驱动
|
||||||
|
Params string // 参数
|
||||||
|
Frequency int64 // 频率(秒单位)
|
||||||
|
CustomId string // 自定义编号
|
||||||
|
CustomSequence int64 // 自定义顺序
|
||||||
|
Type string // 类型
|
||||||
|
SpecifyIp string // 指定外网IP
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateInCustomIdOnly 创建正在运行唯一任务
|
||||||
|
func (j *JobsGorm) CreateInCustomIdOnly(config *ConfigCreateInCustomIdOnly) error {
|
||||||
|
query := j.TaskTypeTakeIn(config.Tx, config.CustomId, config.Type)
|
||||||
|
if query.Id != 0 {
|
||||||
|
return errors.New(fmt.Sprintf("%d:[%s@%s]任务已存在", query.Id, config.CustomId, config.Type))
|
||||||
|
}
|
||||||
|
createStatus := config.Tx.Create(&jobs_gorm_model.Task{
|
||||||
|
Status: TASK_IN,
|
||||||
|
Params: config.Params,
|
||||||
|
StatusDesc: "首次添加任务",
|
||||||
|
Frequency: config.Frequency,
|
||||||
|
RunId: only.GetUuId(),
|
||||||
|
CustomId: config.CustomId,
|
||||||
|
CustomSequence: config.CustomSequence,
|
||||||
|
Type: config.Type,
|
||||||
|
CreatedIp: j.config.outsideIp,
|
||||||
|
SpecifyIp: config.SpecifyIp,
|
||||||
|
UpdatedIp: j.config.outsideIp,
|
||||||
|
})
|
||||||
|
if createStatus.RowsAffected == 0 {
|
||||||
|
return errors.New(fmt.Sprintf("创建[%s@%s]任务失败:%s", config.CustomId, config.Type, createStatus.Error))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConfigCreateInCustomIdMaxNumber 创建正在运行任务并限制数量
|
||||||
|
type ConfigCreateInCustomIdMaxNumber struct {
|
||||||
|
Tx *gorm.DB // 驱动
|
||||||
|
Params string // 参数
|
||||||
|
Frequency int64 // 频率(秒单位)
|
||||||
|
MaxNumber int64 // 最大次数
|
||||||
|
CustomId string // 自定义编号
|
||||||
|
CustomSequence int64 // 自定义顺序
|
||||||
|
Type string // 类型
|
||||||
|
SpecifyIp string // 指定外网IP
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateInCustomIdMaxNumber 创建正在运行任务并限制数量
|
||||||
|
func (j *JobsGorm) CreateInCustomIdMaxNumber(config *ConfigCreateInCustomIdMaxNumber) error {
|
||||||
|
createStatus := config.Tx.Create(&jobs_gorm_model.Task{
|
||||||
|
Status: TASK_IN,
|
||||||
|
Params: config.Params,
|
||||||
|
StatusDesc: "首次添加任务",
|
||||||
|
Frequency: config.Frequency,
|
||||||
|
MaxNumber: config.MaxNumber,
|
||||||
|
RunId: only.GetUuId(),
|
||||||
|
CustomId: config.CustomId,
|
||||||
|
CustomSequence: config.CustomSequence,
|
||||||
|
Type: config.Type,
|
||||||
|
CreatedIp: j.config.outsideIp,
|
||||||
|
SpecifyIp: config.SpecifyIp,
|
||||||
|
UpdatedIp: j.config.outsideIp,
|
||||||
|
})
|
||||||
|
if createStatus.RowsAffected == 0 {
|
||||||
|
return errors.New(fmt.Sprintf("创建[%s@%s]任务失败:%s", config.CustomId, config.Type, createStatus.Error))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConfigCreateInCustomIdMaxNumberOnly 创建正在运行唯一任务并限制数量
|
||||||
|
type ConfigCreateInCustomIdMaxNumberOnly struct {
|
||||||
|
Tx *gorm.DB // 驱动
|
||||||
|
Params string // 参数
|
||||||
|
Frequency int64 // 频率(秒单位)
|
||||||
|
MaxNumber int64 // 最大次数
|
||||||
|
CustomId string // 自定义编号
|
||||||
|
CustomSequence int64 // 自定义顺序
|
||||||
|
Type string // 类型
|
||||||
|
SpecifyIp string // 指定外网IP
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateInCustomIdMaxNumberOnly 创建正在运行唯一任务并限制数量
|
||||||
|
func (j *JobsGorm) CreateInCustomIdMaxNumberOnly(config *ConfigCreateInCustomIdMaxNumberOnly) error {
|
||||||
|
query := j.TaskTypeTakeIn(config.Tx, config.CustomId, config.Type)
|
||||||
|
if query.Id != 0 {
|
||||||
|
return errors.New(fmt.Sprintf("%d:[%s@%s]任务已存在", query.Id, config.CustomId, config.Type))
|
||||||
|
}
|
||||||
|
createStatus := config.Tx.Create(&jobs_gorm_model.Task{
|
||||||
|
Status: TASK_IN,
|
||||||
|
Params: config.Params,
|
||||||
|
StatusDesc: "首次添加任务",
|
||||||
|
Frequency: config.Frequency,
|
||||||
|
MaxNumber: config.MaxNumber,
|
||||||
|
RunId: only.GetUuId(),
|
||||||
|
CustomId: config.CustomId,
|
||||||
|
CustomSequence: config.CustomSequence,
|
||||||
|
Type: config.Type,
|
||||||
|
CreatedIp: j.config.outsideIp,
|
||||||
|
SpecifyIp: config.SpecifyIp,
|
||||||
|
UpdatedIp: j.config.outsideIp,
|
||||||
|
})
|
||||||
|
if createStatus.RowsAffected == 0 {
|
||||||
|
return errors.New(fmt.Sprintf("创建[%s@%s]任务失败:%s", config.CustomId, config.Type, createStatus.Error))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
@ -1,25 +0,0 @@
|
|||||||
package gojobs
|
|
||||||
|
|
||||||
//
|
|
||||||
//type JobsOption func(*JobsCron)
|
|
||||||
//
|
|
||||||
//// WithRedis 缓存服务驱动
|
|
||||||
//func WithRedis(db *goredis.Client) JobsOption {
|
|
||||||
// return func(opts *JobsCron) {
|
|
||||||
// opts.redis = db
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//// WithGorm 数据库服务驱动
|
|
||||||
//func WithGorm(db *gorm.DB) JobsOption {
|
|
||||||
// return func(opts *JobsCron) {
|
|
||||||
// opts.db = db
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//// WithMainService 是否主要服务(主要服务可删除过期服务)
|
|
||||||
//func WithMainService(status int) JobsOption {
|
|
||||||
// return func(opts *JobsCron) {
|
|
||||||
// opts.mainService = status
|
|
||||||
// }
|
|
||||||
//}
|
|
Loading…
Reference in new issue