metropolis/pkg: delete unused package combinectx

Change-Id: I7d92c2055f6010263013b6e0bd759d7f7906f2c0
Reviewed-on: https://review.monogon.dev/c/monogon/+/3000
Tested-by: Jenkins CI
Reviewed-by: Serge Bazanski <serge@monogon.tech>
diff --git a/metropolis/pkg/combinectx/BUILD.bazel b/metropolis/pkg/combinectx/BUILD.bazel
deleted file mode 100644
index 4eeca7f..0000000
--- a/metropolis/pkg/combinectx/BUILD.bazel
+++ /dev/null
@@ -1,17 +0,0 @@
-load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
-
-go_library(
-    name = "combinectx",
-    srcs = ["combinectx.go"],
-    importpath = "source.monogon.dev/metropolis/pkg/combinectx",
-    visibility = ["//visibility:public"],
-)
-
-go_test(
-    name = "combinectx_test",
-    srcs = [
-        "combinectx_test.go",
-        "example_test.go",
-    ],
-    embed = [":combinectx"],
-)
diff --git a/metropolis/pkg/combinectx/combinectx.go b/metropolis/pkg/combinectx/combinectx.go
deleted file mode 100644
index 3ff1d72..0000000
--- a/metropolis/pkg/combinectx/combinectx.go
+++ /dev/null
@@ -1,182 +0,0 @@
-// package combinectx implements context.Contexts that 'combine' two other
-// 'parent' contexts. These can be used to deal with cases where you want to
-// cancel a method call whenever any of two pre-existing contexts expires first.
-//
-// For example, if you want to tie a method call to some incoming request
-// context and an active leader lease, then this library is for you.
-package combinectx
-
-import (
-	"context"
-	"sync"
-	"time"
-)
-
-// Combine 'joins' two existing 'parent' contexts into a single context. This
-// context will be Done() whenever any of the parent context is Done().
-// Combining contexts spawns a goroutine that will be cleaned when any of the
-// parent contexts is Done().
-func Combine(a, b context.Context) context.Context {
-	c := &Combined{
-		a:     a,
-		b:     b,
-		doneC: make(chan struct{}),
-	}
-	go c.run()
-	return c
-}
-
-type Combined struct {
-	// a is the first parent context.
-	a context.Context
-	// b is the second parent context.
-	b context.Context
-
-	// mu guards done.
-	mu sync.Mutex
-	// done is an Error if either parent context is Done(), or nil otherwise.
-	done *Error
-	// doneC is closed when either parent context is Done() and Error is set.
-	doneC chan struct{}
-}
-
-// Error wraps errors returned by parent contexts.
-type Error struct {
-	// underlyingA points to an error returned by the first parent context if the
-	// combined context was Done() as a result of the first parent context being
-	// Done().
-	underlyingA *error
-	// underlyingB points to an error returned by the second parent context if the
-	// combined context was Done() as a result of the second parent context being
-	// Done().
-	underlyingB *error
-}
-
-func (e *Error) Error() string {
-	if e.underlyingA != nil {
-		return (*e.underlyingA).Error()
-	}
-	if e.underlyingB != nil {
-		return (*e.underlyingB).Error()
-	}
-	return ""
-}
-
-// First returns true if the Combined context's first parent was Done().
-func (e *Error) First() bool {
-	return e.underlyingA != nil
-}
-
-// Second returns true if the Combined context's second parent was Done().
-func (e *Error) Second() bool {
-	return e.underlyingB != nil
-}
-
-// Unwrap returns the underlying error of either parent context that is Done().
-func (e *Error) Unwrap() error {
-	if e.underlyingA != nil {
-		return *e.underlyingA
-	}
-	if e.underlyingB != nil {
-		return *e.underlyingB
-	}
-	return nil
-}
-
-// Is allows errors.Is to be true against any *Error.
-func (e *Error) Is(target error) bool {
-	if _, ok := target.(*Error); ok {
-		return true
-	}
-	return false
-}
-
-// As allows errors.As to be true against any *Error.
-func (e *Error) As(target interface{}) bool {
-	if v, ok := target.(**Error); ok {
-		*v = e
-		return true
-	}
-	return false
-}
-
-// run is the main logic that ties together the two parent contexts. It exits
-// when either parent context is canceled.
-func (c *Combined) run() {
-	mark := func(first bool, err error) {
-		c.mu.Lock()
-		defer c.mu.Unlock()
-		c.done = &Error{}
-		if first {
-			c.done.underlyingA = &err
-		} else {
-			c.done.underlyingB = &err
-		}
-		close(c.doneC)
-	}
-	select {
-	case <-c.a.Done():
-		mark(true, c.a.Err())
-	case <-c.b.Done():
-		mark(false, c.b.Err())
-	}
-}
-
-// Deadline returns the earlier Deadline from the two parent contexts, if any.
-func (c *Combined) Deadline() (deadline time.Time, ok bool) {
-	d1, ok1 := c.a.Deadline()
-	d2, ok2 := c.b.Deadline()
-
-	if ok1 && !ok2 {
-		return d1, true
-	}
-	if ok2 && !ok1 {
-		return d2, true
-	}
-	if !ok1 && !ok2 {
-		return time.Time{}, false
-	}
-
-	if d1.Before(d2) {
-		return d1, true
-	}
-	return d2, true
-}
-
-func (c *Combined) Done() <-chan struct{} {
-	return c.doneC
-}
-
-// Err returns nil if neither parent context is Done() yet, or an error otherwise.
-// The returned errors will have the following properties:
-//   1) errors.Is(err, Error{}) will always return true.
-//   2) errors.Is(err, ctx.Err()) will return true if the combined context was
-//      canceled with the same error as ctx.Err().
-//      However, this does NOT mean that the combined context was Done() because
-//      of the ctx being Done() - to ensure this is the case, use errors.As() to
-//      retrieve an Error and its First()/Second() methods.
-//   3) errors.Is(err, context.{Canceled,DeadlineExceeded}) will return true if
-//      the combined context is Canceled or DeadlineExceeded.
-//   4) errors.Is will return false otherwise.
-//   5) errors.As(err, &&Error{})) will always return true. The Error object can
-//      then be used to check the cause of the combined context's error.
-func (c *Combined) Err() error {
-	c.mu.Lock()
-	defer c.mu.Unlock()
-	if c.done == nil {
-		return nil
-	}
-	return c.done
-}
-
-// Value returns the value located under the given key by checking the first and
-// second parent context in order.
-func (c *Combined) Value(key interface{}) interface{} {
-	if v := c.a.Value(key); v != nil {
-		return v
-	}
-	if v := c.b.Value(key); v != nil {
-		return v
-	}
-	return nil
-}
diff --git a/metropolis/pkg/combinectx/combinectx_test.go b/metropolis/pkg/combinectx/combinectx_test.go
deleted file mode 100644
index 04efb2c..0000000
--- a/metropolis/pkg/combinectx/combinectx_test.go
+++ /dev/null
@@ -1,105 +0,0 @@
-package combinectx
-
-import (
-	"context"
-	"errors"
-	"testing"
-	"time"
-)
-
-func TestCancel(t *testing.T) {
-	a, aC := context.WithCancel(context.Background())
-	b, bC := context.WithCancel(context.Background())
-
-	c := Combine(a, b)
-	if want, got := error(nil), c.Err(); want != got {
-		t.Fatalf("Newly combined context should return %v, got %v", want, got)
-	}
-	if _, ok := c.Deadline(); ok {
-		t.Errorf("Newly combined context should have no deadline")
-	}
-
-	// Cancel A.
-	aC()
-	// Cancels are not synchronous - wait for it to propagate...
-	<-c.Done()
-	// ...then cancel B (no-op).
-	bC()
-
-	if c.Err() == nil {
-		t.Fatalf("After cancel, ctx.Err() should be non-nil")
-	}
-	if !errors.Is(c.Err(), a.Err()) {
-		t.Errorf("After cancel, ctx.Err() should be a.Err()")
-	}
-	if !errors.Is(c.Err(), c.Err()) {
-		t.Errorf("After cancel, ctx.Err() should be ctx.Err()")
-	}
-	if !errors.Is(c.Err(), context.Canceled) {
-		t.Errorf("After cancel, ctx.Err() should be context.Canceled")
-	}
-	if !errors.Is(c.Err(), &Error{}) {
-		t.Errorf("After cancel, ctx.Err() should be a Error pointer")
-	}
-	cerr := &Error{}
-	if !errors.As(c.Err(), &cerr) {
-		t.Fatalf("After cancel, ctx.Err() should be usable as *Error")
-	}
-	if !cerr.First() {
-		t.Errorf("ctx.Err().First() should be true")
-	}
-	if cerr.Second() {
-		t.Errorf("ctx.Err().Second() should be false")
-	}
-	if want, got := a.Err(), cerr.Unwrap(); want != got {
-		t.Errorf("ctx.Err().Unwrap() should be %v, got %v", want, got)
-	}
-}
-
-func TestDeadline(t *testing.T) {
-	now := time.Now()
-	aD := now.Add(100 * time.Millisecond)
-	bD := now.Add(10 * time.Millisecond)
-
-	a, aC := context.WithDeadline(context.Background(), aD)
-	b, bC := context.WithDeadline(context.Background(), bD)
-
-	defer aC()
-	defer bC()
-
-	c := Combine(a, b)
-	if want, got := error(nil), c.Err(); want != got {
-		t.Fatalf("Newly combined context should return %v, got %v", want, got)
-	}
-	if d, ok := c.Deadline(); !ok || !d.Equal(bD) {
-		t.Errorf("Newly combined context should have deadline %v, got %v", bD, d)
-	}
-
-	<-c.Done()
-
-	if c.Err() == nil {
-		t.Fatalf("After deadline, ctx.Err() should be non-nil")
-	}
-	if !errors.Is(c.Err(), b.Err()) {
-		t.Errorf("After deadline, ctx.Err() should be b.Err()")
-	}
-	if !errors.Is(c.Err(), context.DeadlineExceeded) {
-		t.Errorf("After cancel, ctx.Err() should be context.DeadlineExceeded")
-	}
-	if !errors.Is(c.Err(), &Error{}) {
-		t.Errorf("After cancel, ctx.Err() should be a Error pointer")
-	}
-	cerr := &Error{}
-	if !errors.As(c.Err(), &cerr) {
-		t.Fatalf("After cancel, ctx.Err() should be usable as *Error")
-	}
-	if cerr.First() {
-		t.Errorf("ctx.Err().First() should be false")
-	}
-	if !cerr.Second() {
-		t.Errorf("ctx.Err().Second() should be true")
-	}
-	if want, got := b.Err(), cerr.Unwrap(); want != got {
-		t.Errorf("ctx.Err().Unwrap() should be %v, got %v", want, got)
-	}
-}
diff --git a/metropolis/pkg/combinectx/example_test.go b/metropolis/pkg/combinectx/example_test.go
deleted file mode 100644
index f0cd70f..0000000
--- a/metropolis/pkg/combinectx/example_test.go
+++ /dev/null
@@ -1,77 +0,0 @@
-package combinectx_test
-
-import (
-	"context"
-	"errors"
-	"fmt"
-	"time"
-
-	"source.monogon.dev/metropolis/pkg/combinectx"
-)
-
-// ExampleCombine shows how to combine two contexts for use with a contextful
-// method.
-func ExampleCombine() {
-	// Let's say you're trying to combine two different contexts: the first one is
-	// some long-term local worker context, while the second is a context from some
-	// incoming request.
-	ctxA, cancelA := context.WithCancel(context.Background())
-	ctxB, cancelB := context.WithTimeout(context.Background(), time.Millisecond*100)
-	defer cancelA()
-	defer cancelB()
-
-	// doIO is some contextful, black box IO-heavy function. You want it to return
-	// early when either the long-term context or the short-term request context
-	// are Done().
-	doIO := func(ctx context.Context) (string, error) {
-		t := time.NewTicker(time.Second)
-		defer t.Stop()
-
-		select {
-		case <-ctx.Done():
-			return "", ctx.Err()
-		case <-t.C:
-			return "successfully reticulated splines", nil
-		}
-	}
-
-	// Combine the two given contexts into one...
-	ctx := combinectx.Combine(ctxA, ctxB)
-	// ... and call doIO with it.
-	v, err := doIO(ctx)
-	if err == nil {
-		fmt.Printf("doIO success: %v\n", v)
-		return
-	}
-
-	fmt.Printf("doIO failed: %v\n", err)
-
-	// The returned error will always be equal to the combined context's Err() call
-	// if the error is due to the combined context being Done().
-	if err == ctx.Err() {
-		fmt.Printf("doIO err == ctx.Err()\n")
-	}
-
-	// The returned error will pass any errors.Is(err, context....) checks. This
-	// ensures compatibility with blackbox code that performs special actions on
-	// the given context.
-	if errors.Is(err, context.DeadlineExceeded) {
-		fmt.Printf("doIO err is context.DeadlineExceeded\n")
-	}
-
-	// The returned error can be inspected by converting it to a *Error and calling
-	// .First()/.Second()/.Unwrap(). This lets the caller figure out which of the
-	// parent contexts caused the combined context to expires.
-	cerr := &combinectx.Error{}
-	if errors.As(err, &cerr) {
-		fmt.Printf("doIO err is *combinectx.Error\n")
-		fmt.Printf("doIO first failed: %v, second failed: %v\n", cerr.First(), cerr.Second())
-	}
-
-	// Output:
-	// doIO failed: context deadline exceeded
-	// doIO err == ctx.Err()
-	// doIO err is context.DeadlineExceeded
-	// doIO err is *combinectx.Error
-	// doIO first failed: false, second failed: true
-}