Files
trbot/utils/task/task.go
Hubert Chen ee590a8a0b refactor teamspeak
teamspeak:
    use task to instead check client goroutine
    and other mess
task:
    add `FindJob()` func to get a `quartz.ScheduledJob`
2025-11-12 05:38:42 +08:00

253 lines
5.6 KiB
Go

package task
import (
"context"
"fmt"
"time"
"trbot/utils"
"github.com/reugn/go-quartz/quartz"
"github.com/rs/zerolog"
)
type Task struct {
Name string
Group string
Job quartz.Job
Trigger quartz.Trigger
}
// Scheduler is an exported `quartz.Scheduler` struct, for use with other unencapsulated methods.
var Scheduler quartz.Scheduler
// InitTaskHandler retrieves the zerolog from ctx as the logger and starts the scheduler.
func InitTaskHandler(ctx context.Context) error {
logger := zerolog.Ctx(ctx)
var err error
// slogLogger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelDebug}))
Scheduler, err = quartz.NewStdScheduler(
// quartz.WithLogger(quartz_logger.NewSlogLogger(ctx, slogLogger)),
quartz.WithLogger(NewZerologWappred(*logger)),
)
if err != nil {
logger.Error().
Err(err).
Msg("failed to create scheduler")
return err
}
// start the scheduler
Scheduler.Start(ctx)
logger.Info().Msg("Task handler initialized")
return nil
}
// ScheduleTask schedules a task into `task.Scheduler`.
func ScheduleTask(ctx context.Context, task Task) error {
if task.Group == "" {
task.Group = "default"
}
logger := zerolog.Ctx(ctx).With().
Str(utils.GetCurrentFuncName()).
Str("name", task.Name).
Str("group", task.Group).
Logger()
if task.Job == nil {
logger.Error().Msg("This task has no job")
return fmt.Errorf("this task has no job")
}
var pauseJob bool
if task.Trigger == nil {
task.Trigger = quartz.NewSimpleTrigger(348 * time.Minute)
pauseJob = true
if task.Group != "trbot" {
logger.Warn().Msg("A task has no trigger, it will add a trigger with a 348-minute interval and pause immediately")
}
}
err := Scheduler.ScheduleJob(
quartz.NewJobDetail(
task.Job,
quartz.NewJobKeyWithGroup(task.Name, task.Group),
),
task.Trigger,
)
if err != nil {
logger.Error().
Err(err).
Msg("Failed to schedule task")
return err
}
if pauseJob {
err = Scheduler.PauseJob(quartz.NewJobKeyWithGroup(task.Name, task.Group))
if err != nil {
logger.Error().
Err(err).
Msg("Failed to pause a task that did not have a trigger")
}
}
logger.Info().
Bool("noTrigger", pauseJob).
Msg("Task scheduled successfully")
return nil
}
// FindJob returns a `quartz.ScheduledJob` by name and group.
func FindJob(name, group string) (quartz.ScheduledJob, error) {
return Scheduler.GetScheduledJob(quartz.NewJobKeyWithGroup(name, group))
}
// RunTask executes a specified task by name and group.
func RunTask(ctx context.Context, name, group string) error {
logger := zerolog.Ctx(ctx).
With().
Str(utils.GetCurrentFuncName()).
Str("name", name).
Str("group", group).
Logger()
job, err := Scheduler.GetScheduledJob(quartz.NewJobKeyWithGroup(name, group))
if err != nil {
logger.Error().Err(err).Msg("Job not found")
return err
}
err = job.JobDetail().Job().Execute(ctx)
if err != nil {
logger.Error().Err(err).Msg("Job execution failed")
return err
}
return nil
}
// UpdateTask updates a specified task by name and group.
func UpdateTask(ctx context.Context, name, group string, job quartz.Job, trigger quartz.Trigger) error {
logger := zerolog.Ctx(ctx).With().
Str(utils.GetCurrentFuncName()).
Str("name", name).
Str("group", group).
Logger()
if job == nil {
logger.Error().Msg("No job in the newTask")
return fmt.Errorf("no job in the newTask")
}
var pauseJob bool
if trigger == nil {
trigger = quartz.NewSimpleTrigger(348 * time.Minute)
pauseJob = true
logger.Warn().Msg("The newTask has no triggers, it will add a trigger with a 348-minute interval and pause immediately")
}
err := Scheduler.DeleteJob(quartz.NewJobKeyWithGroup(name, group))
if err != nil {
logger.Error().
Err(err).
Msg("Failed to delete old task")
return fmt.Errorf("failed to delete old task: %w", err)
}
err = Scheduler.ScheduleJob(
quartz.NewJobDetail(
job,
quartz.NewJobKeyWithGroup(name, group),
),
trigger,
)
if err != nil {
logger.Error().
Err(err).
Msg("Failed to schedule newTask")
return err
}
if pauseJob {
err = Scheduler.PauseJob(quartz.NewJobKeyWithGroup(name, group))
if err != nil {
logger.Error().
Err(err).
Msg("Failed to pause a task that did not have a trigger")
}
}
logger.Info().
Bool("noTrigger", pauseJob).
Msg("Task update successfully")
return nil
}
// PauseTask pause a specified task by name and group.
func PauseTask(ctx context.Context, name, group string) error {
logger := zerolog.Ctx(ctx).
With().
Str(utils.GetCurrentFuncName()).
Str("name", name).
Logger()
err := Scheduler.PauseJob(quartz.NewJobKeyWithGroup(name, group))
if err != nil {
logger.Error().
Err(err).
Msg("Failed to pause task")
return err
}
logger.Info().Msg("Task paused successfully")
return nil
}
// ResumeTask resume a specified task by name and group.
func ResumeTask(ctx context.Context, name, group string) error {
logger := zerolog.Ctx(ctx).
With().
Str(utils.GetCurrentFuncName()).
Str("name", name).
Logger()
err := Scheduler.ResumeJob(quartz.NewJobKeyWithGroup(name, group))
if err != nil {
logger.Error().
Err(err).
Msg("Failed to resume task")
return err
}
logger.Info().Msg("Task resumed successfully")
return nil
}
// DeleteTask delete a specified task by name and group.
func DeleteTask(ctx context.Context, name, group string) error {
logger := zerolog.Ctx(ctx).
With().
Str(utils.GetCurrentFuncName()).
Str("name", name).
Logger()
err := Scheduler.DeleteJob(quartz.NewJobKeyWithGroup(name, group))
if err != nil {
logger.Error().
Err(err).
Msg("Failed to delete task")
return err
}
logger.Info().Msg("Task deleted successfully")
return nil
}