modernize 37→5(-32):interface{}→any、内置 max/min、slices/maps 辅助、strings.Cut/SplitSeq、strings.Builder(修复 mail.go O(n²) 拼接)。逐 hunk 核对语义等价;omitzero 冲突修复被自动跳过(wire 格式不变);手动清 4 处遗留 sort import + 2 处 QF1012。

Result: {"status":"keep","total_issues":74,"golint_canonicalheader":8,"golint_errname":1,"golint_errorlint":12,"golint_forcetypeassert":3,"golint_gosec":0,"golint_intrange":3,"golint_modernize":5,"golint_nilnil":3,"golint_perfsprint":18,"golint_prealloc":3,"golint_recvcheck":7,"golint_usestdlibvars":3,"golint_wastedassign":7,"golint_total":73,"eslint_problems":1,"eslint_errors":0,"eslint_warnings":1,"tsc_errors":0,"measure_s":38}
This commit is contained in:
ryan
2026-08-16 17:28:22 +08:00
parent f1f6bb858a
commit b76f707c8b
56 changed files with 164 additions and 263 deletions
+20 -29
View File
@@ -50,9 +50,9 @@ type GetTableDataRequest struct {
// TableDataResponse 动态数据表响应结构体
type TableDataResponse struct {
Columns []string `json:"columns"`
Total int64 `json:"total"`
Results []map[string]interface{} `json:"results"`
Columns []string `json:"columns"`
Total int64 `json:"total"`
Results []map[string]any `json:"results"`
}
// ExecuteSQLRequest 执行自定义 SQL 请求结构体
@@ -62,11 +62,11 @@ type ExecuteSQLRequest struct {
// ExecuteSQLResponse 执行自定义 SQL 响应结构体
type ExecuteSQLResponse struct {
Type string `json:"type"` // "select" 或 "exec"
Columns []string `json:"columns,omitempty"`
Results []map[string]interface{} `json:"results,omitempty"`
AffectedRows int64 `json:"affected_rows"`
ExecutionTimeMs int64 `json:"execution_time_ms"`
Type string `json:"type"` // "select" 或 "exec"
Columns []string `json:"columns,omitempty"`
Results []map[string]any `json:"results,omitempty"`
AffectedRows int64 `json:"affected_rows"`
ExecutionTimeMs int64 `json:"execution_time_ms"`
}
// formatBytes 格式化字节大小为可读字符串
@@ -119,10 +119,7 @@ func getSQLiteOverview(gormDB *gorm.DB) (DBOverviewResponse, error) {
var sizeStr string
if fi, err := os.Stat(name); err == nil {
size := fi.Size()
if size < 0 {
size = 0
}
size := max(fi.Size(), 0)
sizeStr = formatBytes(uint64(size))
} else {
sizeStr = "0 B"
@@ -165,10 +162,7 @@ func getPostgresOverview(gormDB *gorm.DB) (DBOverviewResponse, error) {
var sizeStr string
var sizeBytes sql.NullInt64
if err := gormDB.Raw("SELECT pg_database_size(current_database())").Scan(&sizeBytes).Error; err == nil && sizeBytes.Valid {
size := sizeBytes.Int64
if size < 0 {
size = 0
}
size := max(sizeBytes.Int64, 0)
sizeStr = formatBytes(uint64(size))
} else {
sizeStr = "0 B"
@@ -294,10 +288,7 @@ func GetDBTableData(c *gin.Context) {
return
}
offset := (req.Page - 1) * req.PageSize
if offset < 0 {
offset = 0
}
offset := max((req.Page-1)*req.PageSize, 0)
limit := req.PageSize
if limit <= 0 {
limit = 10
@@ -332,11 +323,11 @@ func GetDBTableData(c *gin.Context) {
}
// scanTableRows 扫描并提取数据表行数据,做截断处理
func scanTableRows(rows *sql.Rows, cols []string) ([]map[string]interface{}, error) {
results := make([]map[string]interface{}, 0)
func scanTableRows(rows *sql.Rows, cols []string) ([]map[string]any, error) {
results := make([]map[string]any, 0)
for rows.Next() {
columns := make([]interface{}, len(cols))
columnPointers := make([]interface{}, len(cols))
columns := make([]any, len(cols))
columnPointers := make([]any, len(cols))
for i := range columns {
columnPointers[i] = &columns[i]
}
@@ -345,7 +336,7 @@ func scanTableRows(rows *sql.Rows, cols []string) ([]map[string]interface{}, err
return nil, err
}
rowMap := make(map[string]interface{})
rowMap := make(map[string]any)
for i, colName := range cols {
val := columns[i]
if b, ok := val.([]byte); ok {
@@ -385,10 +376,10 @@ func executeSQLQuery(gormDB *gorm.DB, sqlStr string, startTime time.Time) (Execu
return ExecuteSQLResponse{}, err
}
results := make([]map[string]interface{}, 0)
results := make([]map[string]any, 0)
for rows.Next() {
columns := make([]interface{}, len(cols))
columnPointers := make([]interface{}, len(cols))
columns := make([]any, len(cols))
columnPointers := make([]any, len(cols))
for i := range columns {
columnPointers[i] = &columns[i]
}
@@ -397,7 +388,7 @@ func executeSQLQuery(gormDB *gorm.DB, sqlStr string, startTime time.Time) (Execu
return ExecuteSQLResponse{}, err
}
rowMap := make(map[string]interface{})
rowMap := make(map[string]any)
for i, colName := range cols {
val := columns[i]
if b, ok := val.([]byte); ok {
+2 -2
View File
@@ -35,8 +35,8 @@ func getUpgrader() *websocket.Upgrader {
ctx := r.Context()
if sc, err := repository.GetSystemConfigByKey(ctx, model.ConfigKeyServerAddress); err == nil && sc.Value != "" {
originToCheck := strings.TrimRight(strings.TrimSpace(origin), "/")
allowedOrigins := strings.Split(sc.Value, ",")
for _, allowed := range allowedOrigins {
allowedOrigins := strings.SplitSeq(sc.Value, ",")
for allowed := range allowedOrigins {
allowed = strings.TrimRight(strings.TrimSpace(allowed), "/")
if allowed != "" && strings.EqualFold(allowed, originToCheck) {
return true
@@ -3,6 +3,8 @@
package push
import "slices"
import "sync"
const (
@@ -66,13 +68,7 @@ func ListDefinitions() []Definition {
}
// Add any others
for t, d := range definitions {
found := false
for _, o := range order {
if o == t {
found = true
break
}
}
found := slices.Contains(order, t)
if !found {
res = append(res, d)
}
+2 -3
View File
@@ -9,6 +9,7 @@ import (
"encoding/json"
"errors"
"fmt"
"maps"
"strings"
"github.com/Rain-kl/Wavelet/internal/infra/task"
@@ -34,9 +35,7 @@ func (m NotificationMessage) Flatten() map[string]any {
keyContent: m.Content,
keyLevel: m.Level,
}
for k, v := range m.Ext {
res[k] = v
}
maps.Copy(res, m.Ext)
return res
}
+4 -11
View File
@@ -17,6 +17,7 @@ import (
"os"
"path/filepath"
"runtime"
"slices"
"strings"
"sync"
"time"
@@ -163,13 +164,7 @@ func selectLatestRelease(repository string, releases []githubRelease) (githubRel
}
expectedNames := expectedAssetNames(repository, release.TagName)
for _, asset := range release.Assets {
matched := false
for _, name := range expectedNames {
if asset.Name == name {
matched = true
break
}
}
matched := slices.Contains(expectedNames, asset.Name)
if !matched || asset.BrowserDownloadURL == "" || asset.State != "uploaded" {
continue
}
@@ -348,10 +343,8 @@ func getCandidateBinaryNames(executable string, repository string) []string {
if runtime.GOOS == windowsOS && !strings.HasSuffix(strings.ToLower(name), ".exe") {
name += ".exe"
}
for _, existing := range names {
if existing == name {
return
}
if slices.Contains(names, name) {
return
}
names = append(names, name)
}
+7 -10
View File
@@ -7,6 +7,7 @@ package user
import (
"errors"
"net/http"
"slices"
"strconv"
"time"
@@ -93,17 +94,13 @@ func abortUserLogicError(c *gin.Context, err error, notFoundMsg string, forbidde
return true
}
msg := err.Error()
for _, m := range badRequestMsgs {
if msg == m {
response.AbortBadRequest(c, msg)
return true
}
if slices.Contains(badRequestMsgs, msg) {
response.AbortBadRequest(c, msg)
return true
}
for _, m := range forbiddenMsgs {
if msg == m {
response.AbortForbidden(c, msg)
return true
}
if slices.Contains(forbiddenMsgs, msg) {
response.AbortForbidden(c, msg)
return true
}
logger.ErrorF(c.Request.Context(), "Admin user error: %v", err)
response.AbortInternal(c, "内部服务器错误")
@@ -120,7 +120,7 @@ func ensureWorldTraversablePath(targetDir string) error {
if current == "" || current == "." {
return nil
}
for depth := 0; depth < maxDepth; depth++ {
for range maxDepth {
if err := os.Chmod(current, DefaultDirPerm); err != nil { //nolint:gosec // parent dirs must be traversable by the runtime user
if os.IsNotExist(err) || os.IsPermission(err) {
break
+2 -5
View File
@@ -198,7 +198,7 @@ func (s *Service) ensurePagesProject(ctx context.Context, snapshot *state.Snapsh
}
var lastErr error
for attempt := 0; attempt < pagesLatestPullAttempts; attempt++ {
for attempt := range pagesLatestPullAttempts {
latest, err := s.client.GetPagesProjectLatestHash(ctx, projectID)
if err != nil {
return fmt.Errorf("fetch Pages project %d latest hash: %w", projectID, err)
@@ -359,10 +359,7 @@ func validatePagesPackageMetadata(
if extractedBytes == 0 {
extractedBytes = 1
}
maxFileBytes := extractedBytes
if maxFileBytes > agentPagesMaxFileBytes {
maxFileBytes = agentPagesMaxFileBytes
}
maxFileBytes := min(extractedBytes, agentPagesMaxFileBytes)
return pagesPackageLimits{
PackageBytes: metadata.PackageSize,
+2 -2
View File
@@ -12,7 +12,7 @@ import (
"fmt"
"io"
"log/slog"
"sort"
"slices"
"strconv"
"strings"
"sync"
@@ -363,7 +363,7 @@ func referencedWAFIPGroupIDs(supportFiles []protocol.SupportFile) ([]uint, error
for id := range seen {
ids = append(ids, id)
}
sort.Slice(ids, func(i, j int) bool { return ids[i] < ids[j] })
slices.Sort(ids)
return ids, nil
}
+1 -4
View File
@@ -78,10 +78,7 @@ func (m *Manager) Redeem(ctx context.Context, token string, solutions []int, sco
}
now := time.Now().UnixNano() / int64(time.Millisecond)
nonceTTL := time.Duration(payload.Expires-now) * time.Millisecond
if nonceTTL < time.Second {
nonceTTL = time.Second
}
nonceTTL := max(time.Duration(payload.Expires-now)*time.Millisecond, time.Second)
set, err := m.store.SetNX(ctx, nonceKey, "1", nonceTTL)
if err != nil {
+4 -10
View File
@@ -96,10 +96,7 @@ func ReadMemInfo() (int64, int64) {
if total == 0 {
return 0, 0
}
used := total - (memAvailableKB * 1024)
if used < 0 {
used = 0
}
used := max(total-(memAvailableKB*1024), 0)
return total, used
}
@@ -138,8 +135,8 @@ func ReadLinuxCPUStat() (uint64, uint64) {
if err != nil {
return 0, 0
}
lines := strings.Split(string(content), "\n")
for _, line := range lines {
lines := strings.SplitSeq(string(content), "\n")
for line := range lines {
if !strings.HasPrefix(line, "cpu ") {
continue
}
@@ -260,10 +257,7 @@ func StatFilesystem(path string) (int64, int64) {
}
total := multiplyUint64Int64(stat.Blocks, stat.Bsize)
free := multiplyUint64Int64(stat.Bavail, stat.Bsize)
used := total - free
if used < 0 {
used = 0
}
used := max(total-free, 0)
return total, used
}
+1 -1
View File
@@ -285,7 +285,7 @@ func (s *Service) downloadChecksum(ctx context.Context, url string, assetName st
func parseSHA256Checksum(content string, assetName string) (string, error) {
assetName = strings.TrimSpace(assetName)
for _, line := range strings.Split(content, "\n") {
for line := range strings.SplitSeq(content, "\n") {
line = strings.TrimSpace(line)
if line == "" || strings.HasPrefix(line, "#") {
continue
+1 -1
View File
@@ -203,7 +203,7 @@ func (m *Manager) restartProcess(ctx context.Context, relayID string, configPath
startedAt := time.Now()
err := cmd.Start()
if err == nil {
_ = os.WriteFile(pidPath, []byte(fmt.Sprintf("%d", cmd.Process.Pid)), frpcConfigFilePerm)
_ = os.WriteFile(pidPath, fmt.Appendf(nil, "%d", cmd.Process.Pid), frpcConfigFilePerm)
err = cmd.Wait()
}
_ = os.Remove(pidPath)
+2 -6
View File
@@ -6,6 +6,7 @@ package oauth
import (
"context"
"errors"
"slices"
"strings"
"github.com/Rain-kl/Wavelet/internal/model"
@@ -109,10 +110,5 @@ func buildOAuthConfig(ctx context.Context, source *model.AuthSource, redirectURL
}
func containsScope(scopes []string, scope string) bool {
for _, item := range scopes {
if item == scope {
return true
}
}
return false
return slices.Contains(scopes, scope)
}
+3 -12
View File
@@ -179,18 +179,9 @@ func buildNodeAccessLogRecords(nodeID string, direct []NodeAccessLog, buffered [
records := make([]*model.OpenFlareAccessLog, 0, total)
appendLogs := func(logs []NodeAccessLog) {
for _, item := range logs {
bytesSent := item.BytesSent
if bytesSent < 0 {
bytesSent = 0
}
requestLength := item.RequestLength
if requestLength < 0 {
requestLength = 0
}
requestTimeMs := item.RequestTimeMs
if requestTimeMs < 0 {
requestTimeMs = 0
}
bytesSent := max(item.BytesSent, 0)
requestLength := max(item.RequestLength, 0)
requestTimeMs := max(item.RequestTimeMs, 0)
record := &model.OpenFlareAccessLog{
NodeID: nodeID,
LoggedAt: timeFromUnix(item.LoggedAtUnix, reportedAt),
@@ -11,6 +11,7 @@ import (
"encoding/json"
"errors"
"fmt"
"slices"
"sort"
"strconv"
"strings"
@@ -97,7 +98,7 @@ func buildAgentWAFIPGroups(ctx context.Context, ids []uint) ([]WAFIPGroup, error
if len(ids) == 0 {
return []WAFIPGroup{}, nil
}
sort.Slice(ids, func(i, j int) bool { return ids[i] < ids[j] })
slices.Sort(ids)
groups, err := repository.ListOpenFlareWAFIPGroupsByIDs(ctx, ids)
if err != nil {
return nil, err
@@ -204,7 +205,7 @@ func activeConfigWAFIPGroupIDs(ctx context.Context) ([]uint, error) {
for id := range idSet {
ids = append(ids, id)
}
sort.Slice(ids, func(i, j int) bool { return ids[i] < ids[j] })
slices.Sort(ids)
return ids, nil
}
+1 -1
View File
@@ -192,7 +192,7 @@ func (client *HTTPClient) do(ctx context.Context, method, path string, query url
return err
}
requestURL := buildRequestURL(client.baseURL, path, query)
for attempt := 0; attempt < maxRequestAttempts; attempt++ {
for attempt := range maxRequestAttempts {
statusCode, retryHeader, responseBody, requestErr := client.send(ctx, method, requestURL, encodedBody)
if requestErr != nil {
return requestErr
@@ -8,6 +8,7 @@ import (
"encoding/json"
"errors"
"fmt"
"slices"
"sort"
"strconv"
"strings"
@@ -429,7 +430,7 @@ func buildSnapshotWAFIPGroups(ctx context.Context, idSet map[uint]struct{}) ([]s
for id := range idSet {
ids = append(ids, id)
}
sort.Slice(ids, func(i, j int) bool { return ids[i] < ids[j] })
slices.Sort(ids)
groups, err := listWAFIPGroupsByIDs(ctx, ids)
if err != nil {
return nil, err
@@ -629,7 +630,7 @@ func buildCertificateSupportFiles(ctx context.Context, routes []snapshotRoute) (
for certID := range certIDSet {
certIDs = append(certIDs, certID)
}
sort.Slice(certIDs, func(i, j int) bool { return certIDs[i] < certIDs[j] })
slices.Sort(certIDs)
files := make([]SupportFile, 0, len(certIDs)*supportFilesPerCertificate)
for _, certID := range certIDs {
certificate, err := repository.GetTLSCertificateByID(ctx, certID)
@@ -189,7 +189,7 @@ func validateOpenRestyCacheUseStale(key, trimmed string) error {
"http_500": {}, "http_502": {}, "http_503": {}, "http_504": {},
"http_403": {}, "http_404": {}, "http_429": {}, "off": {},
}
for _, token := range strings.Fields(trimmed) {
for token := range strings.FieldsSeq(trimmed) {
if _, ok := allowedTokens[token]; !ok {
return fmt.Errorf("%s 包含不支持的值 %q", key, token)
}
+2 -2
View File
@@ -34,8 +34,8 @@ func validateOriginAddress(address string) error {
if len(address) > maxOriginHostnameLength {
return errors.New(errOriginAddressInvalid)
}
labels := strings.Split(address, ".")
for _, label := range labels {
labels := strings.SplitSeq(address, ".")
for label := range labels {
if len(label) == 0 || len(label) > 63 {
return errors.New(errOriginAddressInvalid)
}
+3 -10
View File
@@ -80,18 +80,11 @@ func resolvePagesLimits(ctx context.Context) pagesLimits {
historyCount := defaultPagesMaxHistoryCount
if value, err := repository.GetIntByKey(ctx, model.ConfigKeyPagesMaxHistoryCount); err == nil {
if value < 0 {
historyCount = 0
} else {
historyCount = value
}
historyCount = max(value, 0)
}
packageBytes := int64(packageMB) * bytesPerMiB
extractedBytes := packageBytes * pagesExtractedSizeMultiplier
if extractedBytes < pagesMinExtractedSizeBytes {
extractedBytes = pagesMinExtractedSizeBytes
}
extractedBytes := max(packageBytes*pagesExtractedSizeMultiplier, pagesMinExtractedSizeBytes)
return pagesLimits{
PackageBytes: packageBytes,
@@ -154,7 +147,7 @@ func normalizePagesFallbackPath(raw string) (string, error) {
return "", errors.New("spa fallback 回退路径不能包含空白或控制字符")
}
}
for _, segment := range strings.Split(value, "/") {
for segment := range strings.SplitSeq(value, "/") {
if segment == "." || segment == ".." {
return "", errors.New("spa fallback 回退路径不能包含 . 或 .. 路径段")
}
+1 -1
View File
@@ -513,7 +513,7 @@ func pruneProjectDeploymentHistory(ctx context.Context, projectID uint, keepCoun
// Two passes: first pass after upload, second pass heals a concurrent race
// that inserted another deployment between our list and delete.
var lastErr error
for pass := 0; pass < 2; pass++ {
for range 2 {
deleted, err := pruneProjectDeploymentHistoryOnce(ctx, projectID, keepCount, preserveCandidateID)
if err != nil {
lastErr = err
+2 -2
View File
@@ -9,7 +9,7 @@ import (
"errors"
"fmt"
"path"
"sort"
"slices"
"strings"
"sync"
"time"
@@ -611,7 +611,7 @@ func lockSourceDeploymentUploadsTx(
if hasIngest && ingestResult.Upload.ID != 0 && ingestResult.Upload.ID != target.UploadID {
uploadIDs = append(uploadIDs, ingestResult.Upload.ID)
}
sort.Slice(uploadIDs, func(i, j int) bool { return uploadIDs[i] < uploadIDs[j] })
slices.Sort(uploadIDs)
var records []model.Upload
if err := tx.Clauses(clause.Locking{Strength: pagesRowLockStrength}).
Where("id IN ?", uploadIDs).
@@ -86,8 +86,8 @@ func validateOriginAddress(address string) error {
if len(address) > maxOriginHostnameLength {
return errors.New(errProxyRouteOriginInvalid)
}
labels := strings.Split(address, ".")
for _, label := range labels {
labels := strings.SplitSeq(address, ".")
for label := range labels {
if len(label) == 0 || len(label) > 63 {
return errors.New(errProxyRouteOriginInvalid)
}
@@ -167,8 +167,8 @@ func buildOriginURLFromParts(scheme, address, port, uri string) (string, error)
Host: formatOriginHost(normalizedAddress, normalizedPort),
}
if normalizedURI != "" {
if strings.HasPrefix(normalizedURI, "?") {
parsed.RawQuery = strings.TrimPrefix(normalizedURI, "?")
if after, ok := strings.CutPrefix(normalizedURI, "?"); ok {
parsed.RawQuery = after
} else {
pathQuery := strings.SplitN(normalizedURI, "?", originURIPathQueryParts)
parsed.Path = pathQuery[0]
@@ -6,7 +6,7 @@ package proxy_route
import (
"context"
"errors"
"sort"
"slices"
"strings"
"time"
@@ -201,7 +201,7 @@ func lockPagesProjectsForRouteMutation(tx *gorm.DB, previousProjectID uint, rout
if nextProjectID != 0 && nextProjectID != previousProjectID {
projectIDs = append(projectIDs, nextProjectID)
}
sort.Slice(projectIDs, func(i int, j int) bool { return projectIDs[i] < projectIDs[j] })
slices.Sort(projectIDs)
for _, projectID := range projectIDs {
project, err := repository.LockPagesProjectByIDTx(tx, projectID)
+1 -1
View File
@@ -123,7 +123,7 @@ func splitAcmeDomains(primaryDomain, otherDomains string) []string {
if !strings.Contains(otherDomains, "\n") && strings.Contains(otherDomains, ",") {
separator = ","
}
for _, domain := range strings.Split(otherDomains, separator) {
for domain := range strings.SplitSeq(otherDomains, separator) {
domain = strings.TrimSpace(domain)
if domain != "" {
domains = append(domains, domain)
+4 -5
View File
@@ -10,6 +10,7 @@ import (
"fmt"
"io"
"log/slog"
"maps"
"net/http"
"strconv"
"strings"
@@ -180,8 +181,8 @@ func (c *SocketIOClient) pollLoop() {
}
slog.Debug("Received polling payload from Uptime Kuma", "length", len(bodyStr))
packets := strings.Split(bodyStr, "\x1e")
for _, pkt := range packets {
packets := strings.SplitSeq(bodyStr, "\x1e")
for pkt := range packets {
if len(pkt) == 0 {
continue
}
@@ -352,9 +353,7 @@ func (c *SocketIOClient) GetMonitorList() map[string]Monitor {
defer c.monitorListMutex.RUnlock()
m := make(map[string]Monitor, len(c.monitorList))
for k, v := range c.monitorList {
m[k] = v
}
maps.Copy(m, c.monitorList)
return m
}
+2 -1
View File
@@ -5,6 +5,7 @@ package waf
import (
"fmt"
"slices"
"sort"
)
@@ -142,7 +143,7 @@ func sortedUniqueStrings(values []string) []string {
func sortedUniqueUints(values []uint) []uint {
result := append([]uint(nil), values...)
sort.Slice(result, func(i, j int) bool { return result[i] < result[j] })
slices.Sort(result)
write := 0
for _, value := range result {
if write == 0 || result[write-1] != value {
@@ -12,6 +12,7 @@ import (
"io"
"net/netip"
"regexp"
"slices"
"strings"
)
@@ -374,12 +375,7 @@ func decodeStrictConfig(raw json.RawMessage, dst any) error {
}
func validSourceHandle(t RuleNodeType, handle string) bool {
for _, expected := range requiredHandles(t) {
if handle == expected {
return true
}
}
return false
return slices.Contains(requiredHandles(t), handle)
}
func requiredHandles(t RuleNodeType) []string {
switch t {
+3 -4
View File
@@ -11,6 +11,7 @@ import (
"fmt"
"io"
"log/slog"
"maps"
"net"
"net/http"
"net/netip"
@@ -325,9 +326,7 @@ func evaluateParsedIPGroupAutoConfig(ctx context.Context, config ipGroupAutoConf
lastSeen = time.Unix(item.LastSeenEpoch, 0).UTC()
}
statusCounts := make(map[int]int, len(item.StatusCounts))
for code, count := range item.StatusCounts {
statusCounts[code] = count
}
maps.Copy(statusCounts, item.StatusCounts)
accumulators[ip] = &ipGroupAutoAccumulator{
ip: ip,
requestCount: item.RequestCount,
@@ -479,7 +478,7 @@ func selectJSONMappingNodes(payload any, mappingRule string) ([]any, error) {
}
rule = strings.TrimPrefix(rule, "$.")
nodes := []any{payload}
for _, rawSegment := range strings.Split(rule, ".") {
for rawSegment := range strings.SplitSeq(rule, ".") {
segment := strings.TrimSpace(rawSegment)
if segment == "" {
continue
+1 -4
View File
@@ -183,10 +183,7 @@ func emptyStatsSeries(since, until time.Time, bucketMinutes int) []StatsPoint {
}
// Cap points to keep chart readable.
maxPoints := 120
capacity := int(end.Sub(start)/bucket) + 1
if capacity > maxPoints {
capacity = maxPoints
}
capacity := min(int(end.Sub(start)/bucket)+1, maxPoints)
points := make([]StatsPoint, 0, capacity)
for cursor := start; !cursor.After(end) && len(points) < maxPoints; cursor = cursor.Add(bucket) {
points = append(points, StatsPoint{BucketStartedAt: cursor})
+1 -1
View File
@@ -240,7 +240,7 @@ func (m *Manager) supervise(ctx context.Context, generation uint64) {
continue
}
_ = os.WriteFile(m.pidPath, []byte(fmt.Sprintf("%d", cmd.Process.Pid)), frpsPidFilePerm)
_ = os.WriteFile(m.pidPath, fmt.Appendf(nil, "%d", cmd.Process.Pid), frpsPidFilePerm)
m.cmd = cmd
m.status = "healthy"
+2 -2
View File
@@ -59,8 +59,8 @@ func validateAllowedExtension(ctx context.Context, ext string) error {
return nil
}
allowedExts := strings.Split(strings.ToLower(sc.Value), ",")
for _, allowedExt := range allowedExts {
allowedExts := strings.SplitSeq(strings.ToLower(sc.Value), ",")
for allowedExt := range allowedExts {
if strings.TrimSpace(allowedExt) == ext {
return nil
}
@@ -193,18 +193,18 @@ func migrateObjects(
const batchSize = 50
const migrationConcurrency = 10
const sha256HexLength = 64
var migrated int64
var migrated atomic.Int64
var lastFilePath string
for {
if err := ctx.Err(); err != nil {
return atomic.LoadInt64(&migrated), fmt.Errorf("storage migration canceled: %w", err)
return migrated.Load(), fmt.Errorf("storage migration canceled: %w", err)
}
task.AppendLog(ctx, "正在查询待迁移对象批次,当前已完成迁移: %d/%d", atomic.LoadInt64(&migrated), total)
task.AppendLog(ctx, "正在查询待迁移对象批次,当前已完成迁移: %d/%d", migrated.Load(), total)
objects, err := repository.ListDistinctActiveStorageObjects(ctx, lastFilePath, batchSize)
if err != nil {
return atomic.LoadInt64(&migrated), fmt.Errorf("query source objects: %w", err)
return migrated.Load(), fmt.Errorf("query source objects: %w", err)
}
if len(objects) == 0 {
task.AppendLog(ctx, "所有对象迁移完毕")
@@ -223,18 +223,18 @@ func migrateObjects(
if err := migrateSingleObject(ctx, sourceBackend, targetBackend, obj, sha256HexLength); err != nil {
return err
}
atomic.AddInt64(&migrated, 1)
migrated.Add(1)
return nil
})
}
if err := g.Wait(); err != nil {
return atomic.LoadInt64(&migrated), err
return migrated.Load(), err
}
task.AppendLog(ctx, "当前批次迁移完成。迁移进度: %d/%d", atomic.LoadInt64(&migrated), total)
task.AppendLog(ctx, "当前批次迁移完成。迁移进度: %d/%d", migrated.Load(), total)
}
return atomic.LoadInt64(&migrated), nil
return migrated.Load(), nil
}
func migrateSingleObject(
+4 -18
View File
@@ -4,6 +4,7 @@
package util
import (
"slices"
"strings"
"github.com/Rain-kl/Wavelet/internal/apps/upload/shared"
@@ -11,32 +12,17 @@ import (
// IsImageExtension reports whether ext is a common image format.
func IsImageExtension(ext string) bool {
for _, imgExt := range []string{"jpg", "jpeg", "png", "webp", "gif"} {
if ext == imgExt {
return true
}
}
return false
return slices.Contains([]string{"jpg", "jpeg", "png", "webp", "gif"}, ext)
}
// IsArchiveExtension reports whether ext is a common archive format.
func IsArchiveExtension(ext string) bool {
for _, e := range []string{"zip", "rar", "7z", "tar", "gz", "tgz", "bz2", "xz"} {
if ext == e {
return true
}
}
return false
return slices.Contains([]string{"zip", "rar", "7z", "tar", "gz", "tgz", "bz2", "xz"}, ext)
}
// IsDocumentExtension reports whether ext is a common document format.
func IsDocumentExtension(ext string) bool {
for _, e := range []string{"pdf", "doc", "docx", "xls", "xlsx", "ppt", "pptx", "txt", "md", "csv", "json", "yaml", "yml", "xml"} {
if ext == e {
return true
}
}
return false
return slices.Contains([]string{"pdf", "doc", "docx", "xls", "xlsx", "ppt", "pptx", "txt", "md", "csv", "json", "yaml", "yml", "xml"}, ext)
}
// NormalizeImageQuality normalizes the requested image quality query parameter.