vitess.io/vitess@v0.16.2/go/vt/schemamanager/schemamanager.go (about)

     1  /*
     2  Copyright 2019 The Vitess Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package schemamanager
    18  
    19  import (
    20  	"encoding/json"
    21  	"fmt"
    22  	"time"
    23  
    24  	"context"
    25  
    26  	"vitess.io/vitess/go/vt/log"
    27  	querypb "vitess.io/vitess/go/vt/proto/query"
    28  )
    29  
    30  const (
    31  	// SchemaChangeDirName is the key name in the ControllerFactory params.
    32  	// It specifies the schema change directory.
    33  	SchemaChangeDirName = "schema_change_dir"
    34  	// SchemaChangeUser is the key name in the ControllerFactory params.
    35  	// It specifies the user who submits this schema change.
    36  	SchemaChangeUser = "schema_change_user"
    37  )
    38  
    39  // ControllerFactory takes a set params and construct a Controller instance.
    40  type ControllerFactory func(params map[string]string) (Controller, error)
    41  
    42  var (
    43  	controllerFactories = make(map[string]ControllerFactory)
    44  )
    45  
    46  // Controller is responsible for getting schema change for a
    47  // certain keyspace and also handling various events happened during schema
    48  // change.
    49  type Controller interface {
    50  	Open(ctx context.Context) error
    51  	Read(ctx context.Context) (sqls []string, err error)
    52  	Close()
    53  	Keyspace() string
    54  	OnReadSuccess(ctx context.Context) error
    55  	OnReadFail(ctx context.Context, err error) error
    56  	OnValidationSuccess(ctx context.Context) error
    57  	OnValidationFail(ctx context.Context, err error) error
    58  	OnExecutorComplete(ctx context.Context, result *ExecuteResult) error
    59  }
    60  
    61  // Executor applies schema changes to underlying system
    62  type Executor interface {
    63  	Open(ctx context.Context, keyspace string) error
    64  	Validate(ctx context.Context, sqls []string) error
    65  	Execute(ctx context.Context, sqls []string) *ExecuteResult
    66  	Close()
    67  }
    68  
    69  // ExecuteResult contains information about schema management state
    70  type ExecuteResult struct {
    71  	FailedShards   []ShardWithError
    72  	SuccessShards  []ShardResult
    73  	CurSQLIndex    int
    74  	Sqls           []string
    75  	UUIDs          []string
    76  	ExecutorErr    string
    77  	TotalTimeSpent time.Duration
    78  }
    79  
    80  // ShardWithError contains information why a shard failed to execute given sql
    81  type ShardWithError struct {
    82  	Shard string
    83  	Err   string
    84  }
    85  
    86  // ShardResult contains sql execute information on a particular shard
    87  type ShardResult struct {
    88  	Shard  string
    89  	Result *querypb.QueryResult
    90  	// Position is a replication position that is guaranteed to be after the
    91  	// schema change was applied. It can be used to wait for replicas to receive
    92  	// the schema change via replication.
    93  	Position string
    94  }
    95  
    96  // Run applies schema changes on Vitess through VtGate.
    97  func Run(ctx context.Context, controller Controller, executor Executor) (execResult *ExecuteResult, err error) {
    98  	if err := controller.Open(ctx); err != nil {
    99  		log.Errorf("failed to open data sourcer: %v", err)
   100  		return execResult, err
   101  	}
   102  	defer controller.Close()
   103  	sqls, err := controller.Read(ctx)
   104  	if err != nil {
   105  		log.Errorf("failed to read data from data sourcer: %v", err)
   106  		controller.OnReadFail(ctx, err)
   107  		return execResult, err
   108  	}
   109  	controller.OnReadSuccess(ctx)
   110  	if len(sqls) == 0 {
   111  		return execResult, nil
   112  	}
   113  	keyspace := controller.Keyspace()
   114  	if err := executor.Open(ctx, keyspace); err != nil {
   115  		log.Errorf("failed to open executor: %v", err)
   116  		return execResult, err
   117  	}
   118  	defer executor.Close()
   119  	if err := executor.Validate(ctx, sqls); err != nil {
   120  		log.Errorf("validation fail: %v", err)
   121  		controller.OnValidationFail(ctx, err)
   122  		return execResult, err
   123  	}
   124  
   125  	if err := controller.OnValidationSuccess(ctx); err != nil {
   126  		return execResult, err
   127  	}
   128  
   129  	execResult = executor.Execute(ctx, sqls)
   130  
   131  	if err := controller.OnExecutorComplete(ctx, execResult); err != nil {
   132  		return execResult, err
   133  	}
   134  	if execResult.ExecutorErr != "" || len(execResult.FailedShards) > 0 {
   135  		out, _ := json.MarshalIndent(execResult, "", "  ")
   136  		return execResult, fmt.Errorf("schema change failed, ExecuteResult: %v", string(out))
   137  	}
   138  	return execResult, nil
   139  }
   140  
   141  // RegisterControllerFactory register a control factory.
   142  func RegisterControllerFactory(name string, factory ControllerFactory) {
   143  	if _, ok := controllerFactories[name]; ok {
   144  		panic(fmt.Sprintf("register a registered key: %s", name))
   145  	}
   146  	controllerFactories[name] = factory
   147  }
   148  
   149  // GetControllerFactory gets a ControllerFactory.
   150  func GetControllerFactory(name string) (ControllerFactory, error) {
   151  	factory, ok := controllerFactories[name]
   152  	if !ok {
   153  		return nil, fmt.Errorf("there is no data sourcer factory with name: %s", name)
   154  	}
   155  	return factory, nil
   156  }