1
0
mirror of https://github.com/v2fly/v2ray-core.git synced 2025-01-02 15:36:41 -05:00

parse duration conf with time.Parse()

This commit is contained in:
jebbs 2021-06-05 13:00:14 +01:00 committed by Shelikhoo
parent 718d6f32bf
commit a8dd708028
No known key found for this signature in database
GPG Key ID: C4D5E79D22B25316
4 changed files with 91 additions and 20 deletions

33
infra/conf/duration.go Normal file
View File

@ -0,0 +1,33 @@
package conf
import (
"encoding/json"
"fmt"
"time"
)
type Duration int64
func (d *Duration) MarshalJSON() ([]byte, error) {
dr := time.Duration(*d)
return json.Marshal(dr.String())
}
func (d *Duration) UnmarshalJSON(b []byte) error {
var v interface{}
if err := json.Unmarshal(b, &v); err != nil {
return err
}
switch value := v.(type) {
case string:
var err error
dr, err := time.ParseDuration(value)
if err != nil {
return err
}
*d = Duration(dr)
return nil
default:
return fmt.Errorf("invalid duration: %v", v)
}
}

View File

@ -0,0 +1,33 @@
package conf_test
import (
"encoding/json"
"testing"
"time"
"github.com/v2fly/v2ray-core/v4/infra/conf"
)
type testWithDuration struct {
Duration conf.Duration
}
func TestDurationJSON(t *testing.T) {
expected := &testWithDuration{
Duration: conf.Duration(time.Hour),
}
data, err := json.Marshal(expected)
if err != nil {
t.Error(err)
return
}
actual := &testWithDuration{}
err = json.Unmarshal(data, &actual)
if err != nil {
t.Error(err)
return
}
if actual.Duration != expected.Duration {
t.Errorf("expected: %s, actual: %s", time.Duration(expected.Duration), time.Duration(actual.Duration))
}
}

View File

@ -1,8 +1,6 @@
package conf package conf
import ( import (
"time"
"github.com/golang/protobuf/proto" "github.com/golang/protobuf/proto"
"github.com/v2fly/v2ray-core/v4/app/router" "github.com/v2fly/v2ray-core/v4/app/router"
@ -29,22 +27,29 @@ func (v *strategyEmptyConfig) Build() (proto.Message, error) {
} }
type strategyLeastLoadConfig struct { type strategyLeastLoadConfig struct {
// note the time values of the HealthCheck holds is not // health check settings
// 'time.Duration' but plain number, sice they were parsed HealthCheck *healthCheckSettings `json:"healthCheck,omitempty"`
// directly from json
HealthCheck *router.HealthPingSettings `json:"healthCheck,omitempty"`
// weight settings // weight settings
Costs []*router.StrategyWeight `json:"costs,omitempty"` Costs []*router.StrategyWeight `json:"costs,omitempty"`
// ping rtt baselines (ms) // ping rtt baselines
Baselines []int `json:"baselines,omitempty"` Baselines []Duration `json:"baselines,omitempty"`
// expected nodes count to select // expected nodes count to select
Expected int32 `json:"expected,omitempty"` Expected int32 `json:"expected,omitempty"`
// max acceptable rtt (ms), filter away high delay nodes. defalut 0 // max acceptable rtt, filter away high delay nodes. defalut 0
MaxRTT int `json:"maxRTT,omitempty"` MaxRTT Duration `json:"maxRTT,omitempty"`
// acceptable failure rate // acceptable failure rate
Tolerance float64 `json:"tolerance,omitempty"` Tolerance float64 `json:"tolerance,omitempty"`
} }
// healthCheckSettings holds settings for health Checker
type healthCheckSettings struct {
Destination string `json:"destination"`
Connectivity string `json:"connectivity"`
Interval Duration `json:"interval"`
SamplingCount int `json:"sampling"`
Timeout Duration `json:"timeout"`
}
// Build implements Buildable. // Build implements Buildable.
func (v *strategyLeastLoadConfig) Build() (proto.Message, error) { func (v *strategyLeastLoadConfig) Build() (proto.Message, error) {
config := &router.StrategyLeastLoadConfig{ config := &router.StrategyLeastLoadConfig{
@ -54,8 +59,8 @@ func (v *strategyLeastLoadConfig) Build() (proto.Message, error) {
config.HealthCheck = &router.HealthPingConfig{ config.HealthCheck = &router.HealthPingConfig{
Destination: v.HealthCheck.Destination, Destination: v.HealthCheck.Destination,
Connectivity: v.HealthCheck.Connectivity, Connectivity: v.HealthCheck.Connectivity,
Interval: int64(v.HealthCheck.Interval * time.Second), Interval: int64(v.HealthCheck.Interval),
Timeout: int64(v.HealthCheck.Timeout * time.Second), Timeout: int64(v.HealthCheck.Timeout),
SamplingCount: int32(v.HealthCheck.SamplingCount), SamplingCount: int32(v.HealthCheck.SamplingCount),
} }
} }
@ -71,7 +76,7 @@ func (v *strategyLeastLoadConfig) Build() (proto.Message, error) {
if config.Expected < 0 { if config.Expected < 0 {
config.Expected = 0 config.Expected = 0
} }
config.MaxRTT = int64(time.Duration(v.MaxRTT) * time.Millisecond) config.MaxRTT = int64(v.MaxRTT)
if config.MaxRTT < 0 { if config.MaxRTT < 0 {
config.MaxRTT = 0 config.MaxRTT = 0
} }
@ -80,7 +85,7 @@ func (v *strategyLeastLoadConfig) Build() (proto.Message, error) {
if b <= 0 { if b <= 0 {
continue continue
} }
config.Baselines = append(config.Baselines, int64(time.Duration(b)*time.Millisecond)) config.Baselines = append(config.Baselines, int64(b))
} }
return config, nil return config, nil
} }

View File

@ -78,9 +78,9 @@ func TestRouterConfig(t *testing.T) {
"type": "leastload", "type": "leastload",
"settings": { "settings": {
"healthCheck": { "healthCheck": {
"interval": 300, "interval": "5m0s",
"sampling": 2, "sampling": 2,
"timeout": 3, "timeout": "5s",
"destination": "dest", "destination": "dest",
"connectivity": "conn" "connectivity": "conn"
}, },
@ -91,9 +91,9 @@ func TestRouterConfig(t *testing.T) {
"value": 5 "value": 5
} }
], ],
"baselines": [400, 600], "baselines": ["400ms", "600ms"],
"expected": 6, "expected": 6,
"maxRTT": 1000, "maxRTT": "1000ms",
"tolerance": 0.5 "tolerance": 0.5
} }
}, },
@ -116,9 +116,9 @@ func TestRouterConfig(t *testing.T) {
Strategy: "leastload", Strategy: "leastload",
StrategySettings: serial.ToTypedMessage(&router.StrategyLeastLoadConfig{ StrategySettings: serial.ToTypedMessage(&router.StrategyLeastLoadConfig{
HealthCheck: &router.HealthPingConfig{ HealthCheck: &router.HealthPingConfig{
Interval: int64(time.Duration(300) * time.Second), Interval: int64(time.Duration(5) * time.Minute),
SamplingCount: 2, SamplingCount: 2,
Timeout: int64(time.Duration(3) * time.Second), Timeout: int64(time.Duration(5) * time.Second),
Destination: "dest", Destination: "dest",
Connectivity: "conn", Connectivity: "conn",
}, },