Skip to content

Commit

Permalink
Merge pull request #44 from SchwarzSail/scheduled_modified
Browse files Browse the repository at this point in the history
feat: scheduled modified
  • Loading branch information
jiuxia211 authored Oct 20, 2024
2 parents a9e2234 + 2c71f9c commit 19b2ac0
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 79 deletions.
132 changes: 67 additions & 65 deletions cmd/classroom/dal/cache/schedule.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,83 +32,85 @@ import (
"github.com/west2-online/jwch"
)

// ScheduledGetClassrooms 定期获取空教室信息
func ScheduledGetClassrooms() error {
ctx := context.Background()
var dates []string
currentTime := time.Now()
// ScheduledUpdateClassroomsInfo 定期获取7天的空教室信息
func ScheduledUpdateClassroomsInfo(date time.Time) error {
var dates []time.Time
// 设定一周时间
for i := 0; i < 7; i++ {
date := currentTime.AddDate(0, 0, i).Format("2006-01-02")
dates = append(dates, date)
for i := 1; i < 7; i++ {
d := date.AddDate(0, 0, i)
dates = append(dates, d)
}
logger.Infof("ScheduledGetClassrooms: start to get empty room info in the next 7 days: %v", dates)

var eg errgroup.Group

// 对每个日期启动一个 goroutine
for _, date := range dates {
for _, d := range dates {
// 将 date 作为参数传递给 goroutine
eg.Go(func(date string) func() error {
return func() error {
// 创建新的 stu 对象,每个 goroutine 都有自己的 client
// 定义 jwch 的 stu 客户端
stu := jwch.NewStudent().WithUser(config.DefaultUser.Account, config.DefaultUser.Password)
// 登录,id 和 cookies 会自动保存在 client 中
// 如果登录失败,重试
err := utils.RetryLogin(stu)
currentDate := d
eg.Go(func() error {
return UpdateClassroomsInfo(currentDate)
})
}

// 等待所有 goroutine 完成,并收集错误
if err := eg.Wait(); err != nil {
return fmt.Errorf("ScheduledUpdateClassroomsInfo: failed to refresh empty room info: %w", err)
}

return nil
}

// UpdateClassroomsInfo update the classroom info in the date
func UpdateClassroomsInfo(date time.Time) error {
currentDate := date.Format("2006-01-02")
logger.Infof("UpdateClassroomsInfo: start to update empty room info in the date %v", currentDate)
ctx := context.Background()
// 定义 jwch 的 stu 客户端
stu := jwch.NewStudent().WithUser(config.DefaultUser.Account, config.DefaultUser.Password)
// 登录,id 和 cookies 会自动保存在 client 中
// 如果登录失败,重试
err := utils.RetryLogin(stu)
if err != nil {
return fmt.Errorf("UpdateClassroomsInfo: failed to login: %w", err)
}
for _, campus := range constants.CampusArray {
for startTime := 1; startTime <= 11; startTime++ {
for endTime := startTime; endTime <= 11; endTime++ {
args := jwch.EmptyRoomReq{
Campus: campus,
Time: currentDate, // 使用传递进来的 date 参数
Start: strconv.Itoa(startTime),
End: strconv.Itoa(endTime),
}
var res []string
var err error
// 从 jwch 获取空教室信息
switch campus {
case "旗山校区":
res, err = stu.GetQiShanEmptyRoom(args)
default:
res, err = stu.GetEmptyRoom(args)
}
if err != nil {
return fmt.Errorf("ScheduledGetClassrooms: failed to login: %w", err)
return fmt.Errorf("UpdateClassroomsInfo: failed to get empty room info: %w", err)
}
for _, campus := range constants.CampusArray {
for startTime := 1; startTime <= 11; startTime++ {
for endTime := startTime; endTime <= 11; endTime++ {
args := jwch.EmptyRoomReq{
Campus: campus,
Time: date, // 使用传递进来的 date 参数
Start: strconv.Itoa(startTime),
End: strconv.Itoa(endTime),
}
var res []string
var err error
// 从 jwch 获取空教室信息
switch campus {
case "旗山校区":
res, err = stu.GetQiShanEmptyRoom(args)
default:
res, err = stu.GetEmptyRoom(args)
}
if err != nil {
return fmt.Errorf("ScheduledGetClassrooms: failed to get empty room info: %w", err)
}
// 收集结果并缓存
switch campus {
case "厦门工艺美院":
err = SetXiaMenEmptyRoomCache(ctx, date, args.Start, args.End, res)
if err != nil {
return fmt.Errorf("ScheduledGetClassrooms: failed to set xiamen empty room cache: %w", err)
}
default:
key := fmt.Sprintf("%s.%s.%s.%s", args.Time, args.Campus, args.Start, args.End)
err = SetEmptyRoomCache(ctx, key, res)
if err != nil {
return fmt.Errorf("ScheduledGetClassrooms: failed to set empty room cache: %w", err)
}
}
}
// 收集结果并缓存
switch campus {
case "厦门工艺美院":
err = SetXiaMenEmptyRoomCache(ctx, currentDate, args.Start, args.End, res)
if err != nil {
return fmt.Errorf("UpdateClassroomsInfo: failed to set xiamen empty room cache: %w", err)
}
default:
key := fmt.Sprintf("%s.%s.%s.%s", args.Time, args.Campus, args.Start, args.End)
err = SetEmptyRoomCache(ctx, key, res)
if err != nil {
return fmt.Errorf("UpdateClassroomsInfo: failed to set empty room cache: %w", err)
}

logger.Infof("ScheduledGetClassrooms: complete all tasks of campus %s in the day %s", campus, date)
}
return nil
}
}(date))
}
}

// 等待所有 goroutine 完成,并收集错误
if err := eg.Wait(); err != nil {
return fmt.Errorf("ScheduledGetClassrooms: failed to refresh empty room info: %w", err)
logger.Infof("UpdateClassroomsInfo: complete all tasks of campus %s in the day %s", campus, date)
}

return nil
}
6 changes: 4 additions & 2 deletions cmd/classroom/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,10 @@ func main() {
}),
)
// 提前缓存空教室数据
// 将signal放入队列,开启定时任务
WorkQueue.Add("signal")
// update用于启动定期更新当天数据的任务
WorkQueue.Add("update")
// 将scheduled放入队列,开启定时任务
WorkQueue.Add("schedule")

if err = svr.Run(); err != nil {
logger.Fatalf("Classroom: server run failed: %v", err)
Expand Down
41 changes: 29 additions & 12 deletions cmd/classroom/workqueue.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ limitations under the License.
package main

import (
"time"

"golang.org/x/time/rate"
"k8s.io/client-go/util/workqueue"

Expand Down Expand Up @@ -50,18 +52,33 @@ func worker() {
logger.Info("Classroom.worker shutdown")
return
}
if err := cache.ScheduledGetClassrooms(); err != nil {
logger.Errorf("Classroom.worker ScheduledGetClassrooms failed: %v", err)
// 如果失败,在使用该函数,采取避退策略
WorkQueue.AddRateLimited(item)
} else {
// 将signal重新放入队列,实现自驱动
WorkQueue.AddAfter(item, constants.ScheduledTime)
logger.Info("Classroom.worker ScheduledGetClassrooms success")
// 任务成功,清除其失败记录
WorkQueue.Forget(item)
var err error
// 根据update和schedule区分爬取
switch item {
case "update":
if err = apply(constants.UpdatedTime, item, cache.UpdateClassroomsInfo); err != nil {
logger.Infof("Classroom.worker: update failed: %v", err)
}
case "schedule":
if err = apply(constants.ScheduledTime, item, cache.ScheduledUpdateClassroomsInfo); err != nil {
logger.Infof("Classroom.worker: schedule failed: %v", err)
}
}
// 任务完成, 释放资源, 防止队列阻塞
WorkQueue.Done(item)
}
}

// 抽象函数
func apply(timeDuration time.Duration, item string, scheduledFunc func(date time.Time) error) (err error) {
if err = scheduledFunc(time.Now()); err != nil {
// 如果失败,在使用该函数,采取避退策略
WorkQueue.AddRateLimited(item)
} else {
// 将signal重新放入队列,实现自驱动
WorkQueue.AddAfter(item, timeDuration)
// 任务成功,清除其失败记录
WorkQueue.Forget(item)
}
// 任务完成, 释放资源, 防止队列阻塞
WorkQueue.Done(item)
return err
}
1 change: 1 addition & 0 deletions pkg/constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ const (

// 定时任务
ScheduledTime = 24 * time.Hour
UpdatedTime = 6 * time.Hour // 当天空教室更新间隔

// retry
MaxRetries = 5 // 最大重试次数
Expand Down

0 comments on commit 19b2ac0

Please sign in to comment.