Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions pkg/queue/sharedmain/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"context"
"net"
"net/http"
"sync/atomic"
"time"

"go.uber.org/zap"
Expand All @@ -43,6 +44,7 @@ func mainHandler(
prober func() bool,
stats *netstats.RequestStats,
logger *zap.SugaredLogger,
pendingRequests *atomic.Int32,
) (http.Handler, *pkghandler.Drainer) {
target := net.JoinHostPort("127.0.0.1", env.UserPort)

Expand Down Expand Up @@ -86,6 +88,8 @@ func mainHandler(

composedHandler = withFullDuplex(composedHandler, env.EnableHTTPFullDuplex, logger)

composedHandler = withRequestCounter(composedHandler, pendingRequests)

drainer := &pkghandler.Drainer{
QuietPeriod: drainSleepDuration,
// Add Activator probe header to the drainer so it can handle probes directly from activator
Expand All @@ -100,6 +104,7 @@ func mainHandler(
// Hence we need to have RequestLogHandler be the first one.
composedHandler = requestLogHandler(logger, composedHandler, env)
}

return composedHandler, drainer
}

Expand Down Expand Up @@ -139,3 +144,11 @@ func withFullDuplex(h http.Handler, enableFullDuplex bool, logger *zap.SugaredLo
h.ServeHTTP(w, r)
})
}

func withRequestCounter(h http.Handler, pendingRequests *atomic.Int32) http.Handler {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we create an struct that implements http.Handler and it holds the atomic counter - that would make this reusable

Your handler can hold the next handler so you can call h.ServeHTTP(w, r)

return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
pendingRequests.Add(1)
defer pendingRequests.Add(-1)
h.ServeHTTP(w, r)
})
}
21 changes: 19 additions & 2 deletions pkg/queue/sharedmain/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"net/http"
"os"
"strconv"
"sync/atomic"
"time"

"github.com/kelseyhightower/envconfig"
Expand Down Expand Up @@ -169,6 +170,8 @@
d := Defaults{
Ctx: signals.NewContext(),
}
pendingRequests := atomic.Int32{}
pendingRequests.Store(0)
Comment on lines +173 to +174
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above comment - let's merge this into a special http.Handler struct counting requests - that is created in the mainHandler function


// Parse the environment.
var env config
Expand Down Expand Up @@ -234,7 +237,7 @@
// Enable TLS when certificate is mounted.
tlsEnabled := exists(logger, certPath) && exists(logger, keyPath)

mainHandler, drainer := mainHandler(d.Ctx, env, d.Transport, probe, stats, logger)
mainHandler, drainer := mainHandler(d.Ctx, env, d.Transport, probe, stats, logger, &pendingRequests)
adminHandler := adminHandler(d.Ctx, logger, drainer)

// Enable TLS server when activator server certs are mounted.
Expand Down Expand Up @@ -303,9 +306,23 @@
return err
case <-d.Ctx.Done():
logger.Info("Received TERM signal, attempting to gracefully shutdown servers.")
logger.Infof("Sleeping %v to allow K8s propagation of non-ready state", drainSleepDuration)
drainer.Drain()

// Wait on active requests to complete. This is done explictly

Check failure on line 311 in pkg/queue/sharedmain/main.go

View workflow job for this annotation

GitHub Actions / style / Golang / Lint

"explictly" is a misspelling of "explicitly"

Check failure on line 311 in pkg/queue/sharedmain/main.go

View workflow job for this annotation

GitHub Actions / style / Golang / Lint

[github.com/client9/misspell] reported by reviewdog 🐶 "explictly" is a misspelling of "explicitly" Raw Output: pkg/queue/sharedmain/main.go:311:55: "explictly" is a misspelling of "explicitly"

Check failure on line 311 in pkg/queue/sharedmain/main.go

View workflow job for this annotation

GitHub Actions / style / Golang / Lint

"explictly" is a misspelling of "explicitly"

Check failure on line 311 in pkg/queue/sharedmain/main.go

View workflow job for this annotation

GitHub Actions / style / Golang / Lint

[github.com/client9/misspell] reported by reviewdog 🐶 "explictly" is a misspelling of "explicitly" Raw Output: pkg/queue/sharedmain/main.go:311:55: "explictly" is a misspelling of "explicitly"
// to avoid closing any connections which have been highjacked,
// as in net/http `.Shutdown` would do so ungracefully.
// See https://github.com/golang/go/issues/17721
ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop()
logger.Infof("Drain: waiting for %d pending requests to complete", pendingRequests.Load())
WaitOnPendingRequests:
for range ticker.C {
if pendingRequests.Load() <= 0 {
logger.Infof("Drain: all pending requests completed")
break WaitOnPendingRequests
}
}

