| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 |
- package common
- import (
- "fmt"
- "os"
- "path/filepath"
- "time"
- "github.com/google/uuid"
- )
- // DiskCacheType 磁盘缓存类型
- type DiskCacheType string
- const (
- DiskCacheTypeBody DiskCacheType = "body" // 请求体缓存
- DiskCacheTypeFile DiskCacheType = "file" // 文件数据缓存
- )
- // 统一的缓存目录名
- const diskCacheDir = "new-api-body-cache"
- // GetDiskCacheDir 获取统一的磁盘缓存目录
- // 注意:每次调用都会重新计算,以响应配置变化
- func GetDiskCacheDir() string {
- cachePath := GetDiskCachePath()
- if cachePath == "" {
- cachePath = os.TempDir()
- }
- return filepath.Join(cachePath, diskCacheDir)
- }
- // EnsureDiskCacheDir 确保缓存目录存在
- func EnsureDiskCacheDir() error {
- dir := GetDiskCacheDir()
- return os.MkdirAll(dir, 0755)
- }
- // CreateDiskCacheFile 创建磁盘缓存文件
- // cacheType: 缓存类型(body/file)
- // 返回文件路径和文件句柄
- func CreateDiskCacheFile(cacheType DiskCacheType) (string, *os.File, error) {
- if err := EnsureDiskCacheDir(); err != nil {
- return "", nil, fmt.Errorf("failed to create cache directory: %w", err)
- }
- dir := GetDiskCacheDir()
- filename := fmt.Sprintf("%s-%s-%d.tmp", cacheType, uuid.New().String()[:8], time.Now().UnixNano())
- filePath := filepath.Join(dir, filename)
- file, err := os.OpenFile(filePath, os.O_CREATE|os.O_RDWR|os.O_EXCL, 0600)
- if err != nil {
- return "", nil, fmt.Errorf("failed to create cache file: %w", err)
- }
- return filePath, file, nil
- }
- // WriteDiskCacheFile 写入数据到磁盘缓存文件
- // 返回文件路径
- func WriteDiskCacheFile(cacheType DiskCacheType, data []byte) (string, error) {
- filePath, file, err := CreateDiskCacheFile(cacheType)
- if err != nil {
- return "", err
- }
- _, err = file.Write(data)
- if err != nil {
- file.Close()
- os.Remove(filePath)
- return "", fmt.Errorf("failed to write cache file: %w", err)
- }
- if err := file.Close(); err != nil {
- os.Remove(filePath)
- return "", fmt.Errorf("failed to close cache file: %w", err)
- }
- return filePath, nil
- }
- // WriteDiskCacheFileString 写入字符串到磁盘缓存文件
- func WriteDiskCacheFileString(cacheType DiskCacheType, data string) (string, error) {
- return WriteDiskCacheFile(cacheType, []byte(data))
- }
- // ReadDiskCacheFile 读取磁盘缓存文件
- func ReadDiskCacheFile(filePath string) ([]byte, error) {
- return os.ReadFile(filePath)
- }
- // ReadDiskCacheFileString 读取磁盘缓存文件为字符串
- func ReadDiskCacheFileString(filePath string) (string, error) {
- data, err := os.ReadFile(filePath)
- if err != nil {
- return "", err
- }
- return string(data), nil
- }
- // RemoveDiskCacheFile 删除磁盘缓存文件
- func RemoveDiskCacheFile(filePath string) error {
- return os.Remove(filePath)
- }
- // CleanupOldDiskCacheFiles 清理旧的缓存文件
- // maxAge: 文件最大存活时间
- // 注意:此函数只删除文件,不更新统计(因为无法知道每个文件的原始大小)
- func CleanupOldDiskCacheFiles(maxAge time.Duration) error {
- dir := GetDiskCacheDir()
- entries, err := os.ReadDir(dir)
- if err != nil {
- if os.IsNotExist(err) {
- return nil // 目录不存在,无需清理
- }
- return err
- }
- now := time.Now()
- for _, entry := range entries {
- if entry.IsDir() {
- continue
- }
- info, err := entry.Info()
- if err != nil {
- continue
- }
- if now.Sub(info.ModTime()) > maxAge {
- // 注意:后台清理任务删除文件时,由于无法得知原始 base64Size,
- // 只能按磁盘文件大小扣减。这在目前 base64 存储模式下是准确的。
- if err := os.Remove(filepath.Join(dir, entry.Name())); err == nil {
- DecrementDiskFiles(info.Size())
- }
- }
- }
- return nil
- }
- // GetDiskCacheInfo 获取磁盘缓存目录信息
- func GetDiskCacheInfo() (fileCount int, totalSize int64, err error) {
- dir := GetDiskCacheDir()
- entries, err := os.ReadDir(dir)
- if err != nil {
- if os.IsNotExist(err) {
- return 0, 0, nil
- }
- return 0, 0, err
- }
- for _, entry := range entries {
- if entry.IsDir() {
- continue
- }
- info, err := entry.Info()
- if err != nil {
- continue
- }
- fileCount++
- totalSize += info.Size()
- }
- return fileCount, totalSize, nil
- }
- // ShouldUseDiskCache 判断是否应该使用磁盘缓存
- func ShouldUseDiskCache(dataSize int64) bool {
- if !IsDiskCacheEnabled() {
- return false
- }
- threshold := GetDiskCacheThresholdBytes()
- if dataSize < threshold {
- return false
- }
- return IsDiskCacheAvailable(dataSize)
- }
|