go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/buildbucket/appengine/internal/buildercron/inactive.go (about)

     1  // Copyright 2022 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 buildercron
    16  
    17  import (
    18  	"context"
    19  
    20  	"go.chromium.org/luci/common/clock"
    21  	"go.chromium.org/luci/common/logging"
    22  	"go.chromium.org/luci/gae/service/datastore"
    23  
    24  	"go.chromium.org/luci/buildbucket/appengine/model"
    25  )
    26  
    27  // RemoveInactiveBuilderStats removes inactive BuilderStats.
    28  //
    29  // BuilderStat is inactive, if either or both of the following conditions are
    30  // true.
    31  // - the Builder hasn't scheduled a build for model.BuilderExpirationDuration
    32  // - the Builder config no longer exists.
    33  func RemoveInactiveBuilderStats(ctx context.Context) error {
    34  	var toDelete []*datastore.Key
    35  	q := datastore.NewQuery(model.BuilderStatKind)
    36  	err := datastore.RunBatch(ctx, 128, q, func(stat *model.BuilderStat) error {
    37  		bk := stat.BuilderKey(ctx)
    38  		if clock.Since(ctx, stat.LastScheduled) > model.BuilderExpirationDuration {
    39  			// Inactive for too long.
    40  			logging.Infof(ctx, "%s: BuilderStat.LastScheduled(%s) is too old; removing BuilderStat",
    41  				stat.ID, stat.LastScheduled)
    42  			toDelete = append(toDelete, datastore.KeyForObj(ctx, stat))
    43  			return nil
    44  		}
    45  
    46  		if clock.Since(ctx, stat.LastScheduled) > model.BuilderStatZombieDuration {
    47  			// Possibly became a zombie too long.
    48  			switch r, err := datastore.Exists(ctx, bk); {
    49  			case err != nil:
    50  				return err
    51  			case !r.Any():
    52  				// The Builder config no longer exists?
    53  				logging.Infof(ctx, "%s: the Builder no longer exists; removing BuilderStat", stat.ID)
    54  				toDelete = append(toDelete, datastore.KeyForObj(ctx, stat))
    55  			}
    56  		}
    57  		return nil
    58  	})
    59  	if err != nil {
    60  		return err
    61  	}
    62  	return datastore.Delete(ctx, toDelete)
    63  }