for name, srv := range httpServers {
logger.Info("Shutting down server: ", name)
if err := srv.Shutdown(context.Background()); err != nil {
Expand Down
43 changes: 43 additions & 0 deletions test/e2e/websocket_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,11 @@
idleTimeoutSeconds: 10,
delay: "20",
expectError: true,
}, {
name: "websocket does not drop after queue drain is called at 30s",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should make a separate this - cause this isn't really testing the WebSocket Timeout but instead we're testing that draining long running requests works as expected.

timeoutSeconds: 60,
delay: "45",
expectError: false,
}}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
Expand Down Expand Up @@ -349,9 +354,47 @@
}
}

func TestWebSocketDrain(t *testing.T) {
clients := Setup(t)

testCases := []struct {
name string
timeoutSeconds int64
delay string
expectError bool
}{{
name: "websocket does not drop after queue drain is called",
timeoutSeconds: 60,
delay: "45",
expectError: false,
}}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
names := test.ResourceNames{
Service: test.ObjectNameForTest(t),
Image: wsServerTestImageName,
}

// Clean up in both abnormal and normal exits.
test.EnsureTearDown(t, clients, &names)

_, err := v1test.CreateServiceReady(t, clients, &names,
rtesting.WithRevisionTimeoutSeconds(tc.timeoutSeconds),
if err != nil {

Check failure on line 383 in test/e2e/websocket_test.go

View workflow job for this annotation

GitHub Actions / style / Golang / Auto-format and Check

expected operand, found 'if'

Check failure on line 383 in test/e2e/websocket_test.go

View workflow job for this annotation

GitHub Actions / style / Golang / Auto-format and Check

expected operand, found 'if'

Check failure on line 383 in test/e2e/websocket_test.go

View workflow job for this annotation

GitHub Actions / build / Build

expected operand, found 'if'

Check failure on line 383 in test/e2e/websocket_test.go

View workflow job for this annotation

GitHub Actions / style / Golang / Lint

syntax error: unexpected keyword if, expected expression (typecheck)

Check failure on line 383 in test/e2e/websocket_test.go

View workflow job for this annotation

GitHub Actions / style / Golang / Lint

expected operand, found 'if' (typecheck)

Check failure on line 383 in test/e2e/websocket_test.go

View workflow job for this annotation

GitHub Actions / build / Build

expected operand, found 'if'

Check failure on line 383 in test/e2e/websocket_test.go

View workflow job for this annotation

GitHub Actions / style / Golang / Lint

syntax error: unexpected keyword if, expected expression (typecheck)

Check failure on line 383 in test/e2e/websocket_test.go

View workflow job for this annotation

GitHub Actions / style / Golang / Lint

expected operand, found 'if' (typecheck)
t.Fatal("Failed to create WebSocket server:", err)

Check failure on line 384 in test/e2e/websocket_test.go

View workflow job for this annotation

GitHub Actions / style / Golang / Auto-format and Check

missing ',' before newline in composite literal

Check failure on line 384 in test/e2e/websocket_test.go

View workflow job for this annotation

GitHub Actions / style / Golang / Auto-format and Check

missing ',' before newline in composite literal

Check failure on line 384 in test/e2e/websocket_test.go

View workflow job for this annotation

GitHub Actions / style / Golang / Lint

missing ',' before newline in composite literal (typecheck)

Check failure on line 384 in test/e2e/websocket_test.go

View workflow job for this annotation

GitHub Actions / style / Golang / Lint

missing ',' before newline in composite literal (typecheck)
}

Check failure on line 385 in test/e2e/websocket_test.go

View workflow job for this annotation

GitHub Actions / style / Golang / Auto-format and Check

missing ',' before newline in argument list

Check failure on line 385 in test/e2e/websocket_test.go

View workflow job for this annotation

GitHub Actions / style / Golang / Auto-format and Check

missing ',' before newline in argument list

Check failure on line 385 in test/e2e/websocket_test.go

View workflow job for this annotation

GitHub Actions / style / Golang / Lint

missing ',' before newline in argument list (typecheck)

Check failure on line 385 in test/e2e/websocket_test.go

View workflow job for this annotation

GitHub Actions / style / Golang / Lint

missing ',' before newline in argument list (typecheck)
// Validate the websocket connection.
err = ValidateWebSocketConnection(t, clients, names, tc.delay)

Check failure on line 387 in test/e2e/websocket_test.go

View workflow job for this annotation

GitHub Actions / style / Golang / Auto-format and Check

expected '==', found '='

Check failure on line 387 in test/e2e/websocket_test.go

View workflow job for this annotation

GitHub Actions / style / Golang / Auto-format and Check

expected '==', found '='

Check failure on line 387 in test/e2e/websocket_test.go

View workflow job for this annotation

GitHub Actions / style / Golang / Lint

expected '==', found '=' (typecheck)

Check failure on line 387 in test/e2e/websocket_test.go

View workflow job for this annotation

GitHub Actions / style / Golang / Lint

expected '==', found '=' (typecheck)
if (err == nil && tc.expectError) || (err != nil && !tc.expectError) {

Check failure on line 388 in test/e2e/websocket_test.go

View workflow job for this annotation

GitHub Actions / style / Golang / Auto-format and Check

expected operand, found 'if'

Check failure on line 388 in test/e2e/websocket_test.go

View workflow job for this annotation

GitHub Actions / style / Golang / Auto-format and Check

expected operand, found 'if'

Check failure on line 388 in test/e2e/websocket_test.go

View workflow job for this annotation

GitHub Actions / style / Golang / Lint

expected operand, found 'if' (typecheck)

Check failure on line 388 in test/e2e/websocket_test.go

View workflow job for this annotation

GitHub Actions / style / Golang / Lint

expected operand, found 'if' (typecheck)
t.Error(err)

Check failure on line 389 in test/e2e/websocket_test.go

View workflow job for this annotation

GitHub Actions / style / Golang / Auto-format and Check

missing ',' before newline in argument list

Check failure on line 389 in test/e2e/websocket_test.go

View workflow job for this annotation

GitHub Actions / style / Golang / Auto-format and Check

missing ',' before newline in argument list

Check failure on line 389 in test/e2e/websocket_test.go

View workflow job for this annotation

GitHub Actions / style / Golang / Lint

missing ',' before newline in argument list (typecheck)

Check failure on line 389 in test/e2e/websocket_test.go

View workflow job for this annotation

GitHub Actions / style / Golang / Lint

missing ',' before newline in argument list (typecheck)
}

Check failure on line 390 in test/e2e/websocket_test.go

View workflow job for this annotation

GitHub Actions / style / Golang / Auto-format and Check

expected operand, found '}'

Check failure on line 390 in test/e2e/websocket_test.go

View workflow job for this annotation

GitHub Actions / style / Golang / Auto-format and Check

expected operand, found '}'

Check failure on line 390 in test/e2e/websocket_test.go

View workflow job for this annotation

GitHub Actions / style / Golang / Lint

expected operand, found '}' (typecheck)

Check failure on line 390 in test/e2e/websocket_test.go

View workflow job for this annotation

GitHub Actions / style / Golang / Lint

expected operand, found '}' (typecheck)
})
}
}

