github.com/m3db/m3@v1.5.0/src/dbnode/namespace/schema_registry_updater.go (about)

     1  // Copyright (c) 2019 Uber Technologies, Inc.
     2  //
     3  // Permission is hereby granted, free of charge, to any person obtaining a copy
     4  // of this software and associated documentation files (the "Software"), to deal
     5  // in the Software without restriction, including without limitation the rights
     6  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     7  // copies of the Software, and to permit persons to whom the Software is
     8  // furnished to do so, subject to the following conditions:
     9  //
    10  // The above copyright notice and this permission notice shall be included in
    11  // all copies or substantial portions of the Software.
    12  //
    13  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    14  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    15  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    16  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    17  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    18  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    19  // THE SOFTWARE.
    20  
    21  package namespace
    22  
    23  import (
    24  	"fmt"
    25  
    26  	xerrors "github.com/m3db/m3/src/x/errors"
    27  
    28  	"go.uber.org/zap"
    29  )
    30  
    31  // UpdateSchemaRegistry updates schema registry with namespace updates.
    32  func UpdateSchemaRegistry(newNamespaces Map, schemaReg SchemaRegistry, log *zap.Logger) error {
    33  	schemaUpdates := newNamespaces.Metadatas()
    34  	multiErr := xerrors.NewMultiError()
    35  	for _, metadata := range schemaUpdates {
    36  		var (
    37  			curSchemaID   = "none"
    38  			curSchemaNone = true
    39  		)
    40  		curSchema, err := schemaReg.GetLatestSchema(metadata.ID())
    41  		if err != nil {
    42  			// NB(bodu): Schema history not found is a valid error as this occurs on initial bootstrap for the db.
    43  			if _, ok := err.(*schemaHistoryNotFoundError); !ok {
    44  				multiErr = multiErr.Add(fmt.Errorf("cannot get latest namespace schema: %v", err))
    45  				continue
    46  			}
    47  		}
    48  
    49  		if curSchema != nil {
    50  			curSchemaNone = false
    51  			curSchemaID = curSchema.DeployId()
    52  			if len(curSchemaID) == 0 {
    53  				msg := "namespace schema update invalid with empty deploy ID"
    54  				log.Warn(msg, zap.Stringer("namespace", metadata.ID()),
    55  					zap.String("currentSchemaID", curSchemaID))
    56  				multiErr = multiErr.Add(fmt.Errorf("%s: namespace=%s", msg, metadata.ID().String()))
    57  				continue
    58  			}
    59  		}
    60  
    61  		// Log schema update.
    62  		latestSchema, found := metadata.Options().SchemaHistory().GetLatest()
    63  		if !found {
    64  			if !curSchemaNone {
    65  				// NB(r): Only interpret this as a warning/error if already had a schema,
    66  				// otherwise this is just a namespace that is not using protobuf schemas.
    67  				msg := "namespace schema not found on update"
    68  				log.Warn(msg, zap.Stringer("namespace", metadata.ID()),
    69  					zap.String("currentSchema", curSchemaID))
    70  				multiErr = multiErr.Add(fmt.Errorf("%s: namespace=%s", msg, metadata.ID().String()))
    71  			}
    72  			continue
    73  		}
    74  
    75  		log.Info("updating database namespace schema", zap.Stringer("namespace", metadata.ID()),
    76  			zap.String("currentSchema", curSchemaID), zap.String("latestSchema", latestSchema.DeployId()))
    77  
    78  		err = schemaReg.SetSchemaHistory(metadata.ID(), metadata.Options().SchemaHistory())
    79  		if err != nil {
    80  			msg := "namespace schema failed to update to latest schema"
    81  			log.Warn(msg,
    82  				zap.Stringer("namespace", metadata.ID()),
    83  				zap.Error(err))
    84  			multiErr = multiErr.Add(fmt.Errorf("%s: namespace=%s, error=%v",
    85  				msg, metadata.ID().String(), err))
    86  		}
    87  	}
    88  	if !multiErr.Empty() {
    89  		return multiErr
    90  	}
    91  	return nil
    92  }