From 11abc45440fb685363aa31df5693b532634ab9ec Mon Sep 17 00:00:00 2001 From: Athurg Gooth Date: Thu, 3 Aug 2023 19:08:39 +0800 Subject: [PATCH] feat: add command to move blob from local to db (#2026) * Add `mvrss` command to move blob from local to db * Add comment for mvrss command --- cmd/memos.go | 78 +++++++++++++++++++++++++++++++++++++++++++++++ store/resource.go | 14 +++++++-- 2 files changed, 89 insertions(+), 3 deletions(-) diff --git a/cmd/memos.go b/cmd/memos.go index dbc1940c..90c371ce 100644 --- a/cmd/memos.go +++ b/cmd/memos.go @@ -114,6 +114,77 @@ var ( } }, } + + mvrssCmd = &cobra.Command{ + Use: "mvrss", // `mvrss` is a shortened for 'means move resource' + Short: "Move resource between storage", + Run: func(cmd *cobra.Command, _ []string) { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + + from, err := cmd.Flags().GetString(mvrssCmdFlagFrom) + if err != nil { + fmt.Printf("failed to get from storage, error: %+v\n", err) + return + } + + to, err := cmd.Flags().GetString(mvrssCmdFlagTo) + if err != nil { + fmt.Printf("failed to get to storage, error: %+v\n", err) + return + } + + if from != "local" || to != "db" { + fmt.Printf("only local=>db be supported currently\n") + return + } + + db := db.NewDB(profile) + if err := db.Open(ctx); err != nil { + fmt.Printf("failed to open db, error: %+v\n", err) + return + } + + s := store.New(db.DBInstance, profile) + resources, err := s.ListResources(ctx, &store.FindResource{}) + if err != nil { + fmt.Printf("failed to list resources, error: %+v\n", err) + return + } + + var emptyString string + for _, res := range resources { + if res.InternalPath == "" { + continue + } + + buf, err := os.ReadFile(res.InternalPath) + if err != nil { + fmt.Printf("Resource %5d failed to read file: %s\n", res.ID, err) + continue + } + + if len(buf) != int(res.Size) { + fmt.Printf("Resource %5d size of file %d != %d\n", res.ID, len(buf), res.Size) + continue + } + + update := store.UpdateResource{ + ID: res.ID, + Blob: buf, + InternalPath: &emptyString, + } + _, err = s.UpdateResource(ctx, &update) + if err != nil { + fmt.Printf("Resource %5d failed to update: %s\n", res.ID, err) + continue + } + + fmt.Printf("Resource %5d copy %12d bytes from %s\n", res.ID, len(buf), res.InternalPath) + } + fmt.Println("done") + }, + } ) func Execute() error { @@ -148,6 +219,11 @@ func init() { setupCmd.Flags().String(setupCmdFlagHostPassword, "", "Owner password") rootCmd.AddCommand(setupCmd) + + mvrssCmd.Flags().String(mvrssCmdFlagFrom, "local", "From storage") + mvrssCmd.Flags().String(mvrssCmdFlagTo, "db", "To Storage") + + rootCmd.AddCommand(mvrssCmd) } func initConfig() { @@ -171,4 +247,6 @@ func initConfig() { const ( setupCmdFlagHostUsername = "host-username" setupCmdFlagHostPassword = "host-password" + mvrssCmdFlagFrom = "from" + mvrssCmdFlagTo = "to" ) diff --git a/store/resource.go b/store/resource.go index 7700124c..706b6957 100644 --- a/store/resource.go +++ b/store/resource.go @@ -36,9 +36,11 @@ type FindResource struct { } type UpdateResource struct { - ID int - UpdatedTs *int64 - Filename *string + ID int + UpdatedTs *int64 + Filename *string + InternalPath *string + Blob []byte } type DeleteResource struct { @@ -174,6 +176,12 @@ func (s *Store) UpdateResource(ctx context.Context, update *UpdateResource) (*Re if v := update.Filename; v != nil { set, args = append(set, "filename = ?"), append(args, *v) } + if v := update.InternalPath; v != nil { + set, args = append(set, "internal_path = ?"), append(args, *v) + } + if v := update.Blob; v != nil { + set, args = append(set, "blob = ?"), append(args, v) + } args = append(args, update.ID) fields := []string{"id", "filename", "external_link", "type", "size", "creator_id", "created_ts", "updated_ts", "internal_path"}