Files
OpenFlare/backend/plugins/domain/upload/storage/migration.go
T
ryan 867fcb2288 refactor: revive cleanup — unused params to _, add missing doc comments
- admin/db_helper GetCache/GetUserService/GetAuthService: ctx -> _ (签名对称保留)
- validateMergedStorageConfig / ParseMigrationTargetConfig / MockStorageService.Put 未用参数 -> _
- SetDBServiceForTest、StorageDriver 常量组补充文档注释
lint_issues 33→26
2026-08-28 16:53:32 +08:00

117 lines
3.6 KiB
Go

// Copyright 2026 Arctel.net
// SPDX-License-Identifier: Apache-2.0
package storage
import (
"Wavelet/core/contracts"
"Wavelet/plugins/domain/upload/shared"
"context"
"encoding/json"
"errors"
"fmt"
"strings"
"gorm.io/gorm"
)
// StorageMigrationTask is the task name for storage migration.
const StorageMigrationTask = "storage:migrate"
// LatestMigrationExecution returns the most recent storage migration task execution.
func LatestMigrationExecution(ctx context.Context) (*contracts.TaskExecutionDTO, bool, error) {
db := shared.GetDB(ctx)
if db == nil {
return nil, false, nil
}
var exec contracts.TaskExecutionDTO
err := db.Table("w_task_executions").Where("task_type = ?", StorageMigrationTask).Order("id DESC").First(&exec).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, false, nil
}
return nil, false, err
}
return &exec, true, nil
}
// ParseMigrationTargetConfig parses and validates a storage migration target payload.
func ParseMigrationTargetConfig(_ context.Context, payload []byte) (contracts.StorageConfigDTO, error) {
if strings.TrimSpace(string(payload)) == "" {
return contracts.StorageConfigDTO{}, errors.New("storage migration target payload is required")
}
var raw struct {
Target json.RawMessage `json:"target"`
}
if err := json.Unmarshal(payload, &raw); err != nil {
return contracts.StorageConfigDTO{}, fmt.Errorf("parse storage migration payload envelope: %w", err)
}
if len(raw.Target) == 0 {
return contracts.StorageConfigDTO{}, errors.New("storage migration target payload is required")
}
var targetBytes []byte
var targetStr string
if err := json.Unmarshal(raw.Target, &targetStr); err == nil {
targetBytes = []byte(targetStr)
} else {
targetBytes = raw.Target
}
var target contracts.StorageConfigDTO
if err := json.Unmarshal(targetBytes, &target); err != nil {
return contracts.StorageConfigDTO{}, fmt.Errorf("parse target storage config: %w", err)
}
return target, nil
}
// NormalizeMigrationPayload validates and normalizes a storage migration payload.
func NormalizeMigrationPayload(ctx context.Context, payload []byte) ([]byte, contracts.StorageConfigDTO, error) {
target, err := ParseMigrationTargetConfig(ctx, payload)
if err != nil {
return nil, contracts.StorageConfigDTO{}, err
}
raw, err := json.Marshal(struct {
Target contracts.StorageConfigDTO `json:"target"`
}{Target: target})
if err != nil {
return nil, contracts.StorageConfigDTO{}, fmt.Errorf("serialize normalized payload: %w", err)
}
return raw, target, nil
}
// SaveActiveConfig persists the active storage configuration to w_system_configs.
func SaveActiveConfig(ctx context.Context, cfg contracts.StorageConfigDTO) error {
db := shared.GetDB(ctx)
if db == nil {
return errors.New("database not available")
}
data, err := json.Marshal(cfg)
if err != nil {
return err
}
return db.Table("w_system_configs").Where("key = ?", "storage_config").Update("value", string(data)).Error
}
// LoadStorageConfig loads the current storage configuration from w_system_configs.
func LoadStorageConfig(ctx context.Context) (contracts.StorageConfigDTO, error) {
db := shared.GetDB(ctx)
if db == nil {
return contracts.StorageConfigDTO{}, errors.New("database not available")
}
var row struct {
Value string
}
if err := db.Table("w_system_configs").Where("key = ?", "storage_config").First(&row).Error; err != nil {
return contracts.StorageConfigDTO{}, err
}
var cfg contracts.StorageConfigDTO
if err := json.Unmarshal([]byte(row.Value), &cfg); err != nil {
return contracts.StorageConfigDTO{}, err
}
return cfg, nil
}