Init V4 community edition (#2265)
* Init V4 community edition * Init V4 community edition
This commit is contained in:
@@ -1,99 +0,0 @@
|
||||
package crontab
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
model "github.com/cloudreve/Cloudreve/v3/models"
|
||||
"github.com/cloudreve/Cloudreve/v3/pkg/cache"
|
||||
"github.com/cloudreve/Cloudreve/v3/pkg/filesystem"
|
||||
"github.com/cloudreve/Cloudreve/v3/pkg/util"
|
||||
)
|
||||
|
||||
func garbageCollect() {
|
||||
// 清理打包下载产生的临时文件
|
||||
collectArchiveFile()
|
||||
|
||||
// 清理过期的内置内存缓存
|
||||
if store, ok := cache.Store.(*cache.MemoStore); ok {
|
||||
collectCache(store)
|
||||
}
|
||||
|
||||
util.Log().Info("Crontab job \"cron_garbage_collect\" complete.")
|
||||
}
|
||||
|
||||
func collectArchiveFile() {
|
||||
// 读取有效期、目录设置
|
||||
tempPath := util.RelativePath(model.GetSettingByName("temp_path"))
|
||||
expires := model.GetIntSetting("download_timeout", 30)
|
||||
|
||||
// 列出文件
|
||||
root := filepath.Join(tempPath, "archive")
|
||||
err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
|
||||
if err == nil && !info.IsDir() &&
|
||||
strings.HasPrefix(filepath.Base(path), "archive_") &&
|
||||
time.Now().Sub(info.ModTime()).Seconds() > float64(expires) {
|
||||
util.Log().Debug("Delete expired batch download temp file %q.", path)
|
||||
// 删除符合条件的文件
|
||||
if err := os.Remove(path); err != nil {
|
||||
util.Log().Debug("Failed to delete temp file %q: %s", path, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
util.Log().Debug("Crontab job cannot list temp batch download folder: %s", err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func collectCache(store *cache.MemoStore) {
|
||||
util.Log().Debug("Cleanup memory cache.")
|
||||
store.GarbageCollect()
|
||||
}
|
||||
|
||||
func uploadSessionCollect() {
|
||||
placeholders := model.GetUploadPlaceholderFiles(0)
|
||||
|
||||
// 将过期的上传会话按照用户分组
|
||||
userToFiles := make(map[uint][]uint)
|
||||
for _, file := range placeholders {
|
||||
_, sessionExist := cache.Get(filesystem.UploadSessionCachePrefix + *file.UploadSessionID)
|
||||
if sessionExist {
|
||||
continue
|
||||
}
|
||||
|
||||
if _, ok := userToFiles[file.UserID]; !ok {
|
||||
userToFiles[file.UserID] = make([]uint, 0)
|
||||
}
|
||||
|
||||
userToFiles[file.UserID] = append(userToFiles[file.UserID], file.ID)
|
||||
}
|
||||
|
||||
// 删除过期的会话
|
||||
for uid, filesIDs := range userToFiles {
|
||||
user, err := model.GetUserByID(uid)
|
||||
if err != nil {
|
||||
util.Log().Warning("Owner of the upload session cannot be found: %s", err)
|
||||
continue
|
||||
}
|
||||
|
||||
fs, err := filesystem.NewFileSystem(&user)
|
||||
if err != nil {
|
||||
util.Log().Warning("Failed to initialize filesystem: %s", err)
|
||||
continue
|
||||
}
|
||||
|
||||
if err = fs.Delete(context.Background(), []uint{}, filesIDs, false, false); err != nil {
|
||||
util.Log().Warning("Failed to delete upload session: %s", err)
|
||||
}
|
||||
|
||||
fs.Recycle()
|
||||
}
|
||||
|
||||
util.Log().Info("Crontab job \"cron_recycle_upload_session\" complete.")
|
||||
}
|
||||
73
pkg/crontab/crontab.go
Normal file
73
pkg/crontab/crontab.go
Normal file
@@ -0,0 +1,73 @@
|
||||
package crontab
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/cloudreve/Cloudreve/v4/application/dependency"
|
||||
"github.com/cloudreve/Cloudreve/v4/ent"
|
||||
"github.com/cloudreve/Cloudreve/v4/inventory"
|
||||
"github.com/cloudreve/Cloudreve/v4/pkg/logging"
|
||||
"github.com/cloudreve/Cloudreve/v4/pkg/setting"
|
||||
"github.com/gofrs/uuid"
|
||||
"github.com/robfig/cron/v3"
|
||||
)
|
||||
|
||||
type (
|
||||
CronTaskFunc func(ctx context.Context)
|
||||
cornRegistration struct {
|
||||
t setting.CronType
|
||||
config string
|
||||
fn CronTaskFunc
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
registrations []cornRegistration
|
||||
)
|
||||
|
||||
// Register registers a cron task.
|
||||
func Register(t setting.CronType, fn CronTaskFunc) {
|
||||
registrations = append(registrations, cornRegistration{
|
||||
t: t,
|
||||
fn: fn,
|
||||
})
|
||||
}
|
||||
|
||||
// NewCron constructs a new cron instance with given dependency.
|
||||
func NewCron(ctx context.Context, dep dependency.Dep) (*cron.Cron, error) {
|
||||
settings := dep.SettingProvider()
|
||||
userClient := dep.UserClient()
|
||||
anonymous, err := userClient.AnonymousUser(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cron: faield to get anonymous user: %w", err)
|
||||
}
|
||||
|
||||
l := dep.Logger()
|
||||
l.Info("Initialize crontab jobs...")
|
||||
c := cron.New()
|
||||
|
||||
for _, r := range registrations {
|
||||
cronConfig := settings.Cron(ctx, r.t)
|
||||
if _, err := c.AddFunc(cronConfig, taskWrapper(string(r.t), cronConfig, anonymous, dep, r.fn)); err != nil {
|
||||
l.Warning("Failed to start crontab job %q: %s", cronConfig, err)
|
||||
}
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func taskWrapper(name, config string, user *ent.User, dep dependency.Dep, task CronTaskFunc) func() {
|
||||
l := dep.Logger()
|
||||
l.Info("Cron task %s started with config %q", name, config)
|
||||
return func() {
|
||||
cid := uuid.Must(uuid.NewV4())
|
||||
l.Info("Executing Cron task %q with Cid %q", name, cid)
|
||||
ctx := context.Background()
|
||||
l := dep.Logger().CopyWithPrefix(fmt.Sprintf("[Cid: %s Cron: %s]", cid, name))
|
||||
ctx = dep.ForkWithLogger(ctx, l)
|
||||
ctx = context.WithValue(ctx, logging.CorrelationIDCtx{}, cid)
|
||||
ctx = context.WithValue(ctx, logging.LoggerCtx{}, l)
|
||||
ctx = context.WithValue(ctx, inventory.UserCtx{}, user)
|
||||
task(ctx)
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
package crontab
|
||||
|
||||
import (
|
||||
model "github.com/cloudreve/Cloudreve/v3/models"
|
||||
"github.com/cloudreve/Cloudreve/v3/pkg/util"
|
||||
"github.com/robfig/cron/v3"
|
||||
)
|
||||
|
||||
// Cron 定时任务
|
||||
var Cron *cron.Cron
|
||||
|
||||
// Reload 重新启动定时任务
|
||||
func Reload() {
|
||||
if Cron != nil {
|
||||
Cron.Stop()
|
||||
}
|
||||
Init()
|
||||
}
|
||||
|
||||
// Init 初始化定时任务
|
||||
func Init() {
|
||||
util.Log().Info("Initialize crontab jobs...")
|
||||
// 读取cron日程设置
|
||||
options := model.GetSettingByNames(
|
||||
"cron_garbage_collect",
|
||||
"cron_recycle_upload_session",
|
||||
)
|
||||
Cron := cron.New()
|
||||
for k, v := range options {
|
||||
var handler func()
|
||||
switch k {
|
||||
case "cron_garbage_collect":
|
||||
handler = garbageCollect
|
||||
case "cron_recycle_upload_session":
|
||||
handler = uploadSessionCollect
|
||||
default:
|
||||
util.Log().Warning("Unknown crontab job type %q, skipping...", k)
|
||||
continue
|
||||
}
|
||||
|
||||
if _, err := Cron.AddFunc(v, handler); err != nil {
|
||||
util.Log().Warning("Failed to start crontab job %q: %s", k, err)
|
||||
}
|
||||
|
||||
}
|
||||
Cron.Start()
|
||||
}
|
||||
Reference in New Issue
Block a user