github.com/masterhung0112/hk_server/v5@v5.0.0-20220302090640-ec71aef15e1c/cmd/hkserver/commands/integrity.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See LICENSE.txt for license information. 3 4 package commands 5 6 import ( 7 "fmt" 8 "os" 9 "strings" 10 11 "github.com/spf13/cobra" 12 13 "github.com/masterhung0112/hk_server/v5/model" 14 ) 15 16 var IntegrityCmd = &cobra.Command{ 17 Use: "integrity", 18 Short: "Check database data integrity", 19 RunE: integrityCmdF, 20 } 21 22 func init() { 23 IntegrityCmd.Flags().Bool("confirm", false, "Confirm you really want to run a complete integrity check that may temporarily harm system performance") 24 IntegrityCmd.Flags().BoolP("verbose", "v", false, "Show detailed information on integrity check results") 25 RootCmd.AddCommand(IntegrityCmd) 26 } 27 28 func printRelationalIntegrityCheckResult(data model.RelationalIntegrityCheckData, verbose bool) { 29 fmt.Printf("Found %d records in relation %s orphans of relation %s\n", 30 len(data.Records), data.ChildName, data.ParentName) 31 if !verbose { 32 return 33 } 34 for _, record := range data.Records { 35 var parentId string 36 37 if record.ParentId == nil { 38 parentId = "NULL" 39 } else if *record.ParentId == "" { 40 parentId = "empty" 41 } else { 42 parentId = *record.ParentId 43 } 44 45 if record.ChildId != nil { 46 if parentId == "NULL" || parentId == "empty" { 47 fmt.Printf(" Child %s (%s.%s) has %s ParentIdAttr (%s.%s)\n", *record.ChildId, data.ChildName, data.ChildIdAttr, parentId, data.ChildName, data.ParentIdAttr) 48 } else { 49 fmt.Printf(" Child %s (%s.%s) is missing Parent %s (%s.%s)\n", *record.ChildId, data.ChildName, data.ChildIdAttr, parentId, data.ChildName, data.ParentIdAttr) 50 } 51 } else { 52 if parentId == "NULL" || parentId == "empty" { 53 fmt.Printf(" Child has %s ParentIdAttr (%s.%s)\n", parentId, data.ChildName, data.ParentIdAttr) 54 } else { 55 fmt.Printf(" Child is missing Parent %s (%s.%s)\n", parentId, data.ChildName, data.ParentIdAttr) 56 } 57 } 58 } 59 } 60 61 func printIntegrityCheckResult(result model.IntegrityCheckResult, verbose bool) { 62 switch data := result.Data.(type) { 63 case model.RelationalIntegrityCheckData: 64 printRelationalIntegrityCheckResult(data, verbose) 65 } 66 } 67 68 func integrityCmdF(command *cobra.Command, args []string) error { 69 a, err := InitDBCommandContextCobra(command) 70 if err != nil { 71 return err 72 } 73 defer a.Srv().Shutdown() 74 75 confirmFlag, _ := command.Flags().GetBool("confirm") 76 if !confirmFlag { 77 var confirm string 78 fmt.Fprintf(os.Stdout, "This check may harm performance on live systems. Are you sure you want to proceed? (y/N): ") 79 fmt.Scanln(&confirm) 80 if !strings.EqualFold(confirm, "y") && !strings.EqualFold(confirm, "yes") { 81 fmt.Fprintf(os.Stderr, "Aborted.\n") 82 return nil 83 } 84 } 85 86 verboseFlag, _ := command.Flags().GetBool("verbose") 87 results := a.Srv().Store.CheckIntegrity() 88 for result := range results { 89 if result.Err != nil { 90 fmt.Fprintf(os.Stderr, "%s\n", result.Err.Error()) 91 break 92 } 93 printIntegrityCheckResult(result, verboseFlag) 94 } 95 96 return nil 97 }