Files

96 lines
3.4 KiB
Go
Raw Permalink Normal View History

package resumable
import (
"context"
"errors"
"github.com/Tencent/WeKnora/internal/types"
"time"
)
const MaxFileSize int64 = 20 << 30
const ChunkSize int64 = 4 << 20
const UserQuota int64 = 40 << 30
const TenantQuota int64 = 100 << 30
const MaxActive = 20
var ErrInvalid = errors.New("上传参数或校验和无效")
var ErrConflict = errors.New("上传状态或分块偏移已变化,请刷新后继续")
var ErrQuota = errors.New("上传暂存配额不足,请取消其他上传或等待过期清理")
var ErrForbidden = errors.New("没有此上传或目标资源的权限")
// UserError contains only an intentionally public explanation written by the
// upload implementation. Driver, filesystem and provider errors are never
// promoted to this type and remain confined to server logs.
type UserError string
func (e UserError) Error() string { return string(e) }
func publicError(err error) string {
var public UserError
if errors.As(err, &public) {
return public.Error()
}
var input *types.DigitalHumanInputError
if errors.As(err, &input) {
return input.Error()
}
for _, sentinel := range []error{ErrInvalid, ErrConflict, ErrQuota, ErrForbidden} {
if errors.Is(err, sentinel) {
return sentinel.Error()
}
}
return "文件处理暂不可用,请稍后重试或联系管理员检查服务日志"
}
type Upload struct {
ID string `json:"id" gorm:"primaryKey;type:varchar(36)"`
TenantID uint64 `json:"-" gorm:"index"`
OwnerID string `json:"-" gorm:"type:varchar(36);index"`
Kind string `json:"kind"`
TargetID string `json:"target_id"`
Name string `json:"name"`
Size int64 `json:"size"`
Offset int64 `json:"offset"`
ChunkSize int64 `json:"chunk_size"`
SHA256 string `json:"sha256"`
Fingerprint string `json:"fingerprint"`
State string `json:"state" gorm:"index"`
Error string `json:"error,omitempty"`
Options types.JSON `json:"options" gorm:"type:jsonb"`
Result types.JSON `json:"result,omitempty" gorm:"type:jsonb"`
IngestOffset int64 `json:"ingest_offset"`
Part int `json:"part"`
ExpiresAt time.Time `json:"expires_at" gorm:"index"`
LeaseUntil *time.Time `json:"-"`
LeaseToken string `json:"-"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
func (Upload) TableName() string { return "resumable_uploads" }
type Chunk struct {
UploadID string `json:"-" gorm:"primaryKey;type:varchar(36)"`
Offset int64 `json:"offset" gorm:"primaryKey"`
Size int64 `json:"size"`
SHA256 string `json:"sha256"`
}
func (Chunk) TableName() string { return "resumable_upload_chunks" }
type CreateInput struct {
Kind string `json:"kind"`
TargetID string `json:"target_id"`
Name string `json:"name"`
Size int64 `json:"size"`
SHA256 string `json:"sha256"`
Fingerprint string `json:"fingerprint"`
Options types.JSON `json:"options"`
}
// Import processes one bounded unit, returning a durable checkpoint. The worker
// renews the lease around each unit and never queues the entire file at once.
type ImportFunc func(context.Context, *Upload, string) (offset int64, result types.JSON, done bool, err error)
type ContextFunc func(context.Context, *Upload) (context.Context, error)
type AuthorizeFunc func(context.Context, string, string) error