github.com/Finschia/finschia-sdk@v0.48.1/types/module/configurator.go (about)

     1  package module
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/gogo/protobuf/grpc"
     7  
     8  	"github.com/Finschia/finschia-sdk/codec"
     9  	sdk "github.com/Finschia/finschia-sdk/types"
    10  	sdkerrors "github.com/Finschia/finschia-sdk/types/errors"
    11  )
    12  
    13  // Configurator provides the hooks to allow modules to configure and register
    14  // their services in the RegisterServices method. It is designed to eventually
    15  // support module object capabilities isolation as described in
    16  // https://github.com/cosmos/cosmos-sdk/issues/7093
    17  type Configurator interface {
    18  	// MsgServer returns a grpc.Server instance which allows registering services
    19  	// that will handle TxBody.messages in transactions. These Msg's WILL NOT
    20  	// be exposed as gRPC services.
    21  	MsgServer() grpc.Server
    22  
    23  	// QueryServer returns a grpc.Server instance which allows registering services
    24  	// that will be exposed as gRPC services as well as ABCI query handlers.
    25  	QueryServer() grpc.Server
    26  
    27  	// RegisterMigration registers an in-place store migration for a module. The
    28  	// handler is a migration script to perform in-place migrations from version
    29  	// `forVersion` to version `forVersion+1`.
    30  	//
    31  	// EACH TIME a module's ConsensusVersion increments, a new migration MUST
    32  	// be registered using this function. If a migration handler is missing for
    33  	// a particular function, the upgrade logic (see RunMigrations function)
    34  	// will panic. If the ConsensusVersion bump does not introduce any store
    35  	// changes, then a no-op function must be registered here.
    36  	RegisterMigration(moduleName string, forVersion uint64, handler MigrationHandler) error
    37  }
    38  
    39  type configurator struct {
    40  	cdc         codec.Codec
    41  	msgServer   grpc.Server
    42  	queryServer grpc.Server
    43  
    44  	// migrations is a map of moduleName -> forVersion -> migration script handler
    45  	migrations map[string]map[uint64]MigrationHandler
    46  }
    47  
    48  // NewConfigurator returns a new Configurator instance
    49  func NewConfigurator(cdc codec.Codec, msgServer grpc.Server, queryServer grpc.Server) Configurator {
    50  	return configurator{
    51  		cdc:         cdc,
    52  		msgServer:   msgServer,
    53  		queryServer: queryServer,
    54  		migrations:  map[string]map[uint64]MigrationHandler{},
    55  	}
    56  }
    57  
    58  var _ Configurator = configurator{}
    59  
    60  // MsgServer implements the Configurator.MsgServer method
    61  func (c configurator) MsgServer() grpc.Server {
    62  	return c.msgServer
    63  }
    64  
    65  // QueryServer implements the Configurator.QueryServer method
    66  func (c configurator) QueryServer() grpc.Server {
    67  	return c.queryServer
    68  }
    69  
    70  // RegisterMigration implements the Configurator.RegisterMigration method
    71  func (c configurator) RegisterMigration(moduleName string, forVersion uint64, handler MigrationHandler) error {
    72  	if forVersion == 0 {
    73  		return sdkerrors.Wrap(sdkerrors.ErrInvalidVersion, "module migration versions should start at 1")
    74  	}
    75  
    76  	if c.migrations[moduleName] == nil {
    77  		c.migrations[moduleName] = map[uint64]MigrationHandler{}
    78  	}
    79  
    80  	if c.migrations[moduleName][forVersion] != nil {
    81  		return sdkerrors.Wrapf(sdkerrors.ErrLogic, "another migration for module %s and version %d already exists", moduleName, forVersion)
    82  	}
    83  
    84  	c.migrations[moduleName][forVersion] = handler
    85  
    86  	return nil
    87  }
    88  
    89  // runModuleMigrations runs all in-place store migrations for one given module from a
    90  // version to another version.
    91  func (c configurator) runModuleMigrations(ctx sdk.Context, moduleName string, fromVersion, toVersion uint64) error {
    92  	// No-op if toVersion is the initial version or if the version is unchanged.
    93  	if toVersion <= 1 || fromVersion == toVersion {
    94  		return nil
    95  	}
    96  
    97  	moduleMigrationsMap, found := c.migrations[moduleName]
    98  	if !found {
    99  		return sdkerrors.Wrapf(sdkerrors.ErrNotFound, "no migrations found for module %s", moduleName)
   100  	}
   101  
   102  	// Run in-place migrations for the module sequentially until toVersion.
   103  	for i := fromVersion; i < toVersion; i++ {
   104  		migrateFn, found := moduleMigrationsMap[i]
   105  		if !found {
   106  			return sdkerrors.Wrapf(sdkerrors.ErrNotFound, "no migration found for module %s from version %d to version %d", moduleName, i, i+1)
   107  		}
   108  		ctx.Logger().Info(fmt.Sprintf("migrating module %s from version %d to version %d", moduleName, i, i+1))
   109  
   110  		err := migrateFn(ctx)
   111  		if err != nil {
   112  			return err
   113  		}
   114  	}
   115  
   116  	return nil
   117  }