This package contains a set of utilities for famous GORM library. If used together they can significantly help you to enable persistency in your application.
The package provides some helpers which are able to apply collection operators defined in query package to a GORM query.
...
// given that Person is a protobuf message and PersonORM is a corresponding GORM model
db, assoc, err = gorm.ApplyFiltering(ctx, db, filtering, &PersonORM{}, &Person{})
if err != nil {
...
}
// Join required associations(for nested field support)
db, err = gorm.JoinAssociations(ctx, db, assoc, &PersonORM{})
if err != nil {
...
}
var people []Person
db.Find(&people)
...
...
db, assoc, err = gorm.ApplySorting(ctx, db, sorting, &PersonORM{}, &Person{})
if err != nil {
...
}
// Join required associations(for nested field support)
db, err = gorm.JoinAssociations(ctx, db, assoc, &PersonORM{})
if err != nil {
...
}
var people []Person
db.Find(&people)
...
...
db = gorm.ApplyPagination(ctx, db, pagination, &PersonORM{}, &Person{})
if err != nil {
...
}
var people []Person
db.Find(&people)
...
...
db, err = gorm.ApplyFieldSelection(ctx, db, fields, &PersonORM{}, &Person{})
if err != nil {
...
}
var people []Person
db.Find(&people)
...
...
db, err = gorm.ApplyCollectionOperators(ctx, db, &PersonORM{}, &Person{}, filtering, sorting, pagination, fields)
if err != nil {
...
}
var people []Person
db.Find(&people)
...
We provide transaction management by offering gorm.Transaction
wrapper and gorm.UnaryServerInterceptor
.
The gorm.Transaction
works as a singleton to prevent an application of creating more than one transaction instance per incoming request.
The gorm.UnaryServerInterceptor
performs management on transactions.
Interceptor creates new transaction on each incoming request and commits it if request finishes without error, otherwise transaction is aborted.
The created transaction is stored in context.Context
and passed to the request handler as usual.
NOTE Client is responsible to call txn.Begin()
to open transaction.
// add gorm interceptor to the chain
server := grpc.NewServer(
grpc.UnaryInterceptor(
grpc_middleware.ChainUnaryServer( // middleware chain
...
gorm.UnaryServerInterceptor(), // transaction management
...
),
),
)
import (
"github.com/infobloxopen/atlas-app-toolkit/gorm"
)
func (s *MyService) MyMethod(ctx context.Context, req *MyMethodRequest) (*MyMethodResponse, error) {
// extract gorm transaction from context
txn, ok := gorm.FromContext(ctx)
if !ok {
return panic("transaction is not opened") // don't panic in production!
}
// start transaction
gormDB := txn.Begin()
if err := gormDB.Error; err != nil {
return nil, err
}
// do stuff with *gorm.DB
return &MyMethodResponse{...}, nil
}
The toolkit does not require any specific method for database provisioning and setup. However, if golang-migrate or the infobloxopen fork of it is used, a couple helper functions are provided here for verifying that the database version matches a required version without having to import the entire migration package.