src/go/configgenerator/routegen/helpers/deadline.go (44 lines of code) (raw):
package helpers
import (
"time"
"github.com/GoogleCloudPlatform/esp-v2/src/go/options"
"github.com/GoogleCloudPlatform/esp-v2/src/go/util"
routepb "github.com/envoyproxy/go-control-plane/envoy/config/route/v3"
"google.golang.org/protobuf/types/known/durationpb"
)
// RouteDeadlineConfiger is a helper to configure deadlines and timeouts on
// backend routes.
type RouteDeadlineConfiger struct {
GlobalStreamIdleTimeout time.Duration
}
// NewRouteDeadlineConfigerFromOPConfig creates a RouteDeadlineConfiger from
// ESPv2 options.
func NewRouteDeadlineConfigerFromOPConfig(opts options.ConfigGeneratorOptions) *RouteDeadlineConfiger {
return &RouteDeadlineConfiger{
GlobalStreamIdleTimeout: opts.StreamIdleTimeout,
}
}
// MaybeAddDeadlines adds the generated deadline config to the route action.
func MaybeAddDeadlines(c *RouteDeadlineConfiger, routeAction *routepb.RouteAction, deadline time.Duration, isStreaming bool) {
if c == nil {
return
}
newDeadline, idleTimeout := c.CalcIdleTimeout(deadline, isStreaming)
routeAction.Timeout = durationpb.New(newDeadline)
routeAction.IdleTimeout = durationpb.New(idleTimeout)
}
// CalcIdleTimeout will return the correct idle timeout based on method properties.
//
// Forked from `service_info.go`
func (c *RouteDeadlineConfiger) CalcIdleTimeout(deadline time.Duration, isStreaming bool) (time.Duration, time.Duration) {
// Response timeouts are not compatible with streaming methods (documented in Envoy).
// This applies to methods with a streaming upstream OR downstream.
var idleTimeout time.Duration
if isStreaming {
if deadline <= 0 {
// When the backend deadline is unspecified , calculate the streamIdleTimeout based on max{defaultTimeout, globalStreamIdleTimeout} .
idleTimeout = calculateStreamIdleTimeout(util.DefaultResponseDeadline, c.GlobalStreamIdleTimeout)
} else {
// User configured deadline serves as the stream idle timeout.
idleTimeout = deadline
}
return 0, idleTimeout
}
if deadline <= 0 {
// If no deadline specified by the user, explicitly use default.
deadline = util.DefaultResponseDeadline
}
// Allow per-route response deadlines to override the global stream idle timeout.
idleTimeout = calculateStreamIdleTimeout(deadline, c.GlobalStreamIdleTimeout)
return deadline, idleTimeout
}
// Calculates the stream idle timeout based on the response deadline for that route and the global stream idle timeout.
//
// Forked from `service_info.go`
func calculateStreamIdleTimeout(operationDeadline time.Duration, streamIdleTimeout time.Duration) time.Duration {
// If the deadline and stream idle timeout have the exact same timeout,
// the error code returned to the client is inconsistent based on which event is processed first.
// (504 for response deadline, 408 for idle timeout)
// So offset the idle timeout to ensure response deadline is always hit first.
operationIdleTimeout := operationDeadline + time.Second
return util.MaxDuration(operationIdleTimeout, streamIdleTimeout)
}