tenancy

package
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Mar 29, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package tenancy implements multi-tenant data isolation modules and steps.

Index

Constants

View Source
const (
	TierRowLevel        = "row_level"
	TierSchemaPerTenant = "schema_per_tenant"
	TierDBPerTenant     = "db_per_tenant"
)

Tier constants for the three supported isolation levels.

Variables

This section is empty.

Functions

func NewDemoteStep

func NewDemoteStep(name string, _ map[string]any) (sdk.StepInstance, error)

NewDemoteStep creates a step.tenant_demote instance.

func NewDeprovisionStep

func NewDeprovisionStep(name string, config map[string]any) (sdk.StepInstance, error)

NewDeprovisionStep creates a step.tenant_deprovision instance.

func NewEvaluatePromotionStep

func NewEvaluatePromotionStep(name string, _ map[string]any) (sdk.StepInstance, error)

NewEvaluatePromotionStep creates a step.tenant_evaluate_promotion instance.

func NewMigrateStep

func NewMigrateStep(name string, config map[string]any) (sdk.StepInstance, error)

NewMigrateStep creates a step.tenant_migrate instance.

func NewPromoteStep

func NewPromoteStep(name string, _ map[string]any) (sdk.StepInstance, error)

NewPromoteStep creates a step.tenant_promote instance.

func NewProvisionStep

func NewProvisionStep(name string, config map[string]any) (sdk.StepInstance, error)

NewProvisionStep creates a step.tenant_provision instance. Config must include "strategy" and any strategy-specific fields.

func NewTenancyModule

func NewTenancyModule(name string, config map[string]any) (sdk.ModuleInstance, error)

NewTenancyModule creates a new data.tenancy module instance.

func TenancyModuleSchema

func TenancyModuleSchema() sdk.ModuleSchemaData

TenancyModuleSchema returns the UI schema definition for the data.tenancy module.

Types

type DBPerTenant

type DBPerTenant struct {
	// contains filtered or unexported fields
}

DBPerTenant isolates each tenant in its own database. A connection template uses "{{tenant}}" as a placeholder for the tenant ID.

func NewDBPerTenant

func NewDBPerTenant(exec SQLExecutor) *DBPerTenant

NewDBPerTenant creates a DBPerTenant strategy.

func (*DBPerTenant) DeprovisionTenant

func (d *DBPerTenant) DeprovisionTenant(ctx context.Context, tenantID string, mode string) error

DeprovisionTenant archives or drops the tenant's database. mode "archive" renames the database; mode "delete" drops it.

func (*DBPerTenant) ProvisionTenant

func (d *DBPerTenant) ProvisionTenant(ctx context.Context, tenantID string) error

ProvisionTenant executes CREATE DATABASE for the tenant.

func (*DBPerTenant) ResolveConnection

func (d *DBPerTenant) ResolveConnection(tenantID, baseConnection string) string

ResolveConnection replaces "{{tenant}}" in the connection template with the tenant ID.

func (*DBPerTenant) ResolveTable

func (d *DBPerTenant) ResolveTable(tenantID, table string) string

ResolveTable returns the table unchanged — tenant is isolated at the DB level.

func (*DBPerTenant) TenantFilter

func (d *DBPerTenant) TenantFilter(tenantID string) (string, string)

TenantFilter returns empty strings — isolation is via database, not row filtering.

type PromotionDB

type PromotionDB interface {
	ExecContext(ctx context.Context, query string, args ...any) (sql.Result, error)
	QueryRowContext(ctx context.Context, query string, args ...any) *sql.Row
}

PromotionDB is the minimal database interface required by promotion steps. *sql.DB satisfies this interface, enabling sqlmock injection in tests.

type PromotionEvaluator

type PromotionEvaluator struct {
	Thresholds map[string]float64
}

PromotionEvaluator compares tenant metrics against configured thresholds and recommends the next isolation tier when any threshold is exceeded.

func (*PromotionEvaluator) Evaluate

func (e *PromotionEvaluator) Evaluate(tenantID, currentTier string, metrics map[string]float64) PromotionResult

Evaluate returns a promotion recommendation for the tenant. It iterates over metrics and returns as soon as a threshold is exceeded.

type PromotionResult

type PromotionResult struct {
	TenantID        string             `json:"tenant_id"`
	CurrentTier     string             `json:"current_tier"`
	RecommendedTier string             `json:"recommended_tier"`
	ShouldPromote   bool               `json:"should_promote"`
	Reason          string             `json:"reason"`
	Metrics         map[string]float64 `json:"metrics"`
}

PromotionResult holds the outcome of a promotion evaluation.

type RowLevel

type RowLevel struct {
	// contains filtered or unexported fields
}

RowLevel isolates tenants via a tenant ID column in shared tables. All tables are shared; queries must include a WHERE clause filtering by tenant.

func NewRowLevel

func NewRowLevel(tenantColumn string, tables []string, exec SQLExecutor) *RowLevel

NewRowLevel creates a RowLevel strategy. tenantColumn is the column used for tenant filtering. tables is the list of tenant-scoped tables (used only in DeprovisionTenant delete mode).

func (*RowLevel) DeprovisionTenant

func (r *RowLevel) DeprovisionTenant(ctx context.Context, tenantID string, mode string) error

DeprovisionTenant deletes all rows belonging to the tenant (mode "delete"). mode "archive" is a no-op for row-level isolation — caller must handle archiving.

