-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unify duration configuration values #1738
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,6 +24,7 @@ import ( | |
"bytes" | ||
"encoding/json" | ||
"fmt" | ||
"math" | ||
"reflect" | ||
"strconv" | ||
"strings" | ||
|
@@ -97,6 +98,11 @@ func (d Duration) String() string { | |
// ParseExtendedDuration is a helper function that allows for string duration | ||
// values containing days. | ||
func ParseExtendedDuration(data string) (result time.Duration, err error) { | ||
// Assume millisecond values if data is provided with no units | ||
if t, errp := strconv.ParseFloat(data, 64); errp == nil { | ||
return time.Duration(t * float64(time.Millisecond)), nil | ||
} | ||
|
||
dPos := strings.IndexByte(data, 'd') | ||
if dPos < 0 { | ||
return time.ParseDuration(data) | ||
|
@@ -123,16 +129,6 @@ func ParseExtendedDuration(data string) (result time.Duration, err error) { | |
return time.Duration(days)*24*time.Hour + hours, nil | ||
} | ||
|
||
// ParseExtendedDurationMs wraps ParseExtendedDuration while assuming | ||
// millisecond values if data is provided with no units. | ||
// TODO: Merge this into ParseExtendedDuration once it's safe to do so globally. | ||
func ParseExtendedDurationMs(data string) (result time.Duration, err error) { | ||
if t, errp := strconv.ParseFloat(data, 32); errp == nil { | ||
data = fmt.Sprintf("%.2fms", t) | ||
} | ||
return ParseExtendedDuration(data) | ||
} | ||
|
||
// UnmarshalText converts text data to Duration | ||
func (d *Duration) UnmarshalText(data []byte) error { | ||
v, err := ParseExtendedDuration(string(data)) | ||
|
@@ -157,12 +153,10 @@ func (d *Duration) UnmarshalJSON(data []byte) error { | |
} | ||
|
||
*d = Duration(v) | ||
} else if t, errp := strconv.ParseFloat(string(data), 64); errp == nil { | ||
*d = Duration(t * float64(time.Millisecond)) | ||
} else { | ||
var v time.Duration | ||
if err := json.Unmarshal(data, &v); err != nil { | ||
return err | ||
} | ||
*d = Duration(v) | ||
return fmt.Errorf("'%s' is not a valid duration value", string(data)) | ||
} | ||
|
||
return nil | ||
|
@@ -233,3 +227,56 @@ func (d NullDuration) ValueOrZero() Duration { | |
|
||
return d.Duration | ||
} | ||
|
||
func getInt64(v interface{}) (int64, error) { | ||
switch n := v.(type) { | ||
case int: | ||
return int64(n), nil | ||
case int8: | ||
return int64(n), nil | ||
case int16: | ||
return int64(n), nil | ||
case int32: | ||
return int64(n), nil | ||
case int64: | ||
return n, nil | ||
case uint: | ||
return int64(n), nil | ||
case uint8: | ||
return int64(n), nil | ||
case uint16: | ||
return int64(n), nil | ||
case uint32: | ||
return int64(n), nil | ||
case uint64: | ||
if n > math.MaxInt64 { | ||
return 0, fmt.Errorf("%d is too big", n) | ||
} | ||
return int64(n), nil | ||
default: | ||
return 0, fmt.Errorf("unable to use type %T as a duration value", v) | ||
} | ||
} | ||
|
||
// GetDurationValue is a helper function that can convert a lot of different | ||
// types to time.Duration. | ||
// | ||
// TODO: move to a separate package and check for integer overflows? | ||
func GetDurationValue(v interface{}) (time.Duration, error) { | ||
switch d := v.(type) { | ||
case time.Duration: | ||
return d, nil | ||
case string: | ||
return ParseExtendedDuration(d) | ||
case float32: | ||
return time.Duration(float64(d) * float64(time.Millisecond)), nil | ||
case float64: | ||
return time.Duration(d * float64(time.Millisecond)), nil | ||
default: | ||
n, err := getInt64(v) | ||
Comment on lines
+267
to
+276
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are any beside time.Duration, string, float64 and int64 ... even possible? Because the previous code didn't handle the rest, and I have the feeling that was because we will never actually get one ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added them out of an abundance of caution... I have no idea if some weird webpack minification magic or something like that won't try to encode plain integer values as something that goja will export as uint8 or whatever... Stranger things have happened... 😅 And given that this helper function is intentionally outside of |
||
if err != nil { | ||
return 0, err | ||
} | ||
return time.Duration(n) * time.Millisecond, nil | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm still baffled that multiple cases don't work for type switches 😕:
This could be much more succinct:
But I guess there's a good reason for it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can do that, but then
n
will be of aninterface{}
type, and you can't directly cast that toint64
... You can do it via thereflect
package, but that'd be much slower and somewhat type unsafe.