Documentation
¶
Overview ¶
Package tenancy implements multi-tenant data isolation modules and steps.
Index ¶
- Constants
- func NewDemoteStep(name string, _ map[string]any) (sdk.StepInstance, error)
- func NewDeprovisionStep(name string, config map[string]any) (sdk.StepInstance, error)
- func NewEvaluatePromotionStep(name string, _ map[string]any) (sdk.StepInstance, error)
- func NewMigrateStep(name string, config map[string]any) (sdk.StepInstance, error)
- func NewPromoteStep(name string, _ map[string]any) (sdk.StepInstance, error)
- func NewProvisionStep(name string, config map[string]any) (sdk.StepInstance, error)
- func NewTenancyModule(name string, config map[string]any) (sdk.ModuleInstance, error)
- func TenancyModuleSchema() sdk.ModuleSchemaData
- type DBPerTenant
- func (d *DBPerTenant) DeprovisionTenant(ctx context.Context, tenantID string, mode string) error
- func (d *DBPerTenant) ProvisionTenant(ctx context.Context, tenantID string) error
- func (d *DBPerTenant) ResolveConnection(tenantID, baseConnection string) string
- func (d *DBPerTenant) ResolveTable(tenantID, table string) string
- func (d *DBPerTenant) TenantFilter(tenantID string) (string, string)
- type PromotionDB
- type PromotionEvaluator
- type PromotionResult
- type RowLevel
- func (r *RowLevel) DeprovisionTenant(ctx context.Context, tenantID string, mode string) error
- func (r *RowLevel) ProvisionTenant(_ context.Context, _ string) error
- func (r *RowLevel) ResolveConnection(tenantID, baseConnection string) string
- func (r *RowLevel) ResolveTable(tenantID, table string) string
- func (r *RowLevel) TenantFilter(tenantID string) (string, string)
- type SQLExecutor
- type SchemaPerTenant
- func (s *SchemaPerTenant) DeprovisionTenant(ctx context.Context, tenantID string, mode string) error
- func (s *SchemaPerTenant) ProvisionTenant(ctx context.Context, tenantID string) error
- func (s *SchemaPerTenant) ResolveConnection(tenantID, baseConnection string) string
- func (s *SchemaPerTenant) ResolveTable(tenantID, table string) string
- func (s *SchemaPerTenant) TenantFilter(tenantID string) (string, string)
- type TenancyConfig
- type TenancyModule
- type TenancyStrategy
Constants ¶
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 ¶
NewDemoteStep creates a step.tenant_demote instance.
func NewDeprovisionStep ¶
NewDeprovisionStep creates a step.tenant_deprovision instance.
func NewEvaluatePromotionStep ¶
NewEvaluatePromotionStep creates a step.tenant_evaluate_promotion instance.
func NewMigrateStep ¶
NewMigrateStep creates a step.tenant_migrate instance.
func NewPromoteStep ¶
NewPromoteStep creates a step.tenant_promote instance.
func NewProvisionStep ¶
NewProvisionStep creates a step.tenant_provision instance. Config must include "strategy" and any strategy-specific fields.
func NewTenancyModule ¶
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 ¶
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 ¶
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 ¶
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 ¶
ProvisionTenant is a no-op for row-level isolation (shared tables need no setup).
func (*RowLevel) ResolveConnection ¶
ResolveConnection returns the base connection unchanged — shared database.
func (*RowLevel) ResolveTable ¶
ResolveTable returns the table unchanged — shared tables, no schema prefix.
type SQLExecutor ¶
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.