go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/resultdb/internal/baselines/testvariants/baseline_testvariants.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 baselinetestvariant provides crud operations for baseline test variants.
    16  package baselinetestvariant
    17  
    18  import (
    19  	"context"
    20  	"time"
    21  
    22  	"cloud.google.com/go/spanner"
    23  
    24  	"google.golang.org/grpc/codes"
    25  
    26  	"go.chromium.org/luci/common/errors"
    27  	"go.chromium.org/luci/resultdb/internal/spanutil"
    28  )
    29  
    30  // BaselineTestVariant captures a test variant mapped to a baseline identifier.
    31  // BaselineTestVariants are used to when determining new tests.
    32  type BaselineTestVariant struct {
    33  	Project     string
    34  	BaselineID  string
    35  	TestID      string
    36  	VariantHash string
    37  	LastUpdated time.Time
    38  }
    39  
    40  var NotFound = errors.New("baseline test variant not found")
    41  
    42  // Read reads one baseline test variant from Spanner.
    43  // If the invocation does not exist, NotFound error is returned.
    44  func Read(ctx context.Context, project, baselineID, testID, variantHash string) (*BaselineTestVariant, error) {
    45  	key := spanner.Key{
    46  		project,
    47  		baselineID,
    48  		testID,
    49  		variantHash,
    50  	}
    51  
    52  	var proj, bID, tID, vHash string
    53  	var lastUpdated time.Time
    54  
    55  	err := spanutil.ReadRow(ctx, "BaselineTestVariants", key, map[string]any{
    56  		"Project":     &proj,
    57  		"BaselineId":  &bID,
    58  		"TestId":      &tID,
    59  		"VariantHash": &vHash,
    60  		"LastUpdated": &lastUpdated,
    61  	})
    62  	if err != nil {
    63  		if spanner.ErrCode(err) == codes.NotFound {
    64  			err = NotFound
    65  		}
    66  		return &BaselineTestVariant{}, err
    67  	}
    68  
    69  	res := &BaselineTestVariant{
    70  		Project:     proj,
    71  		BaselineID:  bID,
    72  		TestID:      tID,
    73  		VariantHash: vHash,
    74  		LastUpdated: lastUpdated,
    75  	}
    76  	return res, nil
    77  }
    78  
    79  // Create returns a Spanner mutation that creates the Baseline Test Variant, setting LastUpdated to spanner.CommitTimestamp
    80  func Create(project, baselineID, testID, variantHash string) *spanner.Mutation {
    81  	row := map[string]any{
    82  		"Project":     project,
    83  		"BaselineId":  baselineID,
    84  		"TestId":      testID,
    85  		"VariantHash": variantHash,
    86  		"LastUpdated": spanner.CommitTimestamp,
    87  	}
    88  	return spanutil.InsertMap("BaselineTestVariants", row)
    89  }
    90  
    91  var baselineTestVariantCols = []string{
    92  	"Project", "BaselineId", "TestId", "VariantHash", "LastUpdated",
    93  }
    94  
    95  // InsertOrUpdate returns a Spanner mutation for inserting/updating a baseline test variant
    96  func InsertOrUpdate(project, baselineID, testID, variantHash string) *spanner.Mutation {
    97  	// Specifying values in a slice directly instead of creating maps to save
    98  	// wasted CPU cycles of generating maps and converting back to slice for
    99  	// large data sets such as test results. See
   100  	// go/src/go.chromium.org/luci/analysis/internal/testresults/span.go
   101  	vals := []any{
   102  		project, baselineID, testID, variantHash, spanner.CommitTimestamp,
   103  	}
   104  	return spanner.InsertOrUpdate("BaselineTestVariants", baselineTestVariantCols, vals)
   105  }