-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Validators DB Upgrades #318
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
package validators | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"go.uber.org/zap" | ||
) | ||
|
||
type upgradeAction int | ||
|
||
const ( | ||
upgradeActionNone upgradeAction = iota | ||
upgradeActionRunMigrations | ||
) | ||
|
||
func upgradeActionString(action upgradeAction) string { | ||
switch action { | ||
case upgradeActionNone: | ||
return "none" | ||
case upgradeActionRunMigrations: | ||
return "run migrations" | ||
default: | ||
return "unknown" | ||
} | ||
} | ||
|
||
// checkVersion checks the current version of the validator store and decides | ||
// whether to run any db migrations. | ||
func (vs *validatorStore) checkVersion(ctx context.Context) (int, upgradeAction, error) { | ||
// Check if schema version exists | ||
version, versionErr := vs.currentVersion(ctx) | ||
// On error, infer that schema_version table doesn't exist (just assuming this | ||
// since we'd need to query sqlite_master table to be certain that was the error) | ||
if versionErr != nil { | ||
// Check if validators db exists (again only infers and this isn't robust because it could fail for other reasons) | ||
_, valErr := vs.currentValidators(ctx) | ||
if valErr != nil { | ||
// Fresh db, do regular initialization at valStoreVersion | ||
return valStoreVersion, upgradeActionNone, nil | ||
} | ||
if valErr == nil { | ||
// Legacy db without version tracking - version 0 | ||
return 0, upgradeActionRunMigrations, nil | ||
} | ||
} | ||
|
||
if version == valStoreVersion { | ||
// DB on the latest version | ||
return version, upgradeActionNone, nil | ||
} | ||
if version < valStoreVersion { | ||
// DB on previous version, Run DB migrations | ||
return version, upgradeActionRunMigrations, nil | ||
} | ||
|
||
// Invalid DB version, return error | ||
return version, upgradeActionNone, fmt.Errorf("validator store version %d is higher than the supported version %d", version, valStoreVersion) | ||
} | ||
|
||
// databaseUpgrade runs the database upgrade based on the current version. | ||
func (vs *validatorStore) initOrUpgradeDatabase(ctx context.Context) error { | ||
version, action, err := vs.checkVersion(ctx) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
vs.log.Info("databaseUpgrade", zap.Int("version", version), zap.String("action", upgradeActionString(action))) | ||
|
||
switch action { | ||
case upgradeActionNone: | ||
return vs.initTables(ctx) | ||
case upgradeActionRunMigrations: | ||
return vs.runMigrations(ctx, version) | ||
default: | ||
vs.log.Error("unknown upgrade action", zap.Int("action", int(action))) | ||
return fmt.Errorf("unknown upgrade action: %d", action) | ||
} | ||
} | ||
|
||
// runMigrations runs incremental db upgrades from current version to the latest version. | ||
func (vs *validatorStore) runMigrations(ctx context.Context, version int) error { | ||
switch version { | ||
case 0: | ||
if err := vs.upgradeValidatorsDB_0_1(ctx); err != nil { | ||
return err | ||
} | ||
fallthrough | ||
case valStoreVersion: | ||
vs.log.Info("databaseUpgrade: completed successfully") | ||
return nil | ||
default: | ||
vs.log.Error("unknown version", zap.Int("version", version)) | ||
return fmt.Errorf("unknown version: %d", version) | ||
} | ||
} | ||
|
||
// upgradeValidatorsDB_0_1 upgrades the validators db from version 0 to 1. | ||
// Version 0: join_reqs table: [candidate, power] | ||
// Version 1: join_reqs table: [candidate, power, expiryAt] | ||
// "ALTER TABLE join_reqs ADD COLUMN expiresAt INTEGER;" | ||
func (vs *validatorStore) upgradeValidatorsDB_0_1(ctx context.Context) error { | ||
vs.log.Info("Upgrading validators db from version 0 to 1") | ||
// Add schema version table | ||
if err := vs.initSchemaVersion(ctx); err != nil { | ||
return err | ||
} | ||
|
||
if err := vs.db.Execute(ctx, sqlAddJoinExpiry, nil); err != nil { | ||
return fmt.Errorf("failed to add expiresAt column to join_reqs table: %w", err) | ||
} | ||
return nil | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No major issue with the string based approach for digesting all the data, but I'll look at this tonight (can be after this merges) and I feel like we might be safer with an all binary approach like with the genesisConfig appHash generation. The fmt package tends to be oriented toward display and often has subtle changes. encoding/binary tends to be more well defined and stable.