dbresolver

package module
v1.5.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 11, 2024 License: MIT Imports: 12 Imported by: 712

README

DBResolver

DBResolver adds multiple databases support to GORM, the following features are supported:

  • Multiple sources, replicas
  • Read/Write Splitting
  • Automatic connection switching based on the working table/struct
  • Manual connection switching
  • Sources/Replicas load balancing
  • Works for RAW SQL
  • Transaction

Quick Start

import (
  "gorm.io/gorm"
  "gorm.io/plugin/dbresolver"
  "gorm.io/driver/mysql"
)

DB, err := gorm.Open(mysql.Open("db1_dsn"), &gorm.Config{})

DB.Use(dbresolver.Register(dbresolver.Config{
  // use `db2` as sources, `db3`, `db4` as replicas
  Sources:  []gorm.Dialector{mysql.Open("db2_dsn")},
  Replicas: []gorm.Dialector{mysql.Open("db3_dsn"), mysql.Open("db4_dsn")},
  // sources/replicas load balancing policy
  Policy: dbresolver.RandomPolicy{},
  // print sources/replicas mode in logger
  ResolverModeReplica: true,
}).Register(dbresolver.Config{
  // use `db1` as sources (DB's default connection), `db5` as replicas for `User`, `Address`
  Replicas: []gorm.Dialector{mysql.Open("db5_dsn")},
}, &User{}, &Address{}).Register(dbresolver.Config{
  // use `db6`, `db7` as sources, `db8` as replicas for `orders`, `Product`
  Sources:  []gorm.Dialector{mysql.Open("db6_dsn"), mysql.Open("db7_dsn")},
  Replicas: []gorm.Dialector{mysql.Open("db8_dsn")},
}, "orders", &Product{}, "secondary"))
Automatic connection switching

DBResolver will automatically switch connections based on the working table/struct

For RAW SQL, DBResolver will extract the table name from the SQL to match the resolver, and will use sources unless the SQL begins with SELECT, for example:

// `User` Resolver Examples
DB.Table("users").Rows() // replicas `db5`
DB.Model(&User{}).Find(&AdvancedUser{}) // replicas `db5`
DB.Exec("update users set name = ?", "jinzhu") // sources `db1`
DB.Raw("select name from users").Row().Scan(&name) // replicas `db5`
DB.Create(&user) // sources `db1`
DB.Delete(&User{}, "name = ?", "jinzhu") // sources `db1`
DB.Table("users").Update("name", "jinzhu") // sources `db1`

// Global Resolver Examples
DB.Find(&Pet{}) // replicas `db3`/`db4`
DB.Save(&Pet{}) // sources `db2`

// Orders Resolver Examples
DB.Find(&Order{}) // replicas `db8`
DB.Table("orders").Find(&Report{}) // replicas `db8`
Read/Write Splitting

Read/Write splitting with DBResolver based on the current using GORM callback.

For Query, Row callback, will use replicas unless Write mode specified For Raw callback, statements are considered read-only and will use replicas if the SQL starts with SELECT

Manual connection switching
// Use Write Mode: read user from sources `db1`
DB.Clauses(dbresolver.Write).First(&user)

// Specify Resolver: read user from `secondary`'s replicas: db8
DB.Clauses(dbresolver.Use("secondary")).First(&user)

// Specify Resolver and Write Mode: read user from `secondary`'s sources: db6 or db7
DB.Clauses(dbresolver.Use("secondary"), dbresolver.Write).First(&user)
Transaction

When using transaction, DBResolver will keep using the transaction and won't switch to sources/replicas based on configuration

But you can specifies which DB to use before starting a transaction, for example:

// Start transaction based on default replicas db
tx := DB.Clauses(dbresolver.Read).Begin()

// Start transaction based on default sources db
tx := DB.Clauses(dbresolver.Write).Begin()

// Start transaction based on `secondary`'s sources
tx := DB.Clauses(dbresolver.Use("secondary"), dbresolver.Write).Begin()
Load Balancing

GORM supports load balancing sources/replicas based on policy, the policy is an interface implements following interface:

type Policy interface {
	Resolve([]gorm.ConnPool) gorm.ConnPool
}

Currently only the RandomPolicy implemented and it is the default option if no policy specified.

Connection Pool
DB.Use(
  dbresolver.Register(dbresolver.Config{ /* xxx */ }).
  SetConnMaxIdleTime(time.Hour).
  SetConnMaxLifetime(24 * time.Hour).
  SetMaxIdleConns(100).
  SetMaxOpenConns(200)
)

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NewResolverModeLogger added in v1.4.0

func NewResolverModeLogger(l logger.Interface) logger.Interface

func Use

func Use(str string) clause.Expression

Use specifies configuration

Types

type Config

type Config struct {
	Sources  []gorm.Dialector
	Replicas []gorm.Dialector
	Policy   Policy

	TraceResolverMode bool
	// contains filtered or unexported fields
}

type DBResolver

type DBResolver struct {
	*gorm.DB
	// contains filtered or unexported fields
}

func Register

func Register(config Config, datas ...interface{}) *DBResolver

func (*DBResolver) Call

func (dr *DBResolver) Call(fc func(connPool gorm.ConnPool) error) error

func (*DBResolver) Initialize

func (dr *DBResolver) Initialize(db *gorm.DB) error

func (*DBResolver) Name

func (dr *DBResolver) Name() string

func (*DBResolver) Register

func (dr *DBResolver) Register(config Config, datas ...interface{}) *DBResolver

func (*DBResolver) SetConnMaxIdleTime

func (dr *DBResolver) SetConnMaxIdleTime(d time.Duration) *DBResolver

func (*DBResolver) SetConnMaxLifetime

func (dr *DBResolver) SetConnMaxLifetime(d time.Duration) *DBResolver

func (*DBResolver) SetMaxIdleConns

func (dr *DBResolver) SetMaxIdleConns(n int) *DBResolver

func (*DBResolver) SetMaxOpenConns

func (dr *DBResolver) SetMaxOpenConns(n int) *DBResolver

type Operation

type Operation string

Operation specifies dbresolver mode

const (
	Write Operation = "write"
	Read  Operation = "read"
)

func (Operation) Build

func (op Operation) Build(clause.Builder)

Build implements clause.Expression interface

func (Operation) ModifyStatement

func (op Operation) ModifyStatement(stmt *gorm.Statement)

ModifyStatement modify operation mode

type Policy

type Policy interface {
	Resolve([]gorm.ConnPool) gorm.ConnPool
}

func RoundRobinPolicy added in v1.5.2

func RoundRobinPolicy() Policy

func StrictRoundRobinPolicy added in v1.5.2

func StrictRoundRobinPolicy() Policy

type PolicyFunc added in v1.5.2

type PolicyFunc func([]gorm.ConnPool) gorm.ConnPool

func (PolicyFunc) Resolve added in v1.5.2

func (f PolicyFunc) Resolve(connPools []gorm.ConnPool) gorm.ConnPool

type RandomPolicy

type RandomPolicy struct {
}

func (RandomPolicy) Resolve

func (RandomPolicy) Resolve(connPools []gorm.ConnPool) gorm.ConnPool

type ResolverMode added in v1.4.0

type ResolverMode string
const (
	ResolverModeSource  ResolverMode = "source"
	ResolverModeReplica ResolverMode = "replica"
)

type ResolverModeKey added in v1.4.0

type ResolverModeKey string

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL