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 }