package runner import ( "context" "sync/atomic" ) type submissionCancellationGate struct { submitted atomic.Bool } type submissionCancellationGateKey struct{} func NewRequestExecutionContext(requestContext context.Context, serverContext context.Context) (context.Context, context.CancelFunc) { base, cancel := context.WithCancel(context.WithoutCancel(requestContext)) gate := &submissionCancellationGate{} ctx := context.WithValue(base, submissionCancellationGateKey{}, gate) go func() { select { case <-serverContext.Done(): cancel() case <-requestContext.Done(): if !gate.submitted.Load() { cancel() return } select { case <-serverContext.Done(): cancel() case <-base.Done(): } case <-base.Done(): } }() return ctx, cancel } func markUpstreamSubmissionStarted(ctx context.Context) { if gate, ok := ctx.Value(submissionCancellationGateKey{}).(*submissionCancellationGate); ok { gate.submitted.Store(true) } } func requestCancelledBeforeSubmission(ctx context.Context) bool { gate, ok := ctx.Value(submissionCancellationGateKey{}).(*submissionCancellationGate) return ok && ctx.Err() != nil && !gate.submitted.Load() }