Pipe minRequestTimeout as an arg to the apiserver
This commit is contained in:
@@ -37,9 +37,10 @@ import (
|
||||
)
|
||||
|
||||
type APIInstaller struct {
|
||||
group *APIGroupVersion
|
||||
info *APIRequestInfoResolver
|
||||
prefix string // Path prefix where API resources are to be registered.
|
||||
group *APIGroupVersion
|
||||
info *APIRequestInfoResolver
|
||||
prefix string // Path prefix where API resources are to be registered.
|
||||
minRequestTimeout int
|
||||
}
|
||||
|
||||
// Struct capturing information about an action ("GET", "POST", "WATCH", PROXY", etc).
|
||||
@@ -419,7 +420,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
|
||||
addParams(route, action.Params)
|
||||
ws.Route(route)
|
||||
case "LIST": // List all resources of a kind.
|
||||
route := ws.GET(action.Path).To(ListResource(lister, watcher, reqScope, false)).
|
||||
route := ws.GET(action.Path).To(ListResource(lister, watcher, reqScope, false, a.minRequestTimeout)).
|
||||
Filter(m).
|
||||
Doc("list objects of kind "+kind).
|
||||
Operation("list"+kind).
|
||||
@@ -492,7 +493,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
|
||||
ws.Route(route)
|
||||
// TODO: deprecated
|
||||
case "WATCH": // Watch a resource.
|
||||
route := ws.GET(action.Path).To(ListResource(lister, watcher, reqScope, true)).
|
||||
route := ws.GET(action.Path).To(ListResource(lister, watcher, reqScope, true, a.minRequestTimeout)).
|
||||
Filter(m).
|
||||
Doc("watch changes to an object of kind "+kind).
|
||||
Operation("watch"+kind).
|
||||
@@ -506,7 +507,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag
|
||||
ws.Route(route)
|
||||
// TODO: deprecated
|
||||
case "WATCHLIST": // Watch all resources of a kind.
|
||||
route := ws.GET(action.Path).To(ListResource(lister, watcher, reqScope, true)).
|
||||
route := ws.GET(action.Path).To(ListResource(lister, watcher, reqScope, true, a.minRequestTimeout)).
|
||||
Filter(m).
|
||||
Doc("watch individual changes to a list of "+kind).
|
||||
Operation("watch"+kind+"list").
|
||||
|
@@ -140,17 +140,24 @@ const (
|
||||
MaxTimeoutSecs = 600
|
||||
)
|
||||
|
||||
// restContainer is a wrapper around a generic restful Container that also contains a MinRequestTimeout
|
||||
type RestContainer struct {
|
||||
*restful.Container
|
||||
MinRequestTimeout int
|
||||
}
|
||||
|
||||
// InstallREST registers the REST handlers (storage, watch, proxy and redirect) into a restful Container.
|
||||
// It is expected that the provided path root prefix will serve all operations. Root MUST NOT end
|
||||
// in a slash. A restful WebService is created for the group and version.
|
||||
func (g *APIGroupVersion) InstallREST(container *restful.Container) error {
|
||||
func (g *APIGroupVersion) InstallREST(container *RestContainer) error {
|
||||
info := &APIRequestInfoResolver{util.NewStringSet(strings.TrimPrefix(g.Root, "/")), g.Mapper}
|
||||
|
||||
prefix := path.Join(g.Root, g.Version)
|
||||
installer := &APIInstaller{
|
||||
group: g,
|
||||
info: info,
|
||||
prefix: prefix,
|
||||
group: g,
|
||||
info: info,
|
||||
prefix: prefix,
|
||||
minRequestTimeout: container.MinRequestTimeout,
|
||||
}
|
||||
ws, registrationErrors := installer.Install()
|
||||
container.Add(ws)
|
||||
|
@@ -231,7 +231,7 @@ func handleInternal(legacy bool, storage map[string]rest.Storage, admissionContr
|
||||
container := restful.NewContainer()
|
||||
container.Router(restful.CurlyRouter{})
|
||||
mux := container.ServeMux
|
||||
if err := group.InstallREST(container); err != nil {
|
||||
if err := group.InstallREST(&RestContainer{container, 0}); err != nil {
|
||||
panic(fmt.Sprintf("unable to install container %s: %v", group.Version, err))
|
||||
}
|
||||
ws := new(restful.WebService)
|
||||
@@ -1901,7 +1901,7 @@ func TestParentResourceIsRequired(t *testing.T) {
|
||||
Codec: newCodec,
|
||||
}
|
||||
container := restful.NewContainer()
|
||||
if err := group.InstallREST(container); err == nil {
|
||||
if err := group.InstallREST(&RestContainer{container, 0}); err == nil {
|
||||
t.Fatal("expected error")
|
||||
}
|
||||
|
||||
@@ -1929,7 +1929,7 @@ func TestParentResourceIsRequired(t *testing.T) {
|
||||
Codec: newCodec,
|
||||
}
|
||||
container = restful.NewContainer()
|
||||
if err := group.InstallREST(container); err != nil {
|
||||
if err := group.InstallREST(&RestContainer{container, 0}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
@@ -185,7 +185,7 @@ func ConnectResource(connecter rest.Connecter, scope RequestScope, admit admissi
|
||||
}
|
||||
|
||||
// ListResource returns a function that handles retrieving a list of resources from a rest.Storage object.
|
||||
func ListResource(r rest.Lister, rw rest.Watcher, scope RequestScope, forceWatch bool) restful.RouteFunction {
|
||||
func ListResource(r rest.Lister, rw rest.Watcher, scope RequestScope, forceWatch bool, minRequestTimeout int) restful.RouteFunction {
|
||||
return func(req *restful.Request, res *restful.Response) {
|
||||
w := res.ResponseWriter
|
||||
|
||||
@@ -252,7 +252,7 @@ func ListResource(r rest.Lister, rw rest.Watcher, scope RequestScope, forceWatch
|
||||
errorJSON(err, scope.Codec, w)
|
||||
return
|
||||
}
|
||||
serveWatch(watcher, scope, w, req)
|
||||
serveWatch(watcher, scope, w, req, minRequestTimeout)
|
||||
return
|
||||
}
|
||||
|
||||
|
@@ -66,10 +66,12 @@ func (w *realTimeoutFactory) TimeoutCh() (<-chan time.Time, func() bool) {
|
||||
}
|
||||
|
||||
// serveWatch handles serving requests to the server
|
||||
func serveWatch(watcher watch.Interface, scope RequestScope, w http.ResponseWriter, req *restful.Request) {
|
||||
// Each watch gets a random timeout to avoid thundering herds. Rand is seeded once in the api installer.
|
||||
timeout := time.Duration(MinTimeoutSecs+rand.Intn(MaxTimeoutSecs-MinTimeoutSecs)) * time.Second
|
||||
|
||||
func serveWatch(watcher watch.Interface, scope RequestScope, w http.ResponseWriter, req *restful.Request, minRequestTimeout int) {
|
||||
var timeout time.Duration
|
||||
if minRequestTimeout > 0 {
|
||||
// Each watch gets a random timeout to avoid thundering herds. Rand is seeded once in the api installer.
|
||||
timeout = time.Duration(minRequestTimeout+rand.Intn(2*minRequestTimeout-minRequestTimeout)) * time.Second
|
||||
}
|
||||
watchServer := &WatchServer{watcher, scope.Codec, func(obj runtime.Object) {
|
||||
if err := setSelfLink(obj, req, scope.Namer); err != nil {
|
||||
glog.V(5).Infof("Failed to set self link for object %v: %v", reflect.TypeOf(obj), err)
|
||||
|
Reference in New Issue
Block a user