chore: 并入 iotlcm-upstream-chan 历史到 upstream-chan/(原提交 1e74497)
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
package upstreamimpl
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-upstream-chan/internal/model"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultUpstreamHTTPTimeout = 10 * time.Second
|
||||
upstreamHTTPTimeoutKey = "dependencies.upstream_http.timeout"
|
||||
)
|
||||
|
||||
func templateConfigJSON(channelConfig *model.SimChannelConfigItemCache) string {
|
||||
if channelConfig == nil || channelConfig.Template == nil {
|
||||
return ""
|
||||
}
|
||||
return channelConfig.Template.TempConfig
|
||||
}
|
||||
|
||||
// parseUpstreamDuration accepts Go duration strings and positive numeric
|
||||
// seconds so template and application configuration use the same contract.
|
||||
func parseUpstreamDuration(raw json.RawMessage, field string) (time.Duration, error) {
|
||||
if len(raw) == 0 || string(raw) == "null" {
|
||||
return 0, fmt.Errorf("%s is empty", field)
|
||||
}
|
||||
var value any
|
||||
if err := json.Unmarshal(raw, &value); err != nil {
|
||||
return 0, fmt.Errorf("invalid %s: %w", field, err)
|
||||
}
|
||||
switch v := value.(type) {
|
||||
case float64:
|
||||
if v <= 0 || v != float64(int64(v)) {
|
||||
return 0, fmt.Errorf("invalid %s: expected positive seconds", field)
|
||||
}
|
||||
return time.Duration(v) * time.Second, nil
|
||||
case string:
|
||||
value := strings.TrimSpace(v)
|
||||
if value == "" {
|
||||
return 0, fmt.Errorf("invalid %s: empty value", field)
|
||||
}
|
||||
duration, err := time.ParseDuration(value)
|
||||
if err != nil || duration <= 0 {
|
||||
return 0, fmt.Errorf("invalid %s: expected positive duration", field)
|
||||
}
|
||||
return duration, nil
|
||||
default:
|
||||
return 0, fmt.Errorf("invalid %s: expected duration or seconds", field)
|
||||
}
|
||||
}
|
||||
|
||||
func parseUpstreamConfigDuration(value any, field string) (time.Duration, error) {
|
||||
raw, err := json.Marshal(value)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("encode %s: %w", field, err)
|
||||
}
|
||||
return parseUpstreamDuration(raw, field)
|
||||
}
|
||||
|
||||
func loadDefaultUpstreamHTTPTimeout(ctx context.Context) time.Duration {
|
||||
value := g.Cfg().MustGet(ctx, upstreamHTTPTimeoutKey, defaultUpstreamHTTPTimeout.String()).Val()
|
||||
timeout, err := parseUpstreamConfigDuration(value, upstreamHTTPTimeoutKey)
|
||||
if err != nil {
|
||||
g.Log().Warningf(ctx, "%v, fallback to %s", err, defaultUpstreamHTTPTimeout)
|
||||
return defaultUpstreamHTTPTimeout
|
||||
}
|
||||
return timeout
|
||||
}
|
||||
|
||||
// resolveUpstreamHTTPTimeout applies the single timeout override for a
|
||||
// template. Missing or invalid template values fall back to application
|
||||
// configuration and finally the code default.
|
||||
func resolveUpstreamHTTPTimeout(ctx context.Context, tempConfig string) time.Duration {
|
||||
defaultTimeout := loadDefaultUpstreamHTTPTimeout(ctx)
|
||||
if strings.TrimSpace(tempConfig) == "" {
|
||||
return defaultTimeout
|
||||
}
|
||||
var raw struct {
|
||||
HTTP struct {
|
||||
Timeout json.RawMessage `json:"timeout"`
|
||||
} `json:"http"`
|
||||
}
|
||||
if err := json.Unmarshal([]byte(tempConfig), &raw); err != nil {
|
||||
g.Log().Warningf(ctx, "parse upstream template config failed: %v, fallback to %s", err, defaultTimeout)
|
||||
return defaultTimeout
|
||||
}
|
||||
if len(raw.HTTP.Timeout) == 0 || string(raw.HTTP.Timeout) == "null" {
|
||||
return defaultTimeout
|
||||
}
|
||||
timeout, err := parseUpstreamDuration(raw.HTTP.Timeout, "http.timeout")
|
||||
if err != nil {
|
||||
g.Log().Warningf(ctx, "%v, fallback to %s", err, defaultTimeout)
|
||||
return defaultTimeout
|
||||
}
|
||||
return timeout
|
||||
}
|
||||
Reference in New Issue
Block a user