fixup! refactor(container): restart handling

This commit is contained in:
Rob Watson 2025-04-12 19:41:31 +02:00
parent 7eff6c6065
commit a0a2e55a67

View File

@ -21,7 +21,6 @@ import (
"github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/filters"
"github.com/docker/docker/api/types/image" "github.com/docker/docker/api/types/image"
"github.com/docker/docker/api/types/network" "github.com/docker/docker/api/types/network"
"github.com/docker/docker/errdefs"
ocispec "github.com/opencontainers/image-spec/specs-go/v1" ocispec "github.com/opencontainers/image-spec/specs-go/v1"
) )
@ -72,6 +71,7 @@ type Client struct {
wg sync.WaitGroup wg sync.WaitGroup
apiClient DockerClient apiClient DockerClient
networkID string networkID string
cancelFuncs map[string]context.CancelFunc
pulledImages map[string]struct{} pulledImages map[string]struct{}
logger *slog.Logger logger *slog.Logger
} }
@ -99,6 +99,7 @@ func NewClient(ctx context.Context, apiClient DockerClient, logger *slog.Logger)
cancel: cancel, cancel: cancel,
apiClient: apiClient, apiClient: apiClient,
networkID: network.ID, networkID: network.ID,
cancelFuncs: make(map[string]context.CancelFunc),
pulledImages: make(map[string]struct{}), pulledImages: make(map[string]struct{}),
logger: logger, logger: logger,
} }
@ -235,6 +236,12 @@ func (a *Client) RunContainer(ctx context.Context, params RunContainerParams) (<
containerStateC <- domain.Container{ID: createResp.ID, Status: domain.ContainerStatusRunning} containerStateC <- domain.Container{ID: createResp.ID, Status: domain.ContainerStatusRunning}
var cancel context.CancelFunc
ctx, cancel = context.WithCancel(ctx)
a.mu.Lock()
a.cancelFuncs[createResp.ID] = cancel
a.mu.Unlock()
a.runContainerLoop( a.runContainerLoop(
ctx, ctx,
createResp.ID, createResp.ID,
@ -385,21 +392,11 @@ func (a *Client) runContainerLoop(
containerErrC <- fmt.Errorf("container start: %w", err) containerErrC <- fmt.Errorf("container start: %w", err)
} }
case err := <-errC: case err := <-errC:
// If this is a not found error, the container has been removed -
// probably by the user. This is a bit hacky, and should be more
// explicit, possibly by signalling to this package that the container
// has been removed by the user instead of just calling
// ContainerRemove.
// TODO: improve this
if errdefs.IsNotFound(err) {
a.logger.Debug("Container not found when setting ContainerWait, ignoring", "id", shortID(containerID))
containerRespC <- containerWaitResponse{WaitResponse: container.WaitResponse{}, restarting: false}
} else {
containerErrC <- err containerErrC <- err
}
return return
case <-ctx.Done(): case <-ctx.Done():
containerErrC <- ctx.Err() // This is probably because the container was stopped.
containerRespC <- containerWaitResponse{WaitResponse: container.WaitResponse{}, restarting: false}
return return
} }
} }
@ -519,6 +516,22 @@ func (a *Client) Close() error {
} }
func (a *Client) removeContainer(ctx context.Context, id string) error { func (a *Client) removeContainer(ctx context.Context, id string) error {
a.mu.Lock()
cancel, ok := a.cancelFuncs[id]
if ok {
delete(a.cancelFuncs, id)
}
a.mu.Unlock()
if ok {
cancel()
} else {
// This shouldn't happen, but we prefer the Docker engine to be the
// definitive source of truth and not the cancelFuncs map so don't sweat it
// if it doesn't exist.
a.logger.Warn("removeContainer: cancelFunc not found", "id", shortID(id))
}
a.logger.Info("Stopping container", "id", shortID(id)) a.logger.Info("Stopping container", "id", shortID(id))
stopTimeout := int(stopTimeout.Seconds()) stopTimeout := int(stopTimeout.Seconds())
if err := a.apiClient.ContainerStop(ctx, id, container.StopOptions{Timeout: &stopTimeout}); err != nil { if err := a.apiClient.ContainerStop(ctx, id, container.StopOptions{Timeout: &stopTimeout}); err != nil {