Skip to content

Commit

Permalink
perf: refactor middleware
Browse files Browse the repository at this point in the history
BREAKING CHANGE: Added native echo context support for echo middleware instead of calling the net/http middleware. Added the ExtractDomain function which is in sync with the regex check of the SchemaName field of the TenantModel. Renamed the context package to tenantcontext. Further added unit tests for all examples.
  • Loading branch information
bartventer committed Feb 8, 2024
1 parent e955618 commit b93e51c
Show file tree
Hide file tree
Showing 26 changed files with 1,422 additions and 340 deletions.
31 changes: 20 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# gorm-multitenancy

[![Go Reference](https://pkg.go.dev/badge/github.com/bartventer/gorm-multitenancy.svg)](https://pkg.go.dev/github.com/bartventer/gorm-multitenancy/v2)
[![Go Reference](https://pkg.go.dev/badge/github.com/bartventer/gorm-multitenancy.svg)](https://pkg.go.dev/github.com/bartventer/gorm-multitenancy/v3)
[![Release](https://img.shields.io/github/release/bartventer/gorm-multitenancy.svg)](https://github.com/bartventer/gorm-multitenancy/releases/latest)
[![Go Report Card](https://goreportcard.com/badge/github.com/bartventer/gorm-multitenancy)](https://goreportcard.com/report/github.com/bartventer/gorm-multitenancy)
[![Coverage Status](https://coveralls.io/repos/github/bartventer/gorm-multitenancy/badge.svg?branch=master)](https://coveralls.io/github/bartventer/gorm-multitenancy?branch=master)
Expand Down Expand Up @@ -43,7 +43,7 @@ This package includes middleware that can be utilized with the routers listed be
## Installation

```bash
go get -u github.com/bartventer/gorm-multitenancy/v2
go get -u github.com/bartventer/gorm-multitenancy/v3
```

## Usage
Expand All @@ -54,36 +54,45 @@ go get -u github.com/bartventer/gorm-multitenancy/v2
- The driver uses the `public` schema for public models and the tenant specific schema for tenant specific models
- All models must implement the `gorm.Tabler` interface
- The table name for public models must be prefixed with `public.` (e.g. `public.books`), whereas the table name for tenant specific models must not contain any prefix (e.g. only `books`)
- All tenant specific models must implement the [TenantTabler](https://pkg.go.dev/github.com/bartventer/gorm-multitenancy/v2/#TenantTabler) interface, which classifies the model as a tenant specific model:
- All tenant specific models must implement the [TenantTabler](https://pkg.go.dev/github.com/bartventer/gorm-multitenancy/v3/#TenantTabler) interface, which classifies the model as a tenant specific model:
- The `TenantTabler` interface has a single method `IsTenantTable() bool` which returns `true` if the model is tenant specific and `false` otherwise
- The `TenantTabler` interface is used to determine which models to migrate when calling `MigratePublicSchema` or `CreateSchemaForTenant`
- Models can be registered in two ways:
<<<<<<< HEAD
- When creating the dialect, by passing the models as variadic arguments to [`postgres.New`](https://pkg.go.dev/github.com/bartventer/gorm-multitenancy/v2/drivers/postgres#New) (e.g. `postgres.New(postgres.Config{...}, &Book{}, &Tenant{})`) or by calling [`postgres.Open`](https://pkg.go.dev/github.com/bartventer/gorm-multitenancy/v2/drivers/postgres#Open) (e.g. `postgres.Open("postgres://...", &Book{}, &Tenant{})`)
- By calling [`postgres.RegisterModels`](https://pkg.go.dev/github.com/bartventer/gorm-multitenancy/v2/drivers/postgres#RegisterModels) (e.g. `postgres.RegisterModels(db, &Book{}, &Tenant{})`)
- Migrations can be performed in two ways (after registering the models):
- By calling [`MigratePublicSchema`](https://pkg.go.dev/github.com/bartventer/gorm-multitenancy/v2/drivers/postgres#MigratePublicSchema) to create the public schema and migrate all public models
- By calling [`CreateSchemaForTenant`](https://pkg.go.dev/github.com/bartventer/gorm-multitenancy/v2/drivers/postgres#CreateSchemaForTenant) to create the schema for the tenant and migrate all tenant specific models
- To drop a tenant schema, call [`DropSchemaForTenant`](https://pkg.go.dev/github.com/bartventer/gorm-multitenancy/v2/drivers/postgres#DropSchemaForTenant); this will drop the schema and all tables in the schema
=======
- When creating the dialect, by passing the models as variadic arguments to [`postgres.New`]((https://pkg.go.dev/github.com/bartventer/gorm-multitenancy/v3/drivers/postgres#New)) (e.g. `postgres.New(postgres.Config{...}, &Book{}, &Tenant{})`) or by calling [`postgres.Open`]((https://pkg.go.dev/github.com/bartventer/gorm-multitenancy/v3/drivers/postgres#Open)) (e.g. `postgres.Open("postgres://...", &Book{}, &Tenant{})`)
- By calling [`postgres.RegisterModels`]((https://pkg.go.dev/github.com/bartventer/gorm-multitenancy/v3/drivers/postgres#RegisterModels)) (e.g. `postgres.RegisterModels(db, &Book{}, &Tenant{})`)
- Migrations can be performed in two ways (after registering the models):
- By calling [`MigratePublicSchema`]((https://pkg.go.dev/github.com/bartventer/gorm-multitenancy/v3/drivers/postgres#MigratePublicSchema)) to create the public schema and migrate all public models
- By calling [`CreateSchemaForTenant`](https://pkg.go.dev/github.com/bartventer/gorm-multitenancy/v3/drivers/postgres#CreateSchemaForTenant) to create the schema for the tenant and migrate all tenant specific models
- To drop a tenant schema, call [`DropSchemaForTenant`](https://pkg.go.dev/github.com/bartventer/gorm-multitenancy/v3/drivers/postgres#DropSchemaForTenant); this will drop the schema and all tables in the schema
>>>>>>> 88b3dbd (perf: refactor middleware)
#### Foreign Key Constraints
- Conforming to the [above conventions](#conventions), foreign key constraints between public and tenant specific models can be created just as if you were using approach 1 (shared database, shared schema).
- The easiest way to get this working is to embed the [postgres.TenantModel](https://pkg.go.dev/github.com/bartventer/gorm-multitenancy/v2/drivers/postgres#TenantModel) struct in your tenant model. This will add the necessary fields for the tenant model (e.g. `DomainURL` and `SchemaName`), you can then create a foreign key constraint between the public and tenant specific models using the `SchemaName` field as the foreign key (e.g. `gorm:"foreignKey:TenantSchema;references:SchemaName"`); off course, you can also create foreign key constraints between any other fields in the models.
- The easiest way to get this working is to embed the [postgres.TenantModel](https://pkg.go.dev/github.com/bartventer/gorm-multitenancy/v3/drivers/postgres#TenantModel) struct in your tenant model. This will add the necessary fields for the tenant model (e.g. `DomainURL` and `SchemaName`), you can then create a foreign key constraint between the public and tenant specific models using the `SchemaName` field as the foreign key (e.g. `gorm:"foreignKey:TenantSchema;references:SchemaName"`); off course, you can also create foreign key constraints between any other fields in the models.

#### Operations on Tenant-Specific Models

Outlined below are two approaches to perform operations on tenant specific models. The first approach is for simple operations on tenant specific models, whereas the second approach is for more complex operations on tenant specific models, but does add ~0.200ms overhead per operation.
| Function | Description |
| --- | --- |
| [`WithTenantSchema`](https://pkg.go.dev/github.com/bartventer/gorm-multitenancy/v2/scopes#WithTenantSchema) | Use this scope function when you want to perform operations on a tenant table, which may include foreign key constraints to a public schema table(s). |
| [`SetSearchPath`](https://pkg.go.dev/github.com/bartventer/gorm-multitenancy/v2/schema/postgres#SetSearchPath) | Use this function when the tenant schema table has foreign key constraints you want to access belonging to other tables in the same tenant schema (and or foreign key relations to public tables). |
| [`WithTenantSchema`](https://pkg.go.dev/github.com/bartventer/gorm-multitenancy/v3/scopes#WithTenantSchema) | Use this scope function when you want to perform operations on a tenant table, which may include foreign key constraints to a public schema table(s). |
| [`SetSearchPath`](https://pkg.go.dev/github.com/bartventer/gorm-multitenancy/v3/schema/postgres#SetSearchPath) | Use this function when the tenant schema table has foreign key constraints you want to access belonging to other tables in the same tenant schema (and or foreign key relations to public tables). |

#### Basic example
For a complete example refer to the [examples](#examples) section)
```go

import (
"gorm.io/gorm"
"github.com/bartventer/gorm-multitenancy/v2/drivers/postgres"
"github.com/bartventer/gorm-multitenancy/v3/drivers/postgres"
)

// For models that are tenant specific, ensure that TenantTabler is implemented
Expand Down Expand Up @@ -182,8 +191,8 @@ func main(){
For a complete example refer to the [PostgreSQL with echo](https://github.com/bartventer/gorm-multitenancy/tree/master/internal/examples/echo) example.
```go
import (
multitenancymw "github.com/bartventer/gorm-multitenancy/v2/middleware/echo"
"github.com/bartventer/gorm-multitenancy/v2/scopes"
multitenancymw "github.com/bartventer/gorm-multitenancy/v3/middleware/echo"
"github.com/bartventer/gorm-multitenancy/v3/scopes"
"github.com/labstack/echo/v4"
// ...
)
Expand Down Expand Up @@ -227,8 +236,8 @@ import (
"net/http"

"github.com/go-chi/chi/v5"
multitenancymw "github.com/bartventer/gorm-multitenancy/v2/middleware/nethttp"
"github.com/bartventer/gorm-multitenancy/v2/scopes"
multitenancymw "github.com/bartventer/gorm-multitenancy/v3/middleware/nethttp"
"github.com/bartventer/gorm-multitenancy/v3/scopes"
// ...
)

Expand Down
26 changes: 0 additions & 26 deletions context/context.go

This file was deleted.

2 changes: 1 addition & 1 deletion drivers/postgres/interfaces.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package postgres

import (
multitenancy "github.com/bartventer/gorm-multitenancy/v2"
multitenancy "github.com/bartventer/gorm-multitenancy/v3"
)

// MultitenancyMigrator is the interface for the postgres migrator with multitenancy support
Expand Down
9 changes: 5 additions & 4 deletions drivers/postgres/migrator.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ import (
"fmt"
"sync"

multicontext "github.com/bartventer/gorm-multitenancy/v2/context"
multicontext "github.com/bartventer/gorm-multitenancy/v3/tenantcontext"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)

const (
PublicSchemaName = "public" // PublicSchemaName is the name of the public schema
// PublicSchemaName is the name of the public schema
PublicSchemaName = "public"
)

type multitenancyMigrationOption uint
Expand Down Expand Up @@ -94,7 +95,7 @@ func (m *Migrator) MigratePublicSchema() error {

// AutoMigrate migrates the tables based on the migration options.
func (m Migrator) AutoMigrate(values ...interface{}) error {
v, ok := m.DB.Get(multicontext.MultitenantMigrationOptions.String())
v, ok := m.DB.Get(multicontext.MigrationOptions.String())
if !ok {
return errors.New("no migration options found")
}
Expand Down Expand Up @@ -127,7 +128,7 @@ func (m *Migrator) DropSchemaForTenant(tenant string) error {

func withMigrationOption(option multitenancyMigrationOption) func(*gorm.DB) *gorm.DB {
return func(db *gorm.DB) *gorm.DB {
return db.Set(multicontext.MultitenantMigrationOptions.String(), option)
return db.Set(multicontext.MigrationOptions.String(), option)
}
}

Expand Down
4 changes: 2 additions & 2 deletions drivers/postgres/migrator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import (
"sync"
"testing"

multitenancy "github.com/bartventer/gorm-multitenancy/v2"
"github.com/bartventer/gorm-multitenancy/v2/internal"
multitenancy "github.com/bartventer/gorm-multitenancy/v3"
"github.com/bartventer/gorm-multitenancy/v3/internal"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
Expand Down
2 changes: 1 addition & 1 deletion drivers/postgres/model_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package postgres
import (
"testing"

"github.com/bartventer/gorm-multitenancy/v2/internal"
"github.com/bartventer/gorm-multitenancy/v3/internal"
"gorm.io/gorm"
)

Expand Down
2 changes: 1 addition & 1 deletion drivers/postgres/postgres.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"strings"
"sync"

multitenancy "github.com/bartventer/gorm-multitenancy/v2"
multitenancy "github.com/bartventer/gorm-multitenancy/v3"
"gorm.io/driver/postgres"
"gorm.io/gorm"
"gorm.io/gorm/migrator"
Expand Down
4 changes: 2 additions & 2 deletions drivers/postgres/postgres_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import (
"sync"
"testing"

multitenancy "github.com/bartventer/gorm-multitenancy/v2"
"github.com/bartventer/gorm-multitenancy/v2/internal"
multitenancy "github.com/bartventer/gorm-multitenancy/v3"
"github.com/bartventer/gorm-multitenancy/v3/internal"
"gorm.io/driver/postgres"
"gorm.io/gorm"
"gorm.io/gorm/migrator"
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module github.com/bartventer/gorm-multitenancy/v2
module github.com/bartventer/gorm-multitenancy/v3

go 1.21.5

Expand Down
Loading

0 comments on commit b93e51c

Please sign in to comment.