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  }