go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/cv/internal/rpc/admin/upgrade_cls.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 admin
    16  
    17  import (
    18  	"context"
    19  
    20  	"go.chromium.org/luci/common/errors"
    21  	"go.chromium.org/luci/common/retry/transient"
    22  	"go.chromium.org/luci/gae/service/datastore"
    23  	"go.chromium.org/luci/server/dsmapper"
    24  
    25  	"go.chromium.org/luci/cv/internal/changelist"
    26  	"go.chromium.org/luci/cv/internal/common"
    27  	"go.chromium.org/luci/cv/internal/run"
    28  )
    29  
    30  var removeCLDescriptionsCOnfig = dsmapper.JobConfig{
    31  	Mapper: "runcl-description",
    32  	Query: dsmapper.Query{
    33  		Kind: "RunCL",
    34  	},
    35  	PageSize:   32,
    36  	ShardCount: 4,
    37  }
    38  
    39  var removeCLDescriptionsFactory = func(_ context.Context, j *dsmapper.Job, _ int) (dsmapper.Mapper, error) {
    40  	tsJobName := string(j.Config.Mapper)
    41  	tsJobID := int64(j.ID)
    42  
    43  	upgradeCLs := func(ctx context.Context, keys []*datastore.Key) error {
    44  		needUpgrade := func(cls []*run.RunCL) []*run.RunCL {
    45  			toUpdate := cls[:0]
    46  			for _, cl := range cls {
    47  				ci := cl.Detail.GetGerrit().GetInfo()
    48  				if ci == nil {
    49  					continue
    50  				}
    51  				revInfo := ci.GetRevisions()[ci.GetCurrentRevision()]
    52  				if revInfo == nil {
    53  					continue
    54  				}
    55  				if revInfo.GetCommit().GetMessage() == "" {
    56  					continue
    57  				}
    58  				toUpdate = append(toUpdate, cl)
    59  			}
    60  			return toUpdate
    61  		}
    62  
    63  		cls := make([]*run.RunCL, len(keys))
    64  		for i, k := range keys {
    65  			cls[i] = &run.RunCL{
    66  				ID:  common.CLID(k.IntID()),
    67  				Run: k.Parent(),
    68  			}
    69  		}
    70  
    71  		// Check before a transaction if an update is even necessary.
    72  		if err := datastore.Get(ctx, cls); err != nil {
    73  			return errors.Annotate(err, "failed to fetch RunCLs").Tag(transient.Tag).Err()
    74  		}
    75  		cls = needUpgrade(cls)
    76  		if len(cls) == 0 {
    77  			return nil
    78  		}
    79  
    80  		err := datastore.RunInTransaction(ctx, func(ctx context.Context) error {
    81  			// Reload inside transaction to avoid races with other CV parts.
    82  			if err := datastore.Get(ctx, cls); err != nil {
    83  				return errors.Annotate(err, "failed to fetch RunCLs").Tag(transient.Tag).Err()
    84  			}
    85  			cls = needUpgrade(cls)
    86  			if len(cls) == 0 {
    87  				return nil
    88  			}
    89  			for _, cl := range cls {
    90  				changelist.RemoveUnusedGerritInfo(cl.Detail.GetGerrit().GetInfo())
    91  			}
    92  			return datastore.Put(ctx, cls)
    93  		}, nil)
    94  		if err != nil {
    95  			return errors.Annotate(err, "failed to update RunCLs").Tag(transient.Tag).Err()
    96  		}
    97  		metricUpgraded.Add(ctx, int64(len(cls)), tsJobName, tsJobID, "RunCL")
    98  		return nil
    99  	}
   100  
   101  	return upgradeCLs, nil
   102  }