diff --git a/back/src/cmd/wts-server/main.go b/back/src/cmd/wts-server/main.go index 821eeb2..eccb887 100644 --- a/back/src/cmd/wts-server/main.go +++ b/back/src/cmd/wts-server/main.go @@ -25,11 +25,12 @@ func main() { //设置微信SDK wx := wechat.Setup(cfg) - //启动守护进程 - daemon.Setup() - //然后,启动服务器 app := server.Setup(cfg, dbx, wx) + + //启动守护进程(因为有的服务需要用到上下文,所以现在修改在server.Setup被执行的后面启动) + daemon.Setup() + err := app.Start("127.0.0.1:" + strconv.Itoa(cfg.ListenPort)) println("Server exited." + err.Error()) diff --git a/back/src/daemon/entry.go b/back/src/daemon/entry.go index 5476705..76b5e2c 100644 --- a/back/src/daemon/entry.go +++ b/back/src/daemon/entry.go @@ -2,4 +2,5 @@ package daemon func Setup() { regExitSigs() + scheduledAutoCancel() } diff --git a/back/src/daemon/scheduledAutoCancel.go b/back/src/daemon/scheduledAutoCancel.go new file mode 100644 index 0000000..65b5324 --- /dev/null +++ b/back/src/daemon/scheduledAutoCancel.go @@ -0,0 +1,117 @@ +package daemon + +import ( + "context" + "fmt" + "log/slog" + "time" + + "github.com/jackc/pgx/v5/pgtype" + "zsxyww.com/wts/model" + "zsxyww.com/wts/model/sqlc" + "zsxyww.com/wts/server" + + "math/rand" +) + +// 在每天值班结束的时候,自动取消(改日修)预约在今天但是状态今天没有更新的工单 +func scheduledAutoCancel() { + go func() { + var first = true + var duration time.Duration + var jobID int + for { + jobID = rand.Int() + //暂时在每晚的9点执行逻辑 + now := time.Now() + next := time.Date(now.Year(), now.Month(), now.Day(), 21, 0, 0, 0, now.Location()) + + // 如果程序启动时已经过了9点,那么就立即执行 + if (!now.Before(next)) && (first == true) { + first = false + goto do + } + + // 如果当前时间已经过了9点,比如程序执行完上一次了,就设置为明天9点的定时 + if !now.Before(next) { + next = next.AddDate(0, 0, 1) + } + first = false //这里防止程序在9点前启动的时候会跑两次逻辑... + + duration = next.Sub(now) + slog.Info("下一次取消程序安排上了", "duration", duration, "nextTime", next) + time.Sleep(duration) + + // 醒来后执行取消工单的操作 + do: + if err := doCancelJob(jobID); err != nil { + slog.Error("自动预约处理程序执行失败", "error", err, "ID", jobID) + } else { + slog.Info("自动取消程序执行完毕", "ID", jobID) + } + } + }() + +} + +func doCancelJob(jobID int) error { + slog.Info("开始执行每日预约处理程序", "ID", jobID) + ctx := context.Background() + err := server.DB.DoQuery(context.Background(), "system", func(q *sqlc.Queries) error { + //1.获取今日(实际上获取所有过去的预约单来保险)预约 + allZone, _ := model.BlocksInZone("all") + var beforeScheduledTickets = []sqlc.WtsVTicket{} + t, err := q.FilterTickets(ctx, sqlc.FilterTicketsParams{ + Blocks: allZone, + Status: []sqlc.WtsStatus{"scheduled"}, + }) + if err != nil { + return fmt.Errorf("在获取工单时失败了:%w", err) + } + for _, a := range t { + now := time.Now() + + var date time.Time + if a.AppointedAt.Valid { + date = a.AppointedAt.Time + } else { + continue + } + + if date.Before(now) { + beforeScheduledTickets = append(beforeScheduledTickets, a) + } + } + //2.将所有工单改为“已取消” + var ticketIDSlice []int32 + for _, a := range beforeScheduledTickets { + ticketIDSlice = append(ticketIDSlice, a.Tid) + } + slog.Info("本次操作共涉及如下工单", "t", ticketIDSlice) + for _, a := range ticketIDSlice { + _, err := q.CreateTicketTrace(ctx, sqlc.CreateTicketTraceParams{ + Tid: a, + UpdatedAt: pgtype.Timestamptz{ + Time: time.Now(), + Valid: true, + }, + Op: "-1", + NewStatus: sqlc.NullWtsStatus{ + WtsStatus: "canceled", + Valid: true, + }, + NewPriority: sqlc.NullWtsPriority{ + WtsPriority: "mainline", + Valid: true, + }, + Remark: "系统检测到预约已过期,似乎是我们爽约了,我们非常抱歉为您造成的不便,您可以再次提交报修预约,我们会努力做得更好。", + }) + if err != nil { + return fmt.Errorf("在增加记录时失败了:%w", err) + } + } + //3.如果没有问题就提交事务 + return nil + }) + return err +} diff --git a/back/src/daemon/signalHandler.go b/back/src/daemon/signalHandler.go index dd1ca54..c35daae 100644 --- a/back/src/daemon/signalHandler.go +++ b/back/src/daemon/signalHandler.go @@ -2,6 +2,7 @@ package daemon import ( "fmt" + "log/slog" "os" "os/signal" "syscall" @@ -21,6 +22,7 @@ func regExitSigs() { go func() { sig := <-sigs + slog.Info("收到退出信号", "signal", sig) fmt.Printf("\n===== %s,roger that! =====\n", sig) err := runCleanup()