Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 35 additions & 3 deletions internal/cmd/backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"io"
"os"
"regexp"
"strconv"
"strings"
"time"

Expand All @@ -22,6 +23,8 @@ import (
"github.com/spf13/cobra"
"golang.org/x/exp/constraints"
"golang.org/x/exp/maps"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"

"github.com/authzed/zed/internal/client"
"github.com/authzed/zed/internal/commands"
Expand Down Expand Up @@ -249,7 +252,7 @@ func backupCreateCmdFunc(cmd *cobra.Command, args []string) (err error) {
ctx := cmd.Context()
schemaResp, err := c.ReadSchema(ctx, &v1.ReadSchemaRequest{})
if err != nil {
return fmt.Errorf("error reading schema: %w", err)
return fmt.Errorf("error reading schema: %w", addSizeErrInfo(err))
} else if schemaResp.ReadAt == nil {
return fmt.Errorf("`backup` is not supported on this version of SpiceDB")
}
Expand Down Expand Up @@ -284,7 +287,7 @@ func backupCreateCmdFunc(cmd *cobra.Command, args []string) (err error) {
},
})
if err != nil {
return fmt.Errorf("error exporting relationships: %w", err)
return fmt.Errorf("error exporting relationships: %w", addSizeErrInfo(err))
}

relationshipReadStart := time.Now()
Expand All @@ -299,7 +302,7 @@ func backupCreateCmdFunc(cmd *cobra.Command, args []string) (err error) {
relsResp, err := relationshipStream.Recv()
if err != nil {
if !errors.Is(err, io.EOF) {
return fmt.Errorf("error receiving relationships: %w", err)
return fmt.Errorf("error receiving relationships: %w", addSizeErrInfo(err))
}
break
}
Expand Down Expand Up @@ -619,3 +622,32 @@ func rewriteLegacy(schema string) string {
schema = string(missingAllowedTypes.ReplaceAll([]byte(schema), []byte("\n/* deleted missing allowed type error */")))
return string(shortRelations.ReplaceAll([]byte(schema), []byte("\n/* deleted short relation name */")))
}

var sizeErrorRegEx = regexp.MustCompile(`received message larger than max \((\d+) vs. (\d+)\)`)

func addSizeErrInfo(err error) error {
if err == nil {
return nil
}

code := status.Code(err)
if code != codes.ResourceExhausted {
return err
}

if !strings.Contains(err.Error(), "received message larger than max") {
return err
}

matches := sizeErrorRegEx.FindStringSubmatch(err.Error())
if len(matches) != 3 {
return fmt.Errorf("%w: set flag --max-message-size=bytecounthere to increase the maximum allowable size", err)
}

necessaryByteCount, err := strconv.Atoi(matches[1])
if err != nil {
return fmt.Errorf("%w: set flag --max-message-size=bytecounthere to increase the maximum allowable size", err)
}

return fmt.Errorf("%w: set flag --max-message-size=%d to increase the maximum allowable size", err, 2*necessaryByteCount)
}
58 changes: 56 additions & 2 deletions internal/cmd/backup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,23 @@ package cmd

import (
"context"
"errors"
"os"
"path/filepath"
"strings"
"testing"

"github.com/authzed/zed/internal/client"
zedtesting "github.com/authzed/zed/internal/testing"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"

v1 "github.com/authzed/authzed-go/proto/authzed/api/v1"
"github.com/authzed/spicedb/pkg/tuple"
"github.com/google/uuid"
"github.com/rs/zerolog"
"github.com/stretchr/testify/require"

"github.com/authzed/zed/internal/client"
zedtesting "github.com/authzed/zed/internal/testing"
)

func init() {
Expand Down Expand Up @@ -379,3 +383,53 @@ func TestBackupRestoreCmdFunc(t *testing.T) {
require.NoError(t, rrCli.CloseSend())
require.Equal(t, "test/resource:1#reader@test/user:1", tuple.MustStringRelationship(rrResp.Relationship))
}

func TestAddSizeErrInfo(t *testing.T) {
tcs := []struct {
name string
err error
expectedError string
}{
{
name: "error is nil",
err: nil,
expectedError: "",
},
{
name: "error is not a size error",
err: errors.New("some error"),
expectedError: "some error",
},
{
name: "error has correct code, wrong message",
err: status.New(codes.ResourceExhausted, "foobar").Err(),
expectedError: "foobar",
},
{
name: "error has correct message, wrong code",
err: status.New(codes.Unauthenticated, "received message larger than max").Err(),
expectedError: "received message larger than max",
},
{
name: "error has correct code and message",
err: status.New(codes.ResourceExhausted, "received message larger than max").Err(),
expectedError: "set flag --max-message-size=bytecounthere",
},
{
name: "error has correct code and message with additional info",
err: status.New(codes.ResourceExhausted, "received message larger than max (1234 vs. 45)").Err(),
expectedError: "set flag --max-message-size=2468",
},
}

for _, tc := range tcs {
t.Run(tc.name, func(t *testing.T) {
err := addSizeErrInfo(tc.err)
if tc.expectedError == "" {
require.NoError(t, err)
} else {
require.ErrorContains(t, err, tc.expectedError)
}
})
}
}
2 changes: 1 addition & 1 deletion internal/cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ func Run() {
rootCmd.PersistentFlags().Bool("no-verify-ca", false, "do not attempt to verify the server's certificate chain and host name")
rootCmd.PersistentFlags().Bool("debug", false, "enable debug logging")
rootCmd.PersistentFlags().String("request-id", "", "optional id to send along with SpiceDB requests for tracing")
rootCmd.PersistentFlags().Int("max-message-size", 0, "maximum size in bytes (defaults to 4mb) of a gRPC message that can be sent or received by zed")
rootCmd.PersistentFlags().Int("max-message-size", 0, "maximum size *in bytes* (defaults to 4_194_304 bytes ~= 4MB) of a gRPC message that can be sent or received by zed")
_ = rootCmd.PersistentFlags().MarkHidden("debug") // This cannot return its error.

versionCmd := &cobra.Command{
Expand Down
Loading