Skip to content

Commit

Permalink
catalog/multiregion: move SynthesizeMultiregionConfig function
Browse files Browse the repository at this point in the history
This commit moves function and type definitions to a smaller package so
the declarative schema changer can use it.

Release note: None
  • Loading branch information
rafiss committed Dec 30, 2024
1 parent 2a4a1ac commit 831164f
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 98 deletions.
2 changes: 1 addition & 1 deletion pkg/backup/restore_job.go
Original file line number Diff line number Diff line change
Expand Up @@ -1428,7 +1428,7 @@ func createImportingDescriptors(
txn.KV(),
desc.GetID(),
descsCol,
sql.SynthesizeRegionConfigOptionIncludeOffline,
multiregion.SynthesizeRegionConfigOptionIncludeOffline,
)
if err != nil {
return err
Expand Down
1 change: 1 addition & 0 deletions pkg/sql/catalog/multiregion/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ go_library(
visibility = ["//visibility:public"],
deps = [
"//pkg/config/zonepb",
"//pkg/keys",
"//pkg/sql/catalog",
"//pkg/sql/catalog/catpb",
"//pkg/sql/catalog/descpb",
Expand Down
91 changes: 91 additions & 0 deletions pkg/sql/catalog/multiregion/region_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
package multiregion

import (
"github.com/cockroachdb/cockroach/pkg/keys"
"github.com/cockroachdb/cockroach/pkg/sql/catalog"
"github.com/cockroachdb/cockroach/pkg/sql/catalog/catpb"
"github.com/cockroachdb/cockroach/pkg/sql/catalog/descpb"
"github.com/cockroachdb/cockroach/pkg/sql/sem/builtins/builtinconstants"
"github.com/cockroachdb/cockroach/pkg/sql/sem/eval"
"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
Expand Down Expand Up @@ -77,3 +81,90 @@ func MaybeRegionalByRowOnUpdateExpr(evalCtx *eval.Context, enumOid oid.Oid) tree
}
return nil
}

func SynthesizeRegionConfig(
regionEnumDesc catalog.RegionEnumTypeDescriptor,
dbDesc catalog.DatabaseDescriptor,
o SynthesizeRegionConfigOptions,
) (RegionConfig, error) {
var regionNames, transitioningRegionNames, addingRegionNames catpb.RegionNames
_ = regionEnumDesc.ForEachRegion(func(name catpb.RegionName, transition descpb.TypeDescriptor_EnumMember_Direction) error {
switch transition {
case descpb.TypeDescriptor_EnumMember_NONE:
regionNames = append(regionNames, name)
case descpb.TypeDescriptor_EnumMember_ADD:
transitioningRegionNames = append(transitioningRegionNames, name)
addingRegionNames = append(addingRegionNames, name)
case descpb.TypeDescriptor_EnumMember_REMOVE:
transitioningRegionNames = append(transitioningRegionNames, name)
if o.ForValidation {
// Since the partitions and zone configs are only updated when a transaction
// commits, this must ignore all regions being added (since they will not be
// reflected in the zone configuration yet), but it must include all region
// being dropped (since they will not be dropped from the zone configuration
// until they are fully removed from the type descriptor, again, at the end
// of the transaction).
regionNames = append(regionNames, name)
}
}
return nil
})
survivalGoal := dbDesc.GetRegionConfig().SurvivalGoal
if o.ForceSurvivalGoal != nil {
survivalGoal = *o.ForceSurvivalGoal
}
regionConfig := MakeRegionConfig(
regionNames,
dbDesc.GetRegionConfig().PrimaryRegion,
survivalGoal,
regionEnumDesc.GetID(),
dbDesc.GetRegionConfig().Placement,
regionEnumDesc.TypeDesc().RegionConfig.SuperRegions,
regionEnumDesc.TypeDesc().RegionConfig.ZoneConfigExtensions,
WithTransitioningRegions(transitioningRegionNames),
WithAddingRegions(addingRegionNames),
WithSecondaryRegion(dbDesc.GetRegionConfig().SecondaryRegion),
)

if err := ValidateRegionConfig(regionConfig, dbDesc.GetID() == keys.SystemDatabaseID); err != nil {
return RegionConfig{}, err
}

return regionConfig, nil
}

type SynthesizeRegionConfigOptions struct {
IncludeOffline bool
ForValidation bool
UseCache bool
ForceSurvivalGoal *descpb.SurvivalGoal
}

// SynthesizeRegionConfigOption is an option to pass into SynthesizeRegionConfig.
type SynthesizeRegionConfigOption func(o *SynthesizeRegionConfigOptions)

// SynthesizeRegionConfigOptionIncludeOffline includes offline descriptors for use
// in RESTORE.
var SynthesizeRegionConfigOptionIncludeOffline SynthesizeRegionConfigOption = func(o *SynthesizeRegionConfigOptions) {
o.IncludeOffline = true
}

// SynthesizeRegionConfigOptionForValidation includes descriptors which are being dropped
// as part of the regions field, allowing validation to account for regions in the
// process of being dropped.
var SynthesizeRegionConfigOptionForValidation SynthesizeRegionConfigOption = func(o *SynthesizeRegionConfigOptions) {
o.ForValidation = true
}

// SynthesizeRegionConfigOptionUseCache uses a cache for synthesizing the region
// config.
var SynthesizeRegionConfigOptionUseCache SynthesizeRegionConfigOption = func(o *SynthesizeRegionConfigOptions) {
o.UseCache = true
}

// SynthesizeRegionConfigOptionForceSurvivalZone forces the zone survival goal
// instead of inheriting from the system database.
var SynthesizeRegionConfigOptionForceSurvivalZone SynthesizeRegionConfigOption = func(o *SynthesizeRegionConfigOptions) {
z := descpb.SurvivalGoal_ZONE_FAILURE
o.ForceSurvivalGoal = &z
}
6 changes: 4 additions & 2 deletions pkg/sql/database_region_change_finalizer.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,11 +213,13 @@ func (r *databaseRegionChangeFinalizer) updateDatabaseZoneConfig(
func (r *databaseRegionChangeFinalizer) repartitionRegionalByRowTables(
ctx context.Context, txn descs.Txn,
) (repartitioned []*tabledesc.Mutable, zoneConfigUpdates []*zoneConfigUpdate, _ error) {
var regionConfigOpts []SynthesizeRegionConfigOption
var regionConfigOpts []multiregion.SynthesizeRegionConfigOption
// For regional by row tables these will be forced as survive zone on
// the system database, even if the system database is survive region
if r.dbID == keys.SystemDatabaseID {
regionConfigOpts = []SynthesizeRegionConfigOption{SynthesizeRegionConfigOptionForceSurvivalZone}
regionConfigOpts = []multiregion.SynthesizeRegionConfigOption{
multiregion.SynthesizeRegionConfigOptionForceSurvivalZone,
}
}

regionConfig, err := SynthesizeRegionConfig(ctx, txn.KV(), r.dbID, r.localPlanner.Descriptors(), regionConfigOpts...)
Expand Down
110 changes: 15 additions & 95 deletions pkg/sql/region_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -1052,7 +1052,7 @@ func (p *planner) refreshZoneConfigsForTables(
// as survive zone.
var surviveZoneCfg *multiregion.RegionConfig
if desc.GetID() == keys.SystemDatabaseID {
tempCfg, err := SynthesizeRegionConfig(ctx, p.txn, desc.GetID(), p.Descriptors(), SynthesizeRegionConfigOptionForceSurvivalZone)
tempCfg, err := SynthesizeRegionConfig(ctx, p.txn, desc.GetID(), p.Descriptors(), multiregion.SynthesizeRegionConfigOptionForceSurvivalZone)
if err != nil {
return err
}
Expand Down Expand Up @@ -1231,7 +1231,7 @@ func (p *planner) ValidateAllMultiRegionZoneConfigsInCurrentDatabase(ctx context
p.txn,
dbDesc.GetID(),
p.Descriptors(),
SynthesizeRegionConfigOptionForValidation,
multiregion.SynthesizeRegionConfigOptionForValidation,
)
if err != nil {
return err
Expand Down Expand Up @@ -1267,11 +1267,13 @@ func (p *planner) ResetMultiRegionZoneConfigsForTable(
if desc.LocalityConfig == nil {
return nil
}
var opts []SynthesizeRegionConfigOption
var opts []multiregion.SynthesizeRegionConfigOption
// System databases will have regional by row tables configured
// as survive zone.
if forceZoneSurvival {
opts = []SynthesizeRegionConfigOption{SynthesizeRegionConfigOptionForceSurvivalZone}
opts = []multiregion.SynthesizeRegionConfigOption{
multiregion.SynthesizeRegionConfigOptionForceSurvivalZone,
}
}
regionConfig, err := SynthesizeRegionConfig(ctx, p.txn, desc.GetParentID(), p.Descriptors(), opts...)
if err != nil {
Expand Down Expand Up @@ -1401,46 +1403,10 @@ func (p *planner) CurrentDatabaseRegionConfig(
p.txn,
dbDesc.GetID(),
p.Descriptors(),
SynthesizeRegionConfigOptionUseCache,
multiregion.SynthesizeRegionConfigOptionUseCache,
)
}

type synthesizeRegionConfigOptions struct {
includeOffline bool
forValidation bool
useCache bool
forceSurvivalGoal *descpb.SurvivalGoal
}

// SynthesizeRegionConfigOption is an option to pass into SynthesizeRegionConfig.
type SynthesizeRegionConfigOption func(o *synthesizeRegionConfigOptions)

// SynthesizeRegionConfigOptionIncludeOffline includes offline descriptors for use
// in RESTORE.
var SynthesizeRegionConfigOptionIncludeOffline SynthesizeRegionConfigOption = func(o *synthesizeRegionConfigOptions) {
o.includeOffline = true
}

// SynthesizeRegionConfigOptionForValidation includes descriptors which are being dropped
// as part of the regions field, allowing validation to account for regions in the
// process of being dropped.
var SynthesizeRegionConfigOptionForValidation SynthesizeRegionConfigOption = func(o *synthesizeRegionConfigOptions) {
o.forValidation = true
}

// SynthesizeRegionConfigOptionUseCache uses a cache for synthesizing the region
// config.
var SynthesizeRegionConfigOptionUseCache SynthesizeRegionConfigOption = func(o *synthesizeRegionConfigOptions) {
o.useCache = true
}

// SynthesizeRegionConfigOptionForceSurvivalZone forces the zone survival goal
// instead of inheriting from the system database.
var SynthesizeRegionConfigOptionForceSurvivalZone SynthesizeRegionConfigOption = func(o *synthesizeRegionConfigOptions) {
z := descpb.SurvivalGoal_ZONE_FAILURE
o.forceSurvivalGoal = &z
}

// ErrNotMultiRegionDatabase is returned from SynthesizeRegionConfig when the
// requested database is not a multi-region database.
var ErrNotMultiRegionDatabase = errors.New(
Expand All @@ -1451,72 +1417,26 @@ var ErrNotMultiRegionDatabase = errors.New(
// configured state of a multi-region database by coalescing state from both
// the database descriptor and multi-region type descriptor. By default, it
// avoids the cache and is intended for use by DDL statements.
//
// TODO(ajwerner): Refactor this to take the database descriptor rather than
// the database ID.
func SynthesizeRegionConfig(
ctx context.Context,
txn *kv.Txn,
dbID descpb.ID,
descsCol *descs.Collection,
opts ...SynthesizeRegionConfigOption,
opts ...multiregion.SynthesizeRegionConfigOption,
) (multiregion.RegionConfig, error) {
var o synthesizeRegionConfigOptions
var o multiregion.SynthesizeRegionConfigOptions
for _, opt := range opts {
opt(&o)
}

dbDesc, regionEnumDesc, err := getDBAndRegionEnumDescs(
ctx, txn, dbID, descsCol, o.useCache, o.includeOffline,
ctx, txn, dbID, descsCol, o.UseCache, o.IncludeOffline,
)
if err != nil {
return multiregion.RegionConfig{}, err
}

var regionNames, transitioningRegionNames, addingRegionNames catpb.RegionNames
_ = regionEnumDesc.ForEachRegion(func(name catpb.RegionName, transition descpb.TypeDescriptor_EnumMember_Direction) error {
switch transition {
case descpb.TypeDescriptor_EnumMember_NONE:
regionNames = append(regionNames, name)
case descpb.TypeDescriptor_EnumMember_ADD:
transitioningRegionNames = append(transitioningRegionNames, name)
addingRegionNames = append(addingRegionNames, name)
case descpb.TypeDescriptor_EnumMember_REMOVE:
transitioningRegionNames = append(transitioningRegionNames, name)
if o.forValidation {
// Since the partitions and zone configs are only updated when a transaction
// commits, this must ignore all regions being added (since they will not be
// reflected in the zone configuration yet), but it must include all region
// being dropped (since they will not be dropped from the zone configuration
// until they are fully removed from the type descriptor, again, at the end
// of the transaction).
regionNames = append(regionNames, name)
}
}
return nil
})
survivalGoal := dbDesc.GetRegionConfig().SurvivalGoal
if o.forceSurvivalGoal != nil {
survivalGoal = *o.forceSurvivalGoal
}
regionConfig := multiregion.MakeRegionConfig(
regionNames,
dbDesc.GetRegionConfig().PrimaryRegion,
survivalGoal,
regionEnumDesc.GetID(),
dbDesc.GetRegionConfig().Placement,
regionEnumDesc.TypeDesc().RegionConfig.SuperRegions,
regionEnumDesc.TypeDesc().RegionConfig.ZoneConfigExtensions,
multiregion.WithTransitioningRegions(transitioningRegionNames),
multiregion.WithAddingRegions(addingRegionNames),
multiregion.WithSecondaryRegion(dbDesc.GetRegionConfig().SecondaryRegion),
)

if err := multiregion.ValidateRegionConfig(regionConfig, dbDesc.GetID() == keys.SystemDatabaseID); err != nil {
return multiregion.RegionConfig{}, err
}

return regionConfig, nil
return multiregion.SynthesizeRegionConfig(regionEnumDesc, dbDesc, o)
}

// GetLocalityRegionEnumPhysicalRepresentation returns the physical
Expand Down Expand Up @@ -2039,7 +1959,7 @@ func (p *planner) validateZoneConfigForMultiRegionDatabaseWasNotModifiedByUser(
p.txn,
dbDesc.GetID(),
p.Descriptors(),
SynthesizeRegionConfigOptionForValidation,
multiregion.SynthesizeRegionConfigOptionForValidation,
)
if err != nil {
return err
Expand Down Expand Up @@ -2122,7 +2042,7 @@ func (p *planner) validateZoneConfigForMultiRegionTableWasNotModifiedByUser(
p.txn,
dbDesc.GetID(),
p.Descriptors(),
SynthesizeRegionConfigOptionForValidation,
multiregion.SynthesizeRegionConfigOptionForValidation,
)
if err != nil {
return err
Expand Down Expand Up @@ -2450,7 +2370,7 @@ func (p *planner) GetMultiregionConfig(
p.txn,
databaseID,
p.Descriptors(),
SynthesizeRegionConfigOptionUseCache,
multiregion.SynthesizeRegionConfigOptionUseCache,
)

if err != nil {
Expand Down Expand Up @@ -2621,7 +2541,7 @@ func (p *planner) optimizeSystemDatabase(ctx context.Context) error {
// System databases will have regional by row tables configured
// as survive zone.
regionConfig, err := SynthesizeRegionConfig(
ctx, p.txn, table.GetParentID(), p.Descriptors(), SynthesizeRegionConfigOptionForceSurvivalZone,
ctx, p.txn, table.GetParentID(), p.Descriptors(), multiregion.SynthesizeRegionConfigOptionForceSurvivalZone,
)
if err != nil {
return err
Expand Down

0 comments on commit 831164f

Please sign in to comment.