Documentation
¶
Overview ¶
Package multitenancy provides PostgreSQL schema-per-tenant support on top of GORM.
It wraps a gorm.DB connection with tenant-aware operations: registering shared and tenant-specific models, migrating them, switching the active tenant schema, and cleaning up a tenant's schema on offboarding. The concrete database behavior is provided by a registered Adapter (see the postgres subpackage).
Index ¶
- Variables
- func Register(name string, adapter Adapter)
- type Adapter
- type DB
- func (db *DB) Begin(opts ...*sql.TxOptions) *DB
- func (db *DB) CurrentTenant(ctx context.Context) string
- func (db *DB) MigrateSharedModels(ctx context.Context) error
- func (db *DB) MigrateTenantModels(ctx context.Context, tenantID string) error
- func (db *DB) OffboardTenant(ctx context.Context, tenantID string) error
- func (db *DB) RegisterModels(ctx context.Context, models ...driver.TenantTabler) error
- func (db *DB) Session(config *gorm.Session) *DB
- func (db *DB) Transaction(fc func(tx *DB) error, opts ...*sql.TxOptions) (err error)
- func (db *DB) UseTenant(ctx context.Context, tenantID string) (reset func() error, err error)
- func (db *DB) WithContext(ctx context.Context) *DB
- func (db *DB) WithTenant(ctx context.Context, tenantID string, fc func(tx *DB) error, ...) (err error)
- type TenantModel
Constants ¶
This section is empty.
Variables ¶
var ( ErrDriverAlreadyRegistered = errors.New("driver already registered") ErrNoRegisteredAdapter = errors.New("no registered adapter for driver") )
Adapter registry errors.
Functions ¶
Types ¶
type Adapter ¶
type Adapter interface {
// AdaptDB enhances an existing [gorm.DB] instance with additional functionalities and returns
// a new [DB] instance. The returned DB instance should be used by a single goroutine at a time
// to ensure thread safety and prevent concurrent access issues.
AdaptDB(ctx context.Context, db *gorm.DB) (*DB, error)
}
Adapter defines an interface for enhancing gorm.DB instances with additional functionalities.
type DB ¶
DB wraps a GORM DB connection, integrating support for multitenancy operations. It provides a unified interface for managing tenant-specific and shared data within a multi-tenant application, leveraging GORM's ORM capabilities for database operations.
func NewDB ¶
NewDB creates a new DB instance using the provided driver.DBFactory and gorm.DB instance. This function is intended for use by Adapter implementations to create new instances of DB with multitenancy support. Not intended for direct use in application code.
func Open ¶
Open is a drop-in replacement for gorm.Open. It returns a new DB instance using the provided dialector (see the postgres subpackage) and options.
import (
gormpg "gorm.io/driver/postgres"
"github.com/openkcm/cmk/internal/multitenancy"
"github.com/openkcm/cmk/internal/multitenancy/postgres"
)
dsn := "postgres://user:password@localhost:5432/dbname?sslmode=disable"
db, err := multitenancy.Open(postgres.New(postgres.Config{Config: gormpg.Config{DSN: dsn}}))
if err != nil {
// handle err
}
func (*DB) CurrentTenant ¶
CurrentTenant returns the identifier for the current tenant context or an empty string if no context is set.
func (*DB) MigrateSharedModels ¶
MigrateSharedModels migrates all registered shared/public models.
Safe for concurrent use by multiple goroutines w.r.t. ensuring data integrity and schema isolation.
func (*DB) MigrateTenantModels ¶
MigrateTenantModels migrates all registered tenant-specific models for the specified tenant. This method is intended to be used when onboarding a new tenant or updating an existing tenant's schema to match the latest model definitions.
Safe for concurrent use by multiple goroutines w.r.t. ensuring data integrity and schema isolation.
func (*DB) OffboardTenant ¶
OffboardTenant cleans up the database by dropping the tenant-specific schema and associated tables. This method is intended to be used after a tenant has been removed.
Safe for concurrent use by multiple goroutines w.r.t. ensuring data integrity and schema isolation.
func (*DB) RegisterModels ¶
RegisterModels registers GORM model structs for multitenancy support, preparing models for tenant-specific operations.
Not safe for concurrent use by multiple goroutines. Call this method from your main function or during application initialization.
func (*DB) Session ¶
Session returns a new copy of the DB, which has a new session with the configuration.
func (*DB) Transaction ¶
Transaction starts a transaction as a block, returns an error if there's any error within the block. If the function passed to tx returns an error, the transaction will be rolled back automatically, otherwise, the transaction will be committed.
func (*DB) UseTenant ¶
UseTenant configures the database for operations specific to a tenant. A reset function is returned to revert the database context to its original state.
Technically safe for concurrent use by multiple goroutines, but should not be used concurrently w.r.t. ensuring data integrity and schema isolation. Either use DB.WithTenant, or ensure that this method is called within a transaction or from its own database connection.
func (*DB) WithContext ¶
WithContext sets the context for the DB.
func (*DB) WithTenant ¶
func (db *DB) WithTenant( ctx context.Context, tenantID string, fc func(tx *DB) error, opts ...*sql.TxOptions, ) (err error)
WithTenant executes the provided function within the context of a specific tenant, ensuring that the database operations are scoped to the tenant's schema. It runs in a transaction that is committed on success and rolled back on error.
Safe for concurrent use by multiple goroutines w.r.t. ensuring data integrity and schema isolation.
type TenantModel ¶
type TenantModel struct {
// DomainURL is the domain URL of the tenant; same as [net/url.URL.Host].
DomainURL string `json:"domainURL" mapstructure:"domainURL" gorm:"column:domain_url;uniqueIndex;size:128"`
// SchemaName is the schema name of the tenant.
//
// Field-level permissions are restricted to read and create.
//
// The following constraints are applied:
// - unique index
// - size: 63
// - check: Not less than 3 characters long
//nolint:lll // gorm struct tags must be a single line; the DB column constraints are load-bearing
SchemaName string `` /* 133-byte string literal not displayed */
}
TenantModel a basic GoLang struct which includes the following fields: DomainURL, SchemaName. It's intended to be embedded into any public model that needs to be scoped to a tenant.
For example:
type Tenant struct {
multitenancy.TenantModel
}
Directories
¶
| Path | Synopsis |
|---|---|
|
Package driver provides the foundational interfaces for implementing multitenancy support within database systems.
|
Package driver provides the foundational interfaces for implementing multitenancy support within database systems. |
|
Package logext provides a custom logger that logs messages to the provided output.
|
Package logext provides a custom logger that logs messages to the provided output. |
|
Package migrator provides utilities for database migration management.
|
Package migrator provides utilities for database migration management. |
|
Package namespace provides utilities for validating tenant names in a consistent manner across different database systems.
|
Package namespace provides utilities for validating tenant names in a consistent manner across different database systems. |
|
Package postgres provides a gorm.Dialector implementation for PostgreSQL databases to support multitenancy in GORM applications, enabling tenant-specific operations and shared resources management using the "shared database, separate schemas" approach.
|
Package postgres provides a gorm.Dialector implementation for PostgreSQL databases to support multitenancy in GORM applications, enabling tenant-specific operations and shared resources management using the "shared database, separate schemas" approach. |