func abs(a int) int {
if a < 0 {

Check failure on line 396 in test/e2e/websocket_test.go

View workflow job for this annotation

GitHub Actions / style / Golang / Auto-format and Check

missing ',' in argument list

Check failure on line 396 in test/e2e/websocket_test.go

View workflow job for this annotation

GitHub Actions / style / Golang / Auto-format and Check

missing ',' in argument list

Check failure on line 396 in test/e2e/websocket_test.go

View workflow job for this annotation

GitHub Actions / style / Golang / Lint

missing ',' in argument list (typecheck)

Check failure on line 396 in test/e2e/websocket_test.go

View workflow job for this annotation

GitHub Actions / style / Golang / Lint

missing ',' in argument list (typecheck)
return -a

Check failure on line 397 in test/e2e/websocket_test.go

View workflow job for this annotation

GitHub Actions / style / Golang / Auto-format and Check

expected operand, found 'return'

Check failure on line 397 in test/e2e/websocket_test.go

View workflow job for this annotation

GitHub Actions / style / Golang / Auto-format and Check

expected operand, found 'return'

Check failure on line 397 in test/e2e/websocket_test.go

View workflow job for this annotation

GitHub Actions / style / Golang / Lint

expected operand, found 'return' (typecheck)

Check failure on line 397 in test/e2e/websocket_test.go

View workflow job for this annotation

GitHub Actions / style / Golang / Lint

expected operand, found 'return' (typecheck)
}

Check failure on line 398 in test/e2e/websocket_test.go

View workflow job for this annotation

GitHub Actions / style / Golang / Auto-format and Check

expected operand, found '}'

Check failure on line 398 in test/e2e/websocket_test.go

View workflow job for this annotation

GitHub Actions / style / Golang / Auto-format and Check

expected operand, found '}'
return a
}
Loading