Skip to content

Commit

Permalink
Refactored data package to support postgresql and cockroach db. This …
Browse files Browse the repository at this point in the history
…includes breaking changes.

1. Updated db example, added example for translating unique constraint violation.
2. Refactored db package (breaking change):
  a. Introduced postgresql package.
  b. The cockroach package is moved under the postgresql package as a postgresql extension.
  c. Removed database specific packages from the data package. Code that uses db specific driver packages are moved into sub packages for that database. i.e. types/pqx.
  d. The db connection property is moved to data.db from data.cockroach
3. Updated tenancy and opa tests to have coverage for both postgresql and cockroach db
  • Loading branch information
TimShi committed May 9, 2024
1 parent 5e5bd40 commit cbead8e
Show file tree
Hide file tree
Showing 56 changed files with 5,623 additions and 2,907 deletions.
2 changes: 1 addition & 1 deletion examples/database/configs/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ data:
logging:
level: warn
slow-threshold: 5s
cockroach:
db:
host: ${db.cockroach.host:localhost}
port: ${db.cockroach.port:26257}
sslmode: ${db.cockroach.sslmode:disable}
Expand Down
62 changes: 62 additions & 0 deletions examples/database/pkg/controller/errorhandling/data_integrity.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package errorhandling

import (
"context"
"errors"
"fmt"
"github.com/cisco-open/go-lanai/pkg/data"
"github.com/cisco-open/go-lanai/pkg/data/repo"
"gorm.io/gorm"
"strings"
)

// TranslateDataIntegrityError used for translating data integrity error (especially duplicate keys error)
// to an error with sensible message
func TranslateDataIntegrityError(ctx context.Context, err error) error {
//nolint:errorlint // intended, we ignore wrapped error
de, ok := err.(data.DataError)
if !ok || !errors.Is(err, data.ErrorCategoryData) {
return err
}

var msg string
switch {
case errors.Is(err, data.ErrorDuplicateKey):
msg = translateDuplicateKeyMessage(ctx, de)
default:
return err
}
return de.WithMessage(msg)
}

func translateDuplicateKeyMessage(ctx context.Context, err data.DataError) string {
// resolve duplicated fields
model := extractModel(ctx, err)
dups, e := repo.Utils().CheckUniqueness(ctx, model)
switch {
case errors.Is(e, data.ErrorDuplicateKey):
default:
return err.Error()
}
pairs := make([]string, 0, len(dups))
for k, v := range dups {
pairs = append(pairs, fmt.Sprintf(`%s: "%v"`, k, v))
}

// resolve model name
resolver, e := repo.Utils().ResolveSchema(ctx, model)
if e != nil {
return e.Error()
}

return fmt.Sprintf("%s already exists with [%s]", resolver.ModelName(), strings.Join(pairs, ", "))
}

func extractModel(_ context.Context, err data.DataError) interface{} {
switch details := err.Details().(type) {
case *gorm.Statement:
return details.Model
default:
return nil
}
}
33 changes: 33 additions & 0 deletions examples/database/pkg/controller/errorhandling/package.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package errorhandling

import (
"github.com/cisco-open/go-lanai/pkg/bootstrap"
"github.com/cisco-open/go-lanai/pkg/utils/order"
"github.com/cisco-open/go-lanai/pkg/web"
"github.com/cisco-open/go-lanai/pkg/web/matcher"
"github.com/cisco-open/go-lanai/pkg/web/weberror"
"go.uber.org/fx"
)

// error pkg register

const (
_ = order.Lowest - 0xffff + iota
OrderDataIntegrityError
)

func Use() {
bootstrap.AddOptions(
fx.Invoke(registerErrorTranslators),
)
}

func registerErrorTranslators(r *web.Registrar) {
// data integrity errors, covers all APIs
r.MustRegister(weberror.New("data integrity").
Order(OrderDataIntegrityError).
ApplyTo(matcher.RouteWithPattern("/api/**")).
Use(TranslateDataIntegrityError).
Build(),
)
}
5 changes: 3 additions & 2 deletions examples/database/pkg/init/package.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ package serviceinit

import (
"github.com/cisco-open/go-lanai/examples/skeleton-service/pkg/controller"
"github.com/cisco-open/go-lanai/examples/skeleton-service/pkg/controller/errorhandling"
"github.com/cisco-open/go-lanai/examples/skeleton-service/pkg/repository"
actuator "github.com/cisco-open/go-lanai/pkg/actuator/init"
appconfig "github.com/cisco-open/go-lanai/pkg/appconfig/init"
"github.com/cisco-open/go-lanai/pkg/bootstrap"
"github.com/cisco-open/go-lanai/pkg/data/cockroach"
data "github.com/cisco-open/go-lanai/pkg/data/init"
"github.com/cisco-open/go-lanai/pkg/data/postgresql/cockroach"
"github.com/cisco-open/go-lanai/pkg/redis"
"github.com/cisco-open/go-lanai/pkg/security"
"github.com/cisco-open/go-lanai/pkg/security/config/resserver"
Expand Down Expand Up @@ -63,6 +64,6 @@ func Use() {
for _, m := range controller.SubModules {
bootstrap.Register(m)
}

errorhandling.Use()
repository.Use()
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ DROP TABLE IF EXISTS "public"."users";
CREATE TABLE friends
(
id UUID NOT NULL DEFAULT gen_random_uuid(),
first_name STRING NOT NULL,
last_name STRING NOT NULL,
CONSTRAINT "primary" PRIMARY KEY (id ASC)
);
first_name TEXT NOT NULL,
last_name TEXT NOT NULL,
CONSTRAINT "primary" PRIMARY KEY (id)
);
CREATE UNIQUE INDEX IF NOT EXISTS idx_friends_name ON friends (first_name, last_name);
20 changes: 10 additions & 10 deletions examples/database/pkg/migrate/package.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
package migrate

import (
"embed"
"github.com/cisco-open/go-lanai/examples/skeleton-service/pkg/migrate/migration_v1"
appconfig "github.com/cisco-open/go-lanai/pkg/appconfig/init"
"github.com/cisco-open/go-lanai/pkg/bootstrap"
"github.com/cisco-open/go-lanai/pkg/data"
"github.com/cisco-open/go-lanai/pkg/data/cockroach"
datainit "github.com/cisco-open/go-lanai/pkg/data/init"
"github.com/cisco-open/go-lanai/pkg/migration"
"go.uber.org/fx"
"gorm.io/gorm"
"embed"
"github.com/cisco-open/go-lanai/examples/skeleton-service/pkg/migrate/migration_v1"
appconfig "github.com/cisco-open/go-lanai/pkg/appconfig/init"
"github.com/cisco-open/go-lanai/pkg/bootstrap"
"github.com/cisco-open/go-lanai/pkg/data"
datainit "github.com/cisco-open/go-lanai/pkg/data/init"
"github.com/cisco-open/go-lanai/pkg/data/postgresql/cockroach"
"github.com/cisco-open/go-lanai/pkg/migration"
"go.uber.org/fx"
"gorm.io/gorm"
)

//go:embed application-migrate.yml
Expand Down
4 changes: 2 additions & 2 deletions examples/database/pkg/model/friend.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ import "github.com/google/uuid"

type Friend struct {
ID uuid.UUID `gorm:"column:id;primary_key;type:UUID;default:gen_random_uuid();"`
FirstName string `gorm:"column:first_name;type:text;not null;"`
LastName string `gorm:"column:last_name;type:text;not null;"`
FirstName string `gorm:"column:first_name;uniqueIndex:idx_friends_name;type:text;not null;"`
LastName string `gorm:"column:last_name;uniqueIndex:idx_friends_name;type:text;not null;"`
}
62 changes: 0 additions & 62 deletions pkg/data/cassandra/package.go

This file was deleted.

58 changes: 0 additions & 58 deletions pkg/data/cassandra/properties.go

This file was deleted.

46 changes: 0 additions & 46 deletions pkg/data/cockroach/db_creator.go

This file was deleted.

Loading

0 comments on commit cbead8e

Please sign in to comment.