Files
tasks/common/contextutil/deadline.go
Stephan BehnkeandGitHub 137ddcbfbb GetWorkflowExecutionHistory long poll soft timeout (#8238)
## What changed?

Added a "soft timeout" (language used by Workflow Update) to
`GetWorkflowExecutionHistory` long polls.

## Why?

We don't want to terminate the long poll connection but instead keep it
alive by sending a response back just before the timeout. The idea is
that this will prevent connections from opening/terminating repeatedly
(ie connection churn).

## How did you test it?
- [ ] built
- [x] run locally and tested manually
- [x] covered by existing tests
- [ ] added new unit test(s)
- [ ] added new functional test(s)

## Potential risks

I was only able to verify this manually by forcing a timeout in the
server and verifying that instead of a deadline exceeded I saw a result.
I'll assume this will work since the existing code already tried doing
just exactly that, but it didn't do it well.
2025-08-27 01:28:26 +00:00

38 lines
952 B
Go

package contextutil
import (
"context"
"time"
)
var noop = func() {}
// WithDeadlineBuffer creates a child context with desired timeout.
// If buffer is non-zero, then child context timeout will be
// the minOf(parentCtx.Deadline()-buffer, maxTimeout). Use this
// method to create child context when childContext cannot use
// all of parent's deadline but instead there is a need to leave
// some time for parent to do some post-work
func WithDeadlineBuffer(
parent context.Context,
timeout time.Duration,
buffer time.Duration,
) (context.Context, context.CancelFunc) {
if parent.Err() != nil {
return parent, noop
}
deadline, hasDeadline := parent.Deadline()
if !hasDeadline {
return context.WithTimeout(parent, timeout)
}
remaining := time.Until(deadline) - buffer
if remaining < timeout {
// Cap the timeout to the remaining time minus buffer.
timeout = max(0, remaining)
}
return context.WithTimeout(parent, timeout)
}