blob: 2f8e7f73225d98c5df54689f93036a4da7123d08 [file] [log] [blame]
// Copyright 2024 The LUCI Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package artifactexporter
import (
"time"
"cloud.google.com/go/bigquery"
"cloud.google.com/go/bigquery/storage/managedwriter/adapt"
"github.com/golang/protobuf/descriptor"
desc "github.com/golang/protobuf/protoc-gen-go/descriptor"
"google.golang.org/protobuf/types/descriptorpb"
"go.chromium.org/luci/common/bq"
"go.chromium.org/luci/resultdb/bqutil"
bqpb "go.chromium.org/luci/resultdb/proto/bq"
pb "go.chromium.org/luci/resultdb/proto/v1"
)
// The table containing test artifacts.
const tableName = "text_artifacts"
const partitionExpirationTime = 90 * 24 * time.Hour // 90 days.
const rowMessage = "luci.resultdb.bq.TextArtifactRow"
var tableMetadata *bigquery.TableMetadata
// tableSchemaDescriptor is a self-contained DescriptorProto for describing
// row protocol buffers sent to the BigQuery Write API.
var tableSchemaDescriptor *descriptorpb.DescriptorProto
func init() {
var err error
var schema bigquery.Schema
if schema, err = generateRowSchema(); err != nil {
panic(err)
}
if tableSchemaDescriptor, err = generateRowSchemaDescriptor(); err != nil {
panic(err)
}
tableMetadata = &bigquery.TableMetadata{
TimePartitioning: &bigquery.TimePartitioning{
Type: bigquery.DayPartitioningType,
Expiration: partitionExpirationTime,
Field: "partition_time",
},
// Clustering on these fields will allow good compression rate and query performance.
Clustering: &bigquery.Clustering{
Fields: []string{"project", "test_id", "artifact_shard", "invocation_id"},
},
// Relax ensures no fields are marked "required".
Schema: schema.Relax(),
Labels: map[string]string{bq.MetadataVersionKey: "1"},
}
}
func generateRowSchema() (schema bigquery.Schema, err error) {
fd, _ := descriptor.MessageDescriptorProto(&bqpb.TextArtifactRow{})
fdsp, _ := descriptor.MessageDescriptorProto(&pb.StringPair{})
fdset := &desc.FileDescriptorSet{File: []*desc.FileDescriptorProto{fd, fdsp}}
return bqutil.GenerateSchema(fdset, rowMessage)
}
func generateRowSchemaDescriptor() (*desc.DescriptorProto, error) {
m := &bqpb.TextArtifactRow{}
descriptorProto, err := adapt.NormalizeDescriptor(m.ProtoReflect().Descriptor())
if err != nil {
return nil, err
}
return descriptorProto, nil
}