go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/cv/internal/prjmanager/itriager/itriager.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 itriager defines interface of a CL component triage process. 16 // 17 // It's a separate package to avoid circular imports. 18 package itriager 19 20 import ( 21 "context" 22 23 "go.chromium.org/luci/common/errors" 24 "go.chromium.org/luci/cv/internal/configs/prjcfg" 25 "go.chromium.org/luci/cv/internal/prjmanager/prjpb" 26 "go.chromium.org/luci/cv/internal/run/runcreator" 27 ) 28 29 // Triage triages a component deciding what and when has to be done. 30 // 31 // Triage is called outside of transaction context. 32 // Triage may be retried with the same or different input, possibly 33 // concurrently, on the same component. 34 // 35 // Triage must treat all given data as read-only. If it needs to modify 36 // component, it should use copy-on-write approach. 37 // 38 // Project Manager guarantees that for each CL of the given component: 39 // - there is a PCL via Supporter interface, 40 // - and for each such CL's dependency, either: 41 // - dep is not yet loaded, 42 // - OR dep must be itself a component's CL. 43 // 44 // May return special, possibly wrapped, ErrOutdatedPMState to signal that 45 // Triage function has detected outdated PMState. 46 type Triage func(ctx context.Context, c *prjpb.Component, s PMState) (Result, error) 47 48 // Result is the result of a component traige. 49 // 50 // Consistency notes: 51 // 52 // The RunsToCreate are processed first, independently from each other. 53 // If at least one fails, then NewValue and CLsTopurge are not saved. 54 // This ensures that in case of Run creation failure, the next PM invocation 55 // will call Triage again. 56 // 57 // If RunsToCreate aren't specified OR all of them are created successfully, 58 // then the CLsTopurge and NewValue are saved atomically. 59 type Result struct { 60 // RunsToCreate is set if a Run has to be created. 61 // 62 // If set, must contain fully populated runcreator.Creator objects. 63 RunsToCreate []*runcreator.Creator 64 65 // TODO(tandrii): support cancel Run actions. 66 67 // NewValue specifies the new value of a component if non-nil. 68 // 69 // Must be set if the input component is .TriageRequired. 70 // If not set, implies that component doesn't have to be changed. 71 NewValue *prjpb.Component 72 73 // CLsToPurge must contain PurgeCLTasks tasks with with these (sub)fields set: 74 // * .PurgingCL.Clid 75 // * .PurgeReasons 76 CLsToPurge []*prjpb.PurgeCLTask 77 // CLsToTriggerDeps are CLs to propagate the CQ votes to the deps of. 78 CLsToTriggerDeps []*prjpb.TriggeringCLDeps 79 } 80 81 // PMState provides limited access to resources of Project Manager (PM) state for 82 // ease of testing and correctness. 83 // 84 // All data exposed by the PMState must not be modified and remains immutable 85 // during the lifetime of a Triage() function execution. 86 type PMState interface { 87 // PCL provides access to the CLs tracked by the PM. 88 // 89 // Returns nil if clid refers to a CL not known to the PM. 90 PCL(clid int64) *prjpb.PCL 91 92 // PurgingCL provides access to CLs being purged on behalf of the PM. 93 // 94 // Returns nil if given CL isn't being purged. 95 PurgingCL(clid int64) *prjpb.PurgingCL 96 97 // ConfigGroup returns a ConfigGroup for a given index of the current 98 // (from the view point of PM) LUCI project config version. 99 ConfigGroup(index int32) *prjcfg.ConfigGroup 100 101 // TriggeringCLDeps provides access to CLs being triggered. 102 // 103 // Returns nil if given CL isn't being triggered. 104 TriggeringCLDeps(clid int64) *prjpb.TriggeringCLDeps 105 } 106 107 // ErrOutdatedPMState signals that PMState is out dated. 108 var ErrOutdatedPMState = errors.New("outdated PM state") 109 110 // IsErrOutdatedPMState returns true if given error is a possibly wrapped 111 // ErrOutdatedPMState. 112 func IsErrOutdatedPMState(err error) bool { 113 return errors.Contains(err, ErrOutdatedPMState) 114 }