Files
OpenFlare/internal/apps/upload/storage_ops.go
T
ryan 9a18bea324 feat(storage): add dynamic storage config and migration
Move storage backend configuration from startup YAML to system_config-backed runtime configuration. Add local, S3-compatible, R2, MinIO, OSS, and WebDAV backend support.

Add a storage migration async task using the existing task dispatch framework. Migration target config is carried in task payload, and maintenance mode is derived from task execution state.

Split upload file management and storage operations, add the admin storage configuration tab, and update migrations and Swagger docs.
2026-06-13 15:31:38 +08:00

88 lines
2.2 KiB
Go

// Copyright 2026 Arctel.net
// SPDX-License-Identifier: Apache-2.0
package upload
import (
"context"
"fmt"
"github.com/Rain-kl/Wavelet/internal/logger"
"github.com/Rain-kl/Wavelet/internal/model"
"github.com/Rain-kl/Wavelet/internal/storage"
)
func storageReadOnly(ctx context.Context) bool {
execution, ok, err := latestStorageMigrationExecution(ctx)
if err != nil {
logger.ErrorF(ctx, "读取存储维护状态失败: %v", err)
return true
}
if !ok {
return false
}
return execution.Status != model.TaskExecutionStatusSucceeded
}
func openStoredObject(ctx context.Context, upload *model.Upload) (*storage.Object, error) {
driver := storage.Driver(upload.StorageDriver)
if driver == "" {
driver = storage.DriverLocal
}
backend, err := backendForStoredDriver(ctx, driver)
if err != nil {
return nil, err
}
return backend.Get(ctx, upload.FilePath)
}
func backendForStoredDriver(ctx context.Context, driver storage.Driver) (storage.Backend, error) {
backend, err := storage.ForDriver(ctx, driver)
if err == nil {
return backend, nil
}
target, ok, targetErr := currentMigrationTargetConfig(ctx)
if targetErr != nil {
return nil, targetErr
}
if ok && target.Driver == driver {
return storage.NewBackend(ctx, target, driver)
}
return nil, fmt.Errorf("storage configuration for driver %q is unavailable", driver)
}
func currentMigrationTargetConfig(ctx context.Context) (storage.Config, bool, error) {
execution, ok, err := latestStorageMigrationExecution(ctx)
if err != nil || !ok {
return storage.Config{}, false, err
}
if execution.Status == model.TaskExecutionStatusSucceeded {
return storage.Config{}, false, nil
}
target, err := parseMigrationTargetConfig(ctx, []byte(execution.Payload))
if err != nil {
return storage.Config{}, false, err
}
return target, true, nil
}
func cfgBucket(ctx context.Context, driver storage.Driver) string {
cfg, err := storage.LoadConfig(ctx)
if err != nil {
return ""
}
switch driver {
case storage.DriverS3:
return cfg.S3.Bucket
case storage.DriverR2:
return cfg.R2.Bucket
case storage.DriverMinIO:
return cfg.MinIO.Bucket
case storage.DriverOSS:
return cfg.OSS.Bucket
default:
return ""
}
}