go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/cv/internal/run/impl/handler/cancel.go (about)

     1  // Copyright 2020 The LUCI Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package handler
    16  
    17  import (
    18  	"context"
    19  
    20  	"go.chromium.org/luci/common/data/stringset"
    21  	"go.chromium.org/luci/common/errors"
    22  	"go.chromium.org/luci/common/logging"
    23  
    24  	"go.chromium.org/luci/cv/internal/common"
    25  	"go.chromium.org/luci/cv/internal/configs/prjcfg"
    26  	"go.chromium.org/luci/cv/internal/run"
    27  	"go.chromium.org/luci/cv/internal/run/impl/state"
    28  )
    29  
    30  // Cancel implements Handler interface.
    31  func (impl *Impl) Cancel(ctx context.Context, rs *state.RunState, reasons []string) (*Result, error) {
    32  	switch status := rs.Status; {
    33  	case status == run.Status_STATUS_UNSPECIFIED:
    34  		err := errors.Reason("CRITICAL: can't cancel a Run with unspecified status").Err()
    35  		common.LogError(ctx, err)
    36  		panic(err)
    37  	case status == run.Status_SUBMITTING:
    38  		// Can't cancel while submitting.
    39  		return &Result{State: rs, PreserveEvents: true}, nil
    40  	case run.IsEnded(status):
    41  		logging.Debugf(ctx, "skipping cancellation because Run is %s", status)
    42  		return &Result{State: rs}, nil
    43  	}
    44  	cg, err := prjcfg.GetConfigGroup(ctx, rs.ID.LUCIProject(), rs.ConfigGroupID)
    45  	if err != nil {
    46  		return nil, errors.Annotate(err, "prjcfg.GetConfigGroup").Err()
    47  	}
    48  	rs = rs.ShallowCopy()
    49  	// make sure reasons are unique and doesn't contain empty reasons.
    50  	uniqueReasons := stringset.NewFromSlice(reasons...)
    51  	uniqueReasons.Del("")
    52  	rs.CancellationReasons = uniqueReasons.ToSortedSlice()
    53  	childRuns, err := run.LoadChildRuns(ctx, rs.ID)
    54  	if err != nil {
    55  		return nil, errors.Annotate(err, "failed to load child runs").Err()
    56  	}
    57  	se := impl.endRun(ctx, rs, run.Status_CANCELLED, cg, childRuns)
    58  
    59  	return &Result{
    60  		State:        rs,
    61  		SideEffectFn: se,
    62  	}, nil
    63  }