Skip to content

Commit

Permalink
Context-aware methods to ProviderClient and ServiceClient
Browse files Browse the repository at this point in the history
Provide new methods to leverage per-call `context.Context`.

This version, suitable to be backported to `v1`, vendors the context
package from the v1.21 standard library, to make "context.AfterFunc"
available.
  • Loading branch information
pierreprinetti committed Feb 1, 2024
1 parent 51831d9 commit 843afd9
Show file tree
Hide file tree
Showing 4 changed files with 874 additions and 37 deletions.
54 changes: 54 additions & 0 deletions context.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package gophercloud

import (
"context"
"time"

future_context "github.com/gophercloud/gophercloud/internal/context"
)

type mergeContext struct {
context.Context
ctx2 context.Context
}

// MergeContext returns a context that is cancelled when at least one of the
// parents is cancelled. The returned context also returns the values of ctx1,
// or ctx2 if nil.
func MergeContext(ctx1, ctx2 context.Context) (context.Context, context.CancelFunc) {
ctx, cancel := future_context.WithCancelCause(ctx1)
stop := future_context.AfterFunc(ctx2, func() {
cancel(future_context.Cause(ctx2))
})

return &mergeContext{
Context: ctx,
ctx2: ctx2,
}, func() {
stop()
cancel(context.Canceled)
}
}

// Value returns ctx2's value if ctx's is nil.
func (ctx *mergeContext) Value(key interface{}) interface{} {
if v := ctx.Context.Value(key); v != nil {
return v
}
return ctx.ctx2.Value(key)
}

// Deadline returns the earlier deadline of the two parents of ctx.
func (ctx *mergeContext) Deadline() (time.Time, bool) {
if d1, ok := ctx.Context.Deadline(); ok {
if d2, ok := ctx.ctx2.Deadline(); ok {
if d1.Before(d2) {
return d1, true
} else {
return d2, true
}
}
return d1, ok
}
return ctx.ctx2.Deadline()
}

0 comments on commit 843afd9

Please sign in to comment.