diff --git a/internal/api/handler.go b/internal/api/handler.go index 5c719f7fd..ca4073374 100644 --- a/internal/api/handler.go +++ b/internal/api/handler.go @@ -1540,10 +1540,11 @@ func (h *Handler) handlePostDashboard(ctx context.Context, ai accessInfo, dash D if create { s = "create" } + err = fmt.Errorf("cannot %s dashboard: %w", s, err) if metajournal.IsUserRequestError(err) { - return &DashboardInfo{}, httpErr(http.StatusBadRequest, fmt.Errorf("can't %s dashboard: %w", s, err)) + return &DashboardInfo{}, httpErr(http.StatusBadRequest, err) } - return &DashboardInfo{}, fmt.Errorf("can't %s dashboard: %w", s, err) + return &DashboardInfo{}, err } return &DashboardInfo{Dashboard: getDashboardMetaInfo(&dashboard)}, nil } @@ -1617,7 +1618,7 @@ func (h *Handler) handlePostNamespace(ctx context.Context, ai accessInfo, namesp if create { s = "create" } - errReturn := fmt.Errorf("can't %s namespace: %w", s, err) + errReturn := fmt.Errorf("cannot %s namespace: %w", s, err) if metajournal.IsUserRequestError(err) { return &NamespaceInfo{}, httpErr(http.StatusBadRequest, errReturn) } @@ -1677,8 +1678,10 @@ func (h *Handler) handlePostMetric(ctx context.Context, ai accessInfo, _ string, } resp, err = h.metadataLoader.SaveMetric(ctx, metric, ai.toMetadata()) if err != nil { - err = fmt.Errorf("error creating metric in sqlite engine: %w", err) - log.Println(err.Error()) + if metajournal.IsUserRequestError(err) { + errReturn := fmt.Errorf("cannot create metric: %w", err) + return format.MetricMetaValue{}, httpErr(http.StatusBadRequest, errReturn) + } return format.MetricMetaValue{}, fmt.Errorf("failed to create metric: %w", err) } } else { @@ -1700,8 +1703,10 @@ func (h *Handler) handlePostMetric(ctx context.Context, ai accessInfo, _ string, } resp, err = h.metadataLoader.SaveMetric(ctx, metric, ai.toMetadata()) if err != nil { - err = fmt.Errorf("error saving metric in sqllite: %w", err) - log.Println(err.Error()) + if metajournal.IsUserRequestError(err) { + errReturn := fmt.Errorf("cannot update metric: %w", err) + return format.MetricMetaValue{}, httpErr(http.StatusBadRequest, errReturn) + } return format.MetricMetaValue{}, fmt.Errorf("can't edit metric: %w", err) } } diff --git a/internal/metadata/dbv2_test.go b/internal/metadata/dbv2_test.go index 696a5d345..e1bddd870 100644 --- a/internal/metadata/dbv2_test.go +++ b/internal/metadata/dbv2_test.go @@ -81,12 +81,8 @@ func Test_SaveMetric(t *testing.T) { e, err := db.SaveEntity(context.Background(), "a", 0, 0, "{}", true, false, format.MetricEvent, metadata) require.NoError(t, err) require.Equal(t, metadata, e.Metadata) - updates, err := db.JournalEvents(context.Background(), 0, 100) - require.NoError(t, err) - require.Len(t, updates, 1) - m := updates[0] - require.Equal(t, "a", m.Name) - require.Equal(t, "{}", m.Data) + _, err = db.SaveEntity(context.Background(), "a", 0, 0, "{}", true, false, format.MetricEvent, metadata) + require.Error(t, err) } func Test_GetOldVersion(t *testing.T) { diff --git a/internal/metadata/rpc_handler.go b/internal/metadata/rpc_handler.go index be58b0e91..f0428bb76 100644 --- a/internal/metadata/rpc_handler.go +++ b/internal/metadata/rpc_handler.go @@ -204,6 +204,9 @@ func (h *Handler) RawEditEntity(ctx context.Context, hctx *rpc.HandlerContext) ( if errors.Is(err, errInvalidMetricVersion) { return "", data_model.ErrEntityInvalidVersion } + if errors.Is(err, errMetricIsExist) { + return "", data_model.ErrEntityExists + } if err != nil { return "", fmt.Errorf("failed to create event: %w", err) } diff --git a/internal/metajournal/metadata.go b/internal/metajournal/metadata.go index 10d6acb3a..b36131066 100644 --- a/internal/metajournal/metadata.go +++ b/internal/metajournal/metadata.go @@ -15,6 +15,7 @@ import ( "math" "time" + "github.com/vkcom/statshouse/internal/data_model" "go4.org/mem" "github.com/vkcom/statshouse/internal/data_model/gen2/tlmetadata" @@ -39,6 +40,21 @@ func IsUserRequestError(err error) bool { return errors.Is(err, errorInvalidUserRequest) } +func wrapSaveEntityError(err error) error { + var rpcErr = &rpc.Error{} + if errors.As(err, &rpcErr) { + switch rpcErr.Code { + case data_model.ErrEntityInvalidVersion.Code: + return errors.Join(errorInvalidUserRequest, fmt.Errorf(data_model.ErrEntityInvalidVersion.Description)) + case data_model.ErrEntityExists.Code: + return errors.Join(errorInvalidUserRequest, fmt.Errorf(data_model.ErrEntityExists.Description)) + case data_model.ErrEntityNotExists.Code: + return errors.Join(errorInvalidUserRequest, fmt.Errorf(data_model.ErrEntityNotExists.Description)) + } + } + return err +} + func NewMetricMetaLoader(client *tlmetadata.Client, loadTimeout time.Duration) *MetricMetaLoader { return &MetricMetaLoader{ client: client, @@ -71,7 +87,7 @@ func (l *MetricMetaLoader) SaveDashboard(ctx context.Context, value format.Dashb event := tlmetadata.Event{} err = l.client.EditEntitynew(ctx, editMetricReq, nil, &event) if err != nil { - return format.DashboardMeta{}, fmt.Errorf("failed to edit metric: %w", err) + return format.DashboardMeta{}, wrapSaveEntityError(err) } if event.Id < math.MinInt32 || event.Id > math.MaxInt32 { return format.DashboardMeta{}, fmt.Errorf("dashboard ID %d assigned by metaengine does not fit into int32 for dashboard %q", event.Id, event.Name) @@ -121,7 +137,7 @@ func (l *MetricMetaLoader) SaveMetricsGroup(ctx context.Context, value format.Me event := tlmetadata.Event{} err = l.client.EditEntitynew(ctx, editMetricReq, nil, &event) if err != nil { - return format.MetricsGroup{}, fmt.Errorf("failed to edit group: %w", err) + return format.MetricsGroup{}, wrapSaveEntityError(err) } if event.Id < math.MinInt32 || event.Id > math.MaxInt32 { return g, fmt.Errorf("group ID %d assigned by metaengine does not fit into int32 for group %q", event.Id, event.Name) @@ -167,7 +183,7 @@ func (l *MetricMetaLoader) SaveNamespace(ctx context.Context, value format.Names event := tlmetadata.Event{} err = l.client.EditEntitynew(ctx, editMetricReq, nil, &event) if err != nil { - return format.NamespaceMeta{}, fmt.Errorf("failed to edit namespace: %w", err) + return format.NamespaceMeta{}, wrapSaveEntityError(err) } if event.Id < math.MinInt32 || event.Id > math.MaxInt32 { return g, fmt.Errorf("namespace ID %d assigned by metaengine does not fit into int32 for group %q", event.Id, event.Name) @@ -260,7 +276,7 @@ func (l *MetricMetaLoader) SaveMetric(ctx context.Context, value format.MetricMe event := tlmetadata.Event{} err = l.client.EditEntitynew(ctx, editMetricReq, nil, &event) if err != nil { - return m, fmt.Errorf("failed to edit metric: %w", err) + return m, wrapSaveEntityError(err) } if event.Id < math.MinInt32 || event.Id > math.MaxInt32 { return m, fmt.Errorf("metric ID %d assigned by metaengine does not fit into int32 for metric %q", event.Id, event.Name)