context2

package
v0.0.0-...-436d200 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 23, 2023 License: BSD-3-Clause Imports: 4 Imported by: 0

Documentation

Overview

Dropbox-specific workarounds for (self-inflicted) problems with the builtin context package.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func StripCancelAndDeadline

func StripCancelAndDeadline(parent context.Context) context.Context

Take a parent context and create a child that totally ignores the parent's cancellation signals (including cancel funcs, deadlines, and timeouts).

Sometimes it's useful to create a child context with all the metadata of the parent but not the cancellation/deadline of the parent. This function lets you do that.

For example, an RPC server might initiate background activity to be carried out after the request returns a result but still want the background RPCs to be traceable to the causing request. Courier cancels the context of the request once its handler func returns, which will cancel all the background activity if that context gets passed in. On the other hand, starting from context.Background() loses the tracing metadata from the originating request, making debugging more difficult.

WARNING: Stopwatches attached to contexts get broken if the child context outlives the parent, which is exacerbated when you use StripCancelAndDeadline to decouple the background goroutine's lifetime from the parent request. It's a good idea to specifically nuke the stopwatch metadata on top of calling StripCancelAndDeadline.

This kind of problem may apply to other libraries that use context-attached metadata, too. Use with care.

func StripDeadline

func StripDeadline(parent context.Context) context.Context

Creates a child context that has no Deadline() metadata. The child will still get cancelled if the parent's context deadline expires, or if the parent gets cancelled.

This is a workaround for Courier's deadline propagation. The Courier client implementation will look at the Deadline() on the context passed to an outbound call and send that deadline along with the request to the remote host. This sounds great in theory (it's just a straightforward generalization of the in-process deadline to RPCs, right?), but in practice, it's not. In the event the deadline expires, all hosts involved in the RPC's call stack will race to throw an error, and the remote server might actually send back a deadline error before the deadline on the clientside context has expired. It is also somewhat commonly the case that a deadline error will get mangled and be rendered unidentifiable as such by the time it gets back to the caller.

This makes it impossible for an RPC handler to tell for certain whether an error from an outbound RPC is due to a deadline originating from the handler's calling client vs. from a timeout set by the handler or by one of the services that handler calls. Since the two timeouts often diverge significantly, you want very much to know which is the case in order to decide whether to count an availability hit. Refusing to forward a client deadline achieves this - if you get any error back from your outbound RPC, you know it's not because the client gave your outbound RPC too little timeout to complete.

Note that it's okay to propagate the cancellation channel because, in order for the remote host to send back an error due to some cancellation signal you sent, you have to send a cancel message over the wire first. So you can check the context you passed to the outbound call to see if it has an Err() set, and, if so, you can safely write the other error from the outbound RPC off as irrelevant.

func WithCancelOnSignal

func WithCancelOnSignal(ctx context.Context, signals ...os.Signal) context.Context

The first time the process receives any of the given signals, cancels the returned context and deregisters the signal handler.

Types

type MockContextError

type MockContextError struct {
	Error error
}

A mock implementation of context.Context allowing specifying the return value of Err() This mock object doesn't implement the other parts of context cancelation/deadline handling, such as the Done() channel.

func (*MockContextError) Deadline

func (c *MockContextError) Deadline() (deadline time.Time, ok bool)

func (*MockContextError) Done

func (c *MockContextError) Done() <-chan struct{}

func (*MockContextError) Err

func (c *MockContextError) Err() error

func (*MockContextError) Value

func (c *MockContextError) Value(key interface{}) interface{}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL