| Index: common/prpc/timeout.go
|
| diff --git a/server/prpc/timeout.go b/common/prpc/timeout.go
|
| similarity index 51%
|
| rename from server/prpc/timeout.go
|
| rename to common/prpc/timeout.go
|
| index 9811395ff985f533ca6a1d928e5715b37bb040f6..25d3aec9c05c004518f6af56b07cea340cadda87 100644
|
| --- a/server/prpc/timeout.go
|
| +++ b/common/prpc/timeout.go
|
| @@ -10,10 +10,6 @@ import (
|
| "time"
|
| )
|
|
|
| -// headerTimeout is HTTP header used to set pRPC request timeout.
|
| -// The single value should match regexp `\d+[HMSmun]`.
|
| -const headerTimeout = "X-Prpc-Timeout"
|
| -
|
| // The rest of this file is adapted from
|
| // https://github.com/grpc/grpc-go/blob/6a026b9f108b49838491178e5d9bf7a4dcf32cf2/transport/http_util.go#L295
|
|
|
| @@ -47,7 +43,8 @@ func timeoutUnitToDuration(u timeoutUnit) (d time.Duration, ok bool) {
|
| return
|
| }
|
|
|
| -func decodeTimeout(s string) (time.Duration, error) {
|
| +// DecodeTimeout decodes a gRPC/pRPC timeout header string into a time.Duration.
|
| +func DecodeTimeout(s string) (time.Duration, error) {
|
| size := len(s)
|
| if size < 2 {
|
| return 0, fmt.Errorf("too short: %q", s)
|
| @@ -63,3 +60,39 @@ func decodeTimeout(s string) (time.Duration, error) {
|
| }
|
| return d * time.Duration(t), nil
|
| }
|
| +
|
| +const maxTimeoutValue int64 = 100000000 - 1
|
| +
|
| +// div does integer division and round-up the result. Note that this is
|
| +// equivalent to (d+r-1)/r but has less chance to overflow.
|
| +func div(d, r time.Duration) int64 {
|
| + if m := d % r; m > 0 {
|
| + return int64(d/r + 1)
|
| + }
|
| + return int64(d / r)
|
| +}
|
| +
|
| +// EncodeTimeout encodes a gRPC/pRPC timeout into a timeout header
|
| +// time.Duration.
|
| +//
|
| +// This rounds the time.Duration to the smallest time unit that can represent
|
| +// it.
|
| +func EncodeTimeout(t time.Duration) string {
|
| + if d := div(t, time.Nanosecond); d <= maxTimeoutValue {
|
| + return strconv.FormatInt(d, 10) + "n"
|
| + }
|
| + if d := div(t, time.Microsecond); d <= maxTimeoutValue {
|
| + return strconv.FormatInt(d, 10) + "u"
|
| + }
|
| + if d := div(t, time.Millisecond); d <= maxTimeoutValue {
|
| + return strconv.FormatInt(d, 10) + "m"
|
| + }
|
| + if d := div(t, time.Second); d <= maxTimeoutValue {
|
| + return strconv.FormatInt(d, 10) + "S"
|
| + }
|
| + if d := div(t, time.Minute); d <= maxTimeoutValue {
|
| + return strconv.FormatInt(d, 10) + "M"
|
| + }
|
| + // Note that maxTimeoutValue * time.Hour > MaxInt64.
|
| + return strconv.FormatInt(div(t, time.Hour), 10) + "H"
|
| +}
|
|
|