go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/cv/internal/prjmanager/prjpb/triggerdeps.go (about)

     1  // Copyright 2023 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 prjpb
    16  
    17  import (
    18  	"sort"
    19  	"time"
    20  
    21  	"go.chromium.org/luci/cv/internal/prjmanager/copyonwrite"
    22  )
    23  
    24  // MaxTriggeringCLDepsDuration limits the time that a TQ task has to execute
    25  // a given TrigggeringCLDesp task.
    26  //
    27  // Once the deadline is exceeded, PM will will remove the task from PStat
    28  // to retriage the CL and see if it has to reschedule another TriggeringCLDeps
    29  // for the CL with its deps.
    30  const MaxTriggeringCLDepsDuration = 8 * time.Minute
    31  
    32  // COWTriggeringCLDeps copy-on-write modifies TriggeringCLDeps.
    33  func (p *PState) COWTriggeringCLDeps(m func(*TriggeringCLDeps) *TriggeringCLDeps, toAdd []*TriggeringCLDeps) ([]*TriggeringCLDeps, bool) {
    34  	in := cowTriggeringCLDeps(p.GetTriggeringClDeps())
    35  	out, updated := copyonwrite.Update(in, triggerCLDepsModifier(m), cowTriggeringCLDeps(toAdd))
    36  	return []*TriggeringCLDeps(out.(cowTriggeringCLDeps)), updated
    37  }
    38  
    39  // GetTriggeringCLDeps returns the TriggeringCLDeps of a given origin clid.
    40  //
    41  // Returns nil, if not found.
    42  func (p *PState) GetTriggeringCLDeps(clid int64) *TriggeringCLDeps {
    43  	items := p.GetTriggeringClDeps()
    44  	idx := sort.Search(len(items), func(i int) bool {
    45  		return items[i].GetOriginClid() >= clid
    46  	})
    47  	if idx >= len(items) || items[idx].GetOriginClid() != clid {
    48  		return nil
    49  	}
    50  	return items[idx]
    51  }
    52  
    53  func triggerCLDepsModifier(f func(*TriggeringCLDeps) *TriggeringCLDeps) copyonwrite.Modifier {
    54  	if f == nil {
    55  		return nil
    56  	}
    57  	return func(v any) any {
    58  		if v := f(v.(*TriggeringCLDeps)); v != nil {
    59  			return v
    60  		}
    61  		return copyonwrite.Deletion
    62  	}
    63  }
    64  
    65  type cowTriggeringCLDeps []*TriggeringCLDeps
    66  
    67  // It's important that TriggeringCLDeps are always sorted.
    68  var _ copyonwrite.SortedSlice = cowTriggeringCLDeps(nil)
    69  
    70  func (c cowTriggeringCLDeps) At(index int) any {
    71  	return c[index]
    72  }
    73  
    74  func (c cowTriggeringCLDeps) Append(v any) copyonwrite.Slice {
    75  	return append(c, v.(*TriggeringCLDeps))
    76  }
    77  
    78  func (c cowTriggeringCLDeps) CloneShallow(length int, capacity int) copyonwrite.Slice {
    79  	r := make(cowTriggeringCLDeps, length, capacity)
    80  	copy(r, c[:length])
    81  	return r
    82  }
    83  
    84  func (c cowTriggeringCLDeps) LessElements(a any, b any) bool {
    85  	return a.(*TriggeringCLDeps).GetOriginClid() < b.(*TriggeringCLDeps).GetOriginClid()
    86  }
    87  
    88  func (c cowTriggeringCLDeps) Len() int {
    89  	return len(c)
    90  }
    91  
    92  func (c cowTriggeringCLDeps) Less(i int, j int) bool {
    93  	return c[i].GetOriginClid() < c[j].GetOriginClid()
    94  }
    95  func (c cowTriggeringCLDeps) Swap(i int, j int) {
    96  	c[i], c[j] = c[j], c[i]
    97  }