123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081 |
- package context
- import "context"
- // valueOnlyContext provides a utility to preserve only the values of a
- // Context. Suppressing any cancellation or deadline on that context being
- // propagated downstream of this value.
- //
- // If preserveExpiredValues is false (default), and the valueCtx is canceled,
- // calls to lookup values with the Values method, will always return nil. Setting
- // preserveExpiredValues to true, will allow the valueOnlyContext to lookup
- // values in valueCtx even if valueCtx is canceled.
- //
- // Based on the Go standard libraries net/lookup.go onlyValuesCtx utility.
- // https://github.com/golang/go/blob/da2773fe3e2f6106634673a38dc3a6eb875fe7d8/src/net/lookup.go
- type valueOnlyContext struct {
- context.Context
- preserveExpiredValues bool
- valuesCtx context.Context
- }
- var _ context.Context = (*valueOnlyContext)(nil)
- // Value looks up the key, returning its value. If configured to not preserve
- // values of expired context, and the wrapping context is canceled, nil will be
- // returned.
- func (v *valueOnlyContext) Value(key interface{}) interface{} {
- if !v.preserveExpiredValues {
- select {
- case <-v.valuesCtx.Done():
- return nil
- default:
- }
- }
- return v.valuesCtx.Value(key)
- }
- // WithSuppressCancel wraps the Context value, suppressing its deadline and
- // cancellation events being propagated downstream to consumer of the returned
- // context.
- //
- // By default the wrapped Context's Values are available downstream until the
- // wrapped Context is canceled. Once the wrapped Context is canceled, Values
- // method called on the context return will no longer lookup any key. As they
- // are now considered expired.
- //
- // To override this behavior, use WithPreserveExpiredValues on the Context
- // before it is wrapped by WithSuppressCancel. This will make the Context
- // returned by WithSuppressCancel allow lookup of expired values.
- func WithSuppressCancel(ctx context.Context) context.Context {
- return &valueOnlyContext{
- Context: context.Background(),
- valuesCtx: ctx,
- preserveExpiredValues: GetPreserveExpiredValues(ctx),
- }
- }
- type preserveExpiredValuesKey struct{}
- // WithPreserveExpiredValues adds a Value to the Context if expired values
- // should be preserved, and looked up by a Context wrapped by
- // WithSuppressCancel.
- //
- // WithPreserveExpiredValues must be added as a value to a Context, before that
- // Context is wrapped by WithSuppressCancel
- func WithPreserveExpiredValues(ctx context.Context, enable bool) context.Context {
- return context.WithValue(ctx, preserveExpiredValuesKey{}, enable)
- }
- // GetPreserveExpiredValues looks up, and returns the PreserveExpressValues
- // value in the context. Returning true if enabled, false otherwise.
- func GetPreserveExpiredValues(ctx context.Context) bool {
- v := ctx.Value(preserveExpiredValuesKey{})
- if v != nil {
- return v.(bool)
- }
- return false
- }
|