-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: sort redis configuration (#107)
* fix: sort redis configuration * fix: yaml serialization * fix: add comment * fix: add comment * fix: doc * fix: doc
- Loading branch information
Showing
6 changed files
with
251 additions
and
45 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package config | ||
|
||
import ( | ||
"encoding/json" | ||
"errors" | ||
"time" | ||
|
||
"gopkg.in/yaml.v3" | ||
) | ||
|
||
// Duration is a type that describe a time duration. It is suitable for use in | ||
// configurations as it implements a variety of serialization methods. | ||
type Duration struct { | ||
time.Duration | ||
} | ||
|
||
// MarshalYAML implements Marshaller | ||
func (d Duration) MarshalYAML() (interface{}, error) { | ||
return d.String(), nil | ||
} | ||
|
||
// UnmarshalYAML implements Unmarshaller | ||
func (d *Duration) UnmarshalYAML(value *yaml.Node) error { | ||
if value.Tag == "!!float" { | ||
return d.UnmarshalJSON([]byte(value.Value)) | ||
} | ||
return d.UnmarshalJSON([]byte("\"" + value.Value + "\"")) | ||
} | ||
|
||
// MarshalJSON implements JSONMarshaller | ||
func (d Duration) MarshalJSON() ([]byte, error) { | ||
return json.Marshal(d.String()) | ||
} | ||
|
||
// UnmarshalJSON implements JSONUnmarsheller | ||
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 float64: | ||
d.Duration = time.Duration(value) | ||
return nil | ||
case string: | ||
var err error | ||
d.Duration, err = time.ParseDuration(value) | ||
if err != nil { | ||
return err | ||
} | ||
return nil | ||
default: | ||
return errors.New("invalid duration") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
package config | ||
|
||
import ( | ||
"encoding/json" | ||
"testing" | ||
"time" | ||
|
||
"github.com/stretchr/testify/assert" | ||
"gopkg.in/yaml.v3" | ||
) | ||
|
||
func TestDuration_UnmarshalJSON(t *testing.T) { | ||
var cases = []struct { | ||
name string | ||
value string | ||
expected Duration | ||
}{ | ||
{ | ||
"simple", | ||
`"5s"`, | ||
Duration{5 * time.Second}, | ||
}, | ||
{ | ||
"float", | ||
`65000000000.0`, | ||
Duration{5*time.Second + time.Minute}, | ||
}, | ||
} | ||
|
||
for _, c := range cases { | ||
c := c | ||
t.Run(c.name, func(t *testing.T) { | ||
t.Parallel() | ||
v1 := Duration{} | ||
yaml.Unmarshal([]byte(c.value), &v1) | ||
assert.Equal(t, c.expected, v1) | ||
v2 := Duration{} | ||
json.Unmarshal([]byte(c.value), &v2) | ||
assert.Equal(t, c.expected, v2) | ||
}) | ||
} | ||
} | ||
|
||
func TestDuration_MarshalJSON(t *testing.T) { | ||
var cases = []struct { | ||
name string | ||
value interface{} | ||
expectedJSON string | ||
expectedYaml string | ||
}{ | ||
{ | ||
"simple", | ||
Duration{5 * time.Second}, | ||
`"5s"`, | ||
"5s\n", | ||
}, | ||
{ | ||
"complex", | ||
Duration{5*time.Second + time.Minute}, | ||
`"1m5s"`, | ||
"1m5s\n", | ||
}, | ||
{ | ||
"wrapped", | ||
struct{ D Duration }{Duration{5*time.Second + time.Minute}}, | ||
`{"D":"1m5s"}`, | ||
"d: 1m5s\n", | ||
}, | ||
} | ||
|
||
for _, c := range cases { | ||
c := c | ||
t.Run(c.name, func(t *testing.T) { | ||
t.Parallel() | ||
data, err := json.Marshal(c.value) | ||
assert.NoError(t, err) | ||
assert.Equal(t, c.expectedJSON, string(data)) | ||
data, err = yaml.Marshal(c.value) | ||
assert.Equal(t, c.expectedYaml, string(data)) | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package otredis | ||
|
||
import ( | ||
"github.com/DoNewsCode/core/config" | ||
) | ||
|
||
// RedisUniversalOptions is the configuration options for redis. | ||
type RedisUniversalOptions struct { | ||
// Either a single address or a seed list of host:port addresses | ||
// of cluster/sentinel nodes. | ||
Addrs []string `json:"addrs" yaml:"addrs"` | ||
|
||
// Database to be selected after connecting to the server. | ||
// Only single-node and failover clients. | ||
DB int `json:"db" yaml:"db"` | ||
|
||
// Common options. | ||
|
||
Username string `json:"username" yaml:"username"` | ||
Password string `json:"password" yaml:"password"` | ||
SentinelPassword string `json:"sentinelPassword" yaml:"sentinelPassword"` | ||
|
||
MaxRetries int `json:"maxRetries" yaml:"maxRetries"` | ||
MinRetryBackoff config.Duration `json:"minRetryBackoff" yaml:"minRetryBackoff"` | ||
MaxRetryBackoff config.Duration `json:"maxRetryBackoff" yaml:"maxRetryBackoff"` | ||
|
||
DialTimeout config.Duration `json:"dialTimeout" yaml:"dialTimeout"` | ||
ReadTimeout config.Duration `json:"readTimeout" yaml:"readTimeout"` | ||
WriteTimeout config.Duration `json:"writeTimeout" yaml:"writeTimeout"` | ||
|
||
PoolSize int `json:"poolSize" yaml:"poolSize"` | ||
MinIdleConns int `json:"minIdleConns" yaml:"minIdleConns"` | ||
MaxConnAge config.Duration `json:"maxConnAge" yaml:"maxConnAge"` | ||
PoolTimeout config.Duration `json:"poolTimeout" yaml:"poolTimeout"` | ||
IdleTimeout config.Duration `json:"idleTimeout" yaml:"idleTimeout"` | ||
IdleCheckFrequency config.Duration `json:"idleCheckFrequency" yaml:"idleCheckFrequency"` | ||
|
||
// Only cluster clients. | ||
|
||
MaxRedirects int `json:"maxRedirects" yaml:"maxRedirects"` | ||
ReadOnly bool `json:"readOnly" yaml:"readOnly"` | ||
RouteByLatency bool `json:"routeByLatency" yaml:"routeByLatency"` | ||
RouteRandomly bool `json:"routeRandomly" yaml:"routeRandomly"` | ||
|
||
// The sentinel master name. | ||
// Only failover clients. | ||
MasterName string `json:"masterName" yaml:"masterName"` | ||
} |