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

     1  // Copyright 2021 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  	"fmt"
    20  	"time"
    21  
    22  	"go.chromium.org/luci/common/errors"
    23  	"go.chromium.org/luci/common/logging"
    24  	"go.chromium.org/luci/cv/internal/changelist"
    25  	"go.chromium.org/luci/cv/internal/configs/prjcfg"
    26  	"go.chromium.org/luci/cv/internal/metrics"
    27  	"go.chromium.org/luci/cv/internal/run"
    28  	"go.chromium.org/luci/cv/internal/run/eventpb"
    29  	"go.chromium.org/luci/cv/internal/run/impl/state"
    30  )
    31  
    32  const (
    33  	// maxResetTriggersDuration is the maximum duration allowed for a Run
    34  	// to reset the triggers of all CLs.
    35  	maxResetTriggersDuration = 5 * time.Minute
    36  
    37  	logEntryLabelResetTriggers = "Reset Triggers"
    38  )
    39  
    40  func (impl *Impl) onCompletedResetTriggers(ctx context.Context, rs *state.RunState, op *run.OngoingLongOps_Op, opCompleted *eventpb.LongOpCompleted) (*Result, error) {
    41  	opID := opCompleted.GetOperationId()
    42  	rs = rs.ShallowCopy()
    43  	rs.RemoveCompletedLongOp(opID)
    44  	if status := rs.Status; run.IsEnded(status) {
    45  		logging.Warningf(ctx, "long operation to reset triggers has completed but Run is %s. Result: %s", rs.Status, opCompleted)
    46  		return &Result{State: rs}, nil
    47  	}
    48  	runStatus := op.GetResetTriggers().GetRunStatusIfSucceeded()
    49  	switch opCompleted.GetStatus() {
    50  	case eventpb.LongOpCompleted_EXPIRED:
    51  		runStatus = run.Status_FAILED
    52  		rs.LogInfof(ctx, logEntryLabelResetTriggers, "failed to reset the triggers of CLs within the %s deadline", maxResetTriggersDuration)
    53  	case eventpb.LongOpCompleted_FAILED:
    54  		runStatus = run.Status_FAILED
    55  		fallthrough
    56  	case eventpb.LongOpCompleted_SUCCEEDED:
    57  		for _, result := range opCompleted.GetResetTriggers().GetResults() {
    58  			changeURL := changelist.ExternalID(result.GetExternalId()).MustURL()
    59  			switch result.GetDetail().(type) {
    60  			case *eventpb.LongOpCompleted_ResetTriggers_Result_SuccessInfo:
    61  				rs.LogInfofAt(result.GetSuccessInfo().GetResetAt().AsTime(), logEntryLabelResetTriggers, "successfully reset the trigger of change %s", changeURL)
    62  				if tjEndTime := rs.Tryjobs.GetState().GetEndTime(); tjEndTime != nil {
    63  					delay := result.GetSuccessInfo().GetResetAt().AsTime().Sub(tjEndTime.AsTime())
    64  					metrics.Internal.RunTryjobResultReportDelay.Add(ctx, float64(delay.Milliseconds()),
    65  						rs.ID.LUCIProject(), rs.ConfigGroupID.Name(), string(rs.Mode))
    66  				}
    67  			case *eventpb.LongOpCompleted_ResetTriggers_Result_FailureInfo:
    68  				rs.LogInfof(ctx, logEntryLabelResetTriggers, "failed to reset the trigger of change %s. Reason: %s", changeURL, result.GetFailureInfo().GetFailureMessage())
    69  			default:
    70  				panic(fmt.Errorf("unexpected long op result status: %s", opCompleted.GetStatus()))
    71  			}
    72  		}
    73  	default:
    74  		panic(fmt.Errorf("unexpected LongOpCompleted status: %s", opCompleted.GetStatus()))
    75  	}
    76  	cg, err := prjcfg.GetConfigGroup(ctx, rs.ID.LUCIProject(), rs.ConfigGroupID)
    77  	if err != nil {
    78  		return nil, errors.Annotate(err, "prjcfg.GetConfigGroup").Err()
    79  	}
    80  	childRuns, err := run.LoadChildRuns(ctx, rs.ID)
    81  	if err != nil {
    82  		return nil, errors.Annotate(err, "failed to load child runs").Err()
    83  	}
    84  	return &Result{
    85  		State:        rs,
    86  		SideEffectFn: impl.endRun(ctx, rs, runStatus, cg, childRuns),
    87  	}, nil
    88  }