1. 20
    1. 6

      Hey, this is a really interesting problem that i think lots of companies hit without noticing, however i think there are simpler ways of tackling it, i figured i could give a few pointers on how your code might be simpler and smaller.

      Firstly with your DisconnectContext you can eliminate stubbing a lot of your fields by embedding the parent context rather than stubbing them eg:

      type DisconnectContext struct {
          context.Context
      }
      

      then only overriding methods you need to change the behaviour of (https://golangbyexample.com/embedding-interfaces-go/).

      edit: i just deleted some stuff about wrapping in another WithCancel to avoid the DisconnectContext from this comment because i was wrong!

      here’s the example i used to prove myself wrong : https://play.golang.org/p/ynNwc-otFGO

      1. 5

        Thanks! I intentionally didn’t use embedding so that I could explicitly show the delegation of Value to the parent. Otherwise, that would be the only method missing from the impl and might be lost to the reader.

      2. 2

        This is roughly what we do at DO. The main thing is that your DisconnectContext wraps its parent but noops on Done()

    2. 2

      I want to see a language with a built-in mechanism for this kind of ambient context. Something strongly-typed, that allows application developers to supply context values that “follow” across things like async “callLater” type deferrals, as well as being useful for structural “container” hierarchies like eg something like a react context.

      But I don’t want it just as an alternative to explicit call parameters, I’d also like to be able to push/pop contextual information for debugging, which would be available when running in debug-mode alongside a regular stack trace.

      1. 2
      2. 1

        Common Lisp has special variables, which are exactly for dynamic context. Regarding type, you can always just DECLAIM or PROCLAIM a type for the special variable.

    3. 1

      I don’t understand why you wouldn’t want a timeout for the secondary request… But, naturally, this functionality is not exposed (in the context pkg), and the cancellation aspects are a bit tricky…

      1. 1

        One reason is if you’re delegating asynchronous calls (something with side effects, say a cleanup process) but still want to preserve the original context for observability/tracing purposes.

        1. 1

          SOOOO. I think the thing I missed is that you can still context.WithCancel() on this dummy context. So, nothing should be lost..