1. 20
  1.  

  2. 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.

      1. 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
          1. 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.

          2. 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..