func (*RowLevel) ProvisionTenant

func (r *RowLevel) ProvisionTenant(_ context.Context, _ string) error

ProvisionTenant is a no-op for row-level isolation (shared tables need no setup).

func (*RowLevel) ResolveConnection

func (r *RowLevel) ResolveConnection(tenantID, baseConnection string) string

ResolveConnection returns the base connection unchanged — shared database.

func (*RowLevel) ResolveTable

func (r *RowLevel) ResolveTable(tenantID, table string) string

ResolveTable returns the table unchanged — shared tables, no schema prefix.

func (*RowLevel) TenantFilter

func (r *RowLevel) TenantFilter(tenantID string) (string, string)

TenantFilter returns the tenant column and tenant ID for WHERE clause injection.

type SQLExecutor

type SQLExecutor func(ctx context.Context, sql string, args ...any) error

SQLExecutor runs a SQL statement against an admin database connection. args holds query parameters for parameterized statements (e.g. $1, $2).

type SchemaPerTenant

type SchemaPerTenant struct {
	// contains filtered or unexported fields
}

SchemaPerTenant isolates each tenant in its own database schema. Tables are prefixed with "{prefix}{tenantID}." and the shared admin connection is used for all tenants.

func NewSchemaPerTenant

func NewSchemaPerTenant(prefix string, exec SQLExecutor) *SchemaPerTenant

NewSchemaPerTenant creates a SchemaPerTenant strategy. prefix is prepended to the tenant ID to form the schema name (e.g. "t_" → "t_acme").

func (*SchemaPerTenant) DeprovisionTenant

func (s *SchemaPerTenant) DeprovisionTenant(ctx context.Context, tenantID string, mode string) error

DeprovisionTenant archives or drops the tenant's schema. mode "archive" renames the schema; mode "delete" drops it with CASCADE.

func (*SchemaPerTenant) ProvisionTenant

func (s *SchemaPerTenant) ProvisionTenant(ctx context.Context, tenantID string) error

ProvisionTenant executes CREATE SCHEMA IF NOT EXISTS for the tenant.

func (*SchemaPerTenant) ResolveConnection

func (s *SchemaPerTenant) ResolveConnection(tenantID, baseConnection string) string

ResolveConnection returns the base connection unchanged (shared DB, schema-based isolation).

func (*SchemaPerTenant) ResolveTable

func (s *SchemaPerTenant) ResolveTable(tenantID, table string) string

ResolveTable returns "{prefix}{tenantID}.{table}".

func (*SchemaPerTenant) TenantFilter

func (s *SchemaPerTenant) TenantFilter(tenantID string) (string, string)

TenantFilter returns empty strings — isolation is via schema, not row filtering.

type TenancyConfig

type TenancyConfig struct {
	Strategy           string   `json:"strategy"            yaml:"strategy"`
	TenantKeyPath      string   `json:"tenant_key"          yaml:"tenant_key"`
	SchemaPrefix       string   `json:"schema_prefix"       yaml:"schema_prefix"`
	ConnectionTemplate string   `json:"connection_template" yaml:"connection_template"`
	TenantColumn       string   `json:"tenant_column"       yaml:"tenant_column"`
	Tables             []string `json:"tables"              yaml:"tables"`
}

TenancyConfig holds configuration for the data.tenancy module.

type TenancyModule

type TenancyModule struct {
	// contains filtered or unexported fields
}

TenancyModule is a data.tenancy module that manages tenant isolation via a pluggable strategy.

func (*TenancyModule) Init

func (m *TenancyModule) Init() error

Init validates the tenancy module configuration.

func (*TenancyModule) Start

func (m *TenancyModule) Start(_ context.Context) error

Start activates the module (no-op: strategies use injected executors).

func (*TenancyModule) Stop

func (m *TenancyModule) Stop(_ context.Context) error

Stop deactivates the module.

func (*TenancyModule) Strategy

func (m *TenancyModule) Strategy() TenancyStrategy

Strategy returns the active TenancyStrategy.

func (*TenancyModule) TenantKey

func (m *TenancyModule) TenantKey() string

TenantKey returns the dot-path used to resolve the tenant ID from pipeline context.

type TenancyStrategy

type TenancyStrategy interface {
	// ResolveTable returns the fully-qualified table reference for a given tenant.
	ResolveTable(tenantID, table string) string

	// ResolveConnection returns the connection string for a given tenant,
	// potentially replacing a template placeholder with the tenant ID.
	ResolveConnection(tenantID, baseConnection string) string

	// TenantFilter returns the column and value to filter by for row-level isolation.
	// Returns empty strings when the strategy uses schema or DB isolation.
	TenantFilter(tenantID string) (column, value string)

	// ProvisionTenant creates the tenant's namespace (schema, database, etc.).
	ProvisionTenant(ctx context.Context, tenantID string) error

	// DeprovisionTenant removes or archives the tenant's namespace.
	// mode is "archive" (rename/retain data) or "delete" (destroy data).
	DeprovisionTenant(ctx context.Context, tenantID string, mode string) error
}

TenancyStrategy defines how multi-tenant isolation is implemented. Each strategy controls table resolution, connection routing, tenant filtering, and tenant lifecycle SQL for a specific isolation model.

Jump to

Keyboard shortcuts

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