From c160c2b3aa8c115134a95834c0eb08ee2cfec198 Mon Sep 17 00:00:00 2001 From: Jamie Barton Date: Tue, 30 Jul 2024 12:23:59 +0100 Subject: [PATCH 1/7] feat(db/create): ask to wake sleeping groups before create --- internal/cmd/db_create.go | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/internal/cmd/db_create.go b/internal/cmd/db_create.go index ce145b36..070d7012 100644 --- a/internal/cmd/db_create.go +++ b/internal/cmd/db_create.go @@ -55,6 +55,27 @@ var createCmd = &cobra.Command{ return err } + groupInfo, err := getGroup(client, group) + if err != nil { + return fmt.Errorf("failed to get group info: %w", err) + } + + groupStatus := aggregateGroupStatus(groupInfo) + if groupStatus == "Archived 💤" { + fmt.Printf("The group %s is currently archived. Do you want to wake it up? [Y/n]: ", internal.Emph(group)) + var response string + fmt.Scanln(&response) + if response == "" || response == "y" || response == "yes" { + err = unarchiveGroup(client, group) + if err != nil { + return fmt.Errorf("failed to wake up group: %w", err) + } + fmt.Printf("Group %s has been woken up.\n", internal.Emph(group)) + } else { + return fmt.Errorf("cannot create a database in an archived group. Please wake up the group first") + } + } + location, err := locationFromFlag(client) if err != nil { return err From d57d29c1c23779f4ad4131585de889bd04fc0214 Mon Sep 17 00:00:00 2001 From: Jamie Barton Date: Tue, 30 Jul 2024 12:33:29 +0100 Subject: [PATCH 2/7] create group utils --- internal/cmd/db_create.go | 21 ++++----------------- internal/cmd/group_utils.go | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 17 deletions(-) create mode 100644 internal/cmd/group_utils.go diff --git a/internal/cmd/db_create.go b/internal/cmd/db_create.go index 070d7012..c807f859 100644 --- a/internal/cmd/db_create.go +++ b/internal/cmd/db_create.go @@ -55,25 +55,12 @@ var createCmd = &cobra.Command{ return err } - groupInfo, err := getGroup(client, group) + awake, err := ensureGroupAwake(client, group) if err != nil { - return fmt.Errorf("failed to get group info: %w", err) + return err } - - groupStatus := aggregateGroupStatus(groupInfo) - if groupStatus == "Archived 💤" { - fmt.Printf("The group %s is currently archived. Do you want to wake it up? [Y/n]: ", internal.Emph(group)) - var response string - fmt.Scanln(&response) - if response == "" || response == "y" || response == "yes" { - err = unarchiveGroup(client, group) - if err != nil { - return fmt.Errorf("failed to wake up group: %w", err) - } - fmt.Printf("Group %s has been woken up.\n", internal.Emph(group)) - } else { - return fmt.Errorf("cannot create a database in an archived group. Please wake up the group first") - } + if !awake { + return fmt.Errorf("cannot create a database in an archived group. Please wake up the group first") } location, err := locationFromFlag(client) diff --git a/internal/cmd/group_utils.go b/internal/cmd/group_utils.go new file mode 100644 index 00000000..34b8a44a --- /dev/null +++ b/internal/cmd/group_utils.go @@ -0,0 +1,36 @@ +package cmd + +import ( + "fmt" + "strings" + + "github.com/tursodatabase/turso-cli/internal" + "github.com/tursodatabase/turso-cli/internal/turso" +) + +func ensureGroupAwake(client *turso.Client, groupName string) (bool, error) { + group, err := getGroup(client, groupName) + if err != nil { + return false, fmt.Errorf("failed to get group info: %w", err) + } + + groupStatus := aggregateGroupStatus(group) + if groupStatus != "Archived 💤" { + return true, nil + } + + fmt.Printf("The group %s is currently archived. Do you want to wake it up? [Y/n]: ", internal.Emph(groupName)) + var response string + fmt.Scanln(&response) + response = strings.ToLower(strings.TrimSpace(response)) + if response == "" || response == "y" || response == "yes" { + err = unarchiveGroup(client, groupName) + if err != nil { + return false, fmt.Errorf("failed to wake up group: %w", err) + } + fmt.Printf("Group %s has been woken up.\n", internal.Emph(groupName)) + return true, nil + } + + return false, nil +} From 2041cf503700ca9c0172f4619d928610ddf5ba8a Mon Sep 17 00:00:00 2001 From: Jamie Barton Date: Tue, 30 Jul 2024 12:38:51 +0100 Subject: [PATCH 3/7] check group is unarchived before connecting to shell --- internal/cmd/db_shell.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/internal/cmd/db_shell.go b/internal/cmd/db_shell.go index ef462eb5..5a8e1d91 100644 --- a/internal/cmd/db_shell.go +++ b/internal/cmd/db_shell.go @@ -108,6 +108,16 @@ var shellCmd = &cobra.Command{ return err } + spinner.Stop() + awake, err := ensureGroupAwake(client, db.Group) + if err != nil { + return err + } + if !awake { + return fmt.Errorf("cannot connect to a database in an archived group. Please wake up the group first") + } + spinner.Start() + var claim *turso.PermissionsClaim if len(flags.AttachClaims()) > 0 { err := validateDBNames(client, flags.AttachClaims()) From 98a4981cb6ea5d5c0c0f87e2bf43e864323967a5 Mon Sep 17 00:00:00 2001 From: Jamie Barton Date: Tue, 30 Jul 2024 13:34:39 +0100 Subject: [PATCH 4/7] =?UTF-8?q?remove=20=F0=9F=92=A4=20emoji?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/cmd/group.go | 2 +- internal/cmd/group_utils.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/cmd/group.go b/internal/cmd/group.go index cfaf664c..5f70e070 100644 --- a/internal/cmd/group.go +++ b/internal/cmd/group.go @@ -226,7 +226,7 @@ func groupsTable(groups []turso.Group) [][]string { func aggregateGroupStatus(group turso.Group) string { status := "Healthy" if group.Archived { - return "Archived 💤" + return "Archived" } allIdle := true for _, locationStatus := range group.Status.Locations { diff --git a/internal/cmd/group_utils.go b/internal/cmd/group_utils.go index 34b8a44a..089369f9 100644 --- a/internal/cmd/group_utils.go +++ b/internal/cmd/group_utils.go @@ -15,7 +15,7 @@ func ensureGroupAwake(client *turso.Client, groupName string) (bool, error) { } groupStatus := aggregateGroupStatus(group) - if groupStatus != "Archived 💤" { + if groupStatus != "Archived" { return true, nil } From a4ce8a81e8f5ac526ef10c186d7ddd8d12b451ff Mon Sep 17 00:00:00 2001 From: Jamie Barton Date: Tue, 30 Jul 2024 14:14:20 +0100 Subject: [PATCH 5/7] use promptConfirmation --- internal/cmd/group_utils.go | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/internal/cmd/group_utils.go b/internal/cmd/group_utils.go index 089369f9..cb15d7dd 100644 --- a/internal/cmd/group_utils.go +++ b/internal/cmd/group_utils.go @@ -2,7 +2,6 @@ package cmd import ( "fmt" - "strings" "github.com/tursodatabase/turso-cli/internal" "github.com/tursodatabase/turso-cli/internal/turso" @@ -19,11 +18,13 @@ func ensureGroupAwake(client *turso.Client, groupName string) (bool, error) { return true, nil } - fmt.Printf("The group %s is currently archived. Do you want to wake it up? [Y/n]: ", internal.Emph(groupName)) - var response string - fmt.Scanln(&response) - response = strings.ToLower(strings.TrimSpace(response)) - if response == "" || response == "y" || response == "yes" { + prompt := fmt.Sprintf("The group %s is currently archived. Do you want to wake it up?", internal.Emph(groupName)) + confirmed, err := promptConfirmation(prompt) + if err != nil { + return false, fmt.Errorf("could not get prompt confirmed by user: %w", err) + } + + if confirmed { err = unarchiveGroup(client, groupName) if err != nil { return false, fmt.Errorf("failed to wake up group: %w", err) From dc8aa23e6182d975df4552c77fec594efc56ff7a Mon Sep 17 00:00:00 2001 From: Jamie Barton Date: Tue, 30 Jul 2024 14:16:19 +0100 Subject: [PATCH 6/7] dont print success twice --- internal/cmd/group_utils.go | 1 - 1 file changed, 1 deletion(-) diff --git a/internal/cmd/group_utils.go b/internal/cmd/group_utils.go index cb15d7dd..2e7aaa16 100644 --- a/internal/cmd/group_utils.go +++ b/internal/cmd/group_utils.go @@ -29,7 +29,6 @@ func ensureGroupAwake(client *turso.Client, groupName string) (bool, error) { if err != nil { return false, fmt.Errorf("failed to wake up group: %w", err) } - fmt.Printf("Group %s has been woken up.\n", internal.Emph(groupName)) return true, nil } From 77bbb442282ed9fb79dc9ba3dcb2cbaff6b4a6c8 Mon Sep 17 00:00:00 2001 From: Jamie Barton Date: Wed, 7 Aug 2024 11:16:16 +0100 Subject: [PATCH 7/7] retry based on error --- internal/cmd/db_create.go | 19 +++++--------- internal/cmd/db_shell.go | 10 ------- internal/cmd/group_utils.go | 52 ++++++++++++++++++++++++------------- 3 files changed, 40 insertions(+), 41 deletions(-) diff --git a/internal/cmd/db_create.go b/internal/cmd/db_create.go index c807f859..cd1f3deb 100644 --- a/internal/cmd/db_create.go +++ b/internal/cmd/db_create.go @@ -8,7 +8,6 @@ import ( "github.com/spf13/cobra" "github.com/tursodatabase/turso-cli/internal" "github.com/tursodatabase/turso-cli/internal/flags" - "github.com/tursodatabase/turso-cli/internal/prompt" "github.com/tursodatabase/turso-cli/internal/turso" ) @@ -55,14 +54,6 @@ var createCmd = &cobra.Command{ return err } - awake, err := ensureGroupAwake(client, group) - if err != nil { - return err - } - if !awake { - return fmt.Errorf("cannot create a database in an archived group. Please wake up the group first") - } - location, err := locationFromFlag(client) if err != nil { return err @@ -83,14 +74,16 @@ var createCmd = &cobra.Command{ } start := time.Now() - spinner := prompt.Spinner(fmt.Sprintf("Creating database %s in group %s...", internal.Emph(name), internal.Emph(group))) - defer spinner.Stop() + spinnerText := fmt.Sprintf("Creating database %s in group %s...", internal.Emph(name), internal.Emph(group)) + + _, err = RetryOnSleepingGroup(client, group, spinnerText, func() (any, error) { + return client.Databases.Create(name, location, "", "", group, schemaFlag, typeFlag == "schema", seed, sizeLimitFlag) + }) - if _, err = client.Databases.Create(name, location, "", "", group, schemaFlag, typeFlag == "schema", seed, sizeLimitFlag); err != nil { + if err != nil { return fmt.Errorf("could not create database %s: %w", name, err) } - spinner.Stop() elapsed := time.Since(start) fmt.Printf("Created database %s at group %s in %s.\n\n", internal.Emph(name), internal.Emph(group), elapsed.Round(time.Millisecond).String()) diff --git a/internal/cmd/db_shell.go b/internal/cmd/db_shell.go index 5a8e1d91..ef462eb5 100644 --- a/internal/cmd/db_shell.go +++ b/internal/cmd/db_shell.go @@ -108,16 +108,6 @@ var shellCmd = &cobra.Command{ return err } - spinner.Stop() - awake, err := ensureGroupAwake(client, db.Group) - if err != nil { - return err - } - if !awake { - return fmt.Errorf("cannot connect to a database in an archived group. Please wake up the group first") - } - spinner.Start() - var claim *turso.PermissionsClaim if len(flags.AttachClaims()) > 0 { err := validateDBNames(client, flags.AttachClaims()) diff --git a/internal/cmd/group_utils.go b/internal/cmd/group_utils.go index 2e7aaa16..3ce2eb5b 100644 --- a/internal/cmd/group_utils.go +++ b/internal/cmd/group_utils.go @@ -2,35 +2,51 @@ package cmd import ( "fmt" + "strings" + "time" "github.com/tursodatabase/turso-cli/internal" + "github.com/tursodatabase/turso-cli/internal/prompt" "github.com/tursodatabase/turso-cli/internal/turso" ) -func ensureGroupAwake(client *turso.Client, groupName string) (bool, error) { - group, err := getGroup(client, groupName) - if err != nil { - return false, fmt.Errorf("failed to get group info: %w", err) +func RetryOnSleepingGroup(client *turso.Client, group string, mainSpinnerText string, action func() (any, error)) (any, error) { + mainSpinner := prompt.Spinner(mainSpinnerText) + result, actionErr := action() + if actionErr == nil { + return result, nil } - groupStatus := aggregateGroupStatus(group) - if groupStatus != "Archived" { - return true, nil - } + errMsg := actionErr.Error() + if strings.Contains(errMsg, "group_sleeping") || + (strings.Contains(errMsg, "cannot create database on group") && strings.Contains(errMsg, "because it is archived")) { - prompt := fmt.Sprintf("The group %s is currently archived. Do you want to wake it up?", internal.Emph(groupName)) - confirmed, err := promptConfirmation(prompt) - if err != nil { - return false, fmt.Errorf("could not get prompt confirmed by user: %w", err) - } + mainSpinner.Stop() + fmt.Printf("Error: %s\n\n", errMsg) + time.Sleep(time.Second) - if confirmed { - err = unarchiveGroup(client, groupName) + promptMsg := fmt.Sprintf("The group %s is currently archived. Do you want to unarchive it now??", internal.Emph(group)) + confirmed, err := promptConfirmation(promptMsg) if err != nil { - return false, fmt.Errorf("failed to wake up group: %w", err) + return nil, fmt.Errorf("could not get prompt confirmed by user: %w", err) + } + if !confirmed { + return nil, fmt.Errorf("cannot perform action on an archived group") } - return true, nil + + err = unarchiveGroup(client, group) + if err != nil { + return nil, fmt.Errorf("failed to wake up group: %w", err) + } + + fmt.Printf("Retrying...\n") + time.Sleep(time.Second) + + mainSpinner = prompt.Spinner(mainSpinnerText) + + return action() } - return false, nil + mainSpinner.Stop() + return nil, actionErr }