go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/cv/internal/run/impl/handler/handler.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  	"time"
    20  
    21  	"go.chromium.org/luci/server/quota/quotapb"
    22  
    23  	cfgpb "go.chromium.org/luci/cv/api/config/v2"
    24  	"go.chromium.org/luci/cv/internal/changelist"
    25  	"go.chromium.org/luci/cv/internal/common"
    26  	"go.chromium.org/luci/cv/internal/common/eventbox"
    27  	"go.chromium.org/luci/cv/internal/common/tree"
    28  	"go.chromium.org/luci/cv/internal/gerrit"
    29  	"go.chromium.org/luci/cv/internal/run"
    30  	"go.chromium.org/luci/cv/internal/run/bq"
    31  	"go.chromium.org/luci/cv/internal/run/eventpb"
    32  	"go.chromium.org/luci/cv/internal/run/impl/state"
    33  	"go.chromium.org/luci/cv/internal/run/pubsub"
    34  	"go.chromium.org/luci/cv/internal/run/rdb"
    35  	"go.chromium.org/luci/cv/internal/tryjob"
    36  )
    37  
    38  // Result is the result of handling the events.
    39  type Result struct {
    40  	// State is the new RunState after handling the events.
    41  	State *state.RunState
    42  	// SideEffectFn is called in a transaction to atomically transition the
    43  	// RunState to the new state and perform side effect.
    44  	SideEffectFn eventbox.SideEffectFn
    45  	// PreserveEvents, if true, instructs RunManager not to consume the events
    46  	// during state transition.
    47  	PreserveEvents bool
    48  	// PostProcessFn is executed by the eventbox user after event processing
    49  	// completes.
    50  	PostProcessFn eventbox.PostProcessFn
    51  }
    52  
    53  // Handler is an interface that handles events that RunManager receives.
    54  type Handler interface {
    55  	// Start starts a Run.
    56  	Start(context.Context, *state.RunState) (*Result, error)
    57  
    58  	// Cancel cancels a Run.
    59  	Cancel(context.Context, *state.RunState, []string) (*Result, error)
    60  
    61  	// OnCLsUpdated decides whether to cancel a Run based on changes to the CLs.
    62  	OnCLsUpdated(context.Context, *state.RunState, common.CLIDs) (*Result, error)
    63  
    64  	// UpdateConfig updates Run's config if possible.
    65  	//
    66  	// If Run is no longer viable, cancels the Run.
    67  	UpdateConfig(context.Context, *state.RunState, string) (*Result, error)
    68  
    69  	// OnReadyForSubmission acquires a slot in Submit Queue and makes sure this
    70  	// Run is not currently being submitted by another RM task. If all succeeded,
    71  	// returns a PostProcessFn for submission.
    72  	OnReadyForSubmission(context.Context, *state.RunState) (*Result, error)
    73  
    74  	// OnCLsSubmitted records provided CLs have been submitted.
    75  	OnCLsSubmitted(context.Context, *state.RunState, common.CLIDs) (*Result, error)
    76  
    77  	// OnSubmissionCompleted acts on the submission result.
    78  	//
    79  	// If submission succeeds, mark run as `SUCCEEDED`. Otherwise, decides whether
    80  	// to retry submission or fail the run depending on the submission result.
    81  	OnSubmissionCompleted(ctx context.Context, rs *state.RunState, sc *eventpb.SubmissionCompleted) (*Result, error)
    82  
    83  	// OnLongOpCompleted processes results of the completed long operation.
    84  	OnLongOpCompleted(ctx context.Context, rs *state.RunState, result *eventpb.LongOpCompleted) (*Result, error)
    85  
    86  	// OnTryjobsUpdated decides the next step for the given tryjobs and the run.
    87  	OnTryjobsUpdated(context.Context, *state.RunState, common.TryjobIDs) (*Result, error)
    88  
    89  	// TryResumeSubmission resumes not-yet-expired submission if the current task
    90  	// is a retry of the submission task.
    91  	//
    92  	// Fail the Run if the submission deadline has been exceeded.
    93  	TryResumeSubmission(context.Context, *state.RunState) (*Result, error)
    94  
    95  	// Poke checks current Run state and takes actions to progress the Run.
    96  	Poke(context.Context, *state.RunState) (*Result, error)
    97  
    98  	// OnParentRunCompleted checks decides how to handle the run based on its completed parent run.
    99  	OnParentRunCompleted(context.Context, *state.RunState) (*Result, error)
   100  }
   101  
   102  // PM encapsulates interaction with Project Manager by the Run events handler.
   103  type PM interface {
   104  	NotifyRunFinished(ctx context.Context, runID common.RunID, status run.Status) error
   105  	NotifyCLsUpdated(ctx context.Context, luciProject string, cls *changelist.CLUpdatedEvents) error
   106  }
   107  
   108  // RM encapsulates interaction with Run Manager by the Run events handler.
   109  type RM interface {
   110  	Invoke(ctx context.Context, runID common.RunID, eta time.Time) error
   111  	PokeAfter(ctx context.Context, runID common.RunID, after time.Duration) error
   112  	NotifyReadyForSubmission(ctx context.Context, runID common.RunID, eta time.Time) error
   113  	NotifyCLsSubmitted(ctx context.Context, runID common.RunID, clids common.CLIDs) error
   114  	NotifySubmissionCompleted(ctx context.Context, runID common.RunID, sc *eventpb.SubmissionCompleted, invokeRM bool) error
   115  	Start(ctx context.Context, runID common.RunID) error
   116  	NotifyParentRunCompleted(ctx context.Context, runID common.RunID) error
   117  }
   118  
   119  // QM manages run and tryjob quotas.
   120  type QM interface {
   121  	DebitRunQuota(ctx context.Context, r *run.Run) (*quotapb.OpResult, *cfgpb.UserLimit, error)
   122  }
   123  
   124  // CLUpdater encapsulates interaction with CL Updater by the Run events handler.
   125  type CLUpdater interface {
   126  	ScheduleBatch(ctx context.Context, luciProject string, cls []*changelist.CL, requester changelist.UpdateCLTask_Requester) error
   127  }
   128  
   129  // TryjobNotifier encapsulates interaction with Tryjob components by the Run
   130  // events handler.
   131  type TryjobNotifier interface {
   132  	ScheduleUpdate(ctx context.Context, id common.TryjobID, eid tryjob.ExternalID) error
   133  }
   134  
   135  // Impl is a prod implementation of Handler interface.
   136  type Impl struct {
   137  	PM          PM
   138  	RM          RM
   139  	TN          TryjobNotifier
   140  	QM          QM
   141  	GFactory    gerrit.Factory
   142  	CLUpdater   CLUpdater
   143  	CLMutator   *changelist.Mutator
   144  	BQExporter  *bq.Exporter
   145  	RdbNotifier *rdb.Notifier
   146  	TreeClient  tree.Client
   147  	Publisher   *pubsub.Publisher
   148  	Env         *common.Env
   149  }
   150  
   151  var _ Handler = (*Impl)(nil)