tenant

package
v0.16.13 Latest Latest
Warning

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

Go to latest
Published: Jul 21, 2026 License: Apache-2.0 Imports: 3 Imported by: 0

Documentation

Overview

Package tenant provides tenant-scoping helpers for the middle and handler tiers.

The storage tier enforces isolation by construction (see storage.StoreConfig). This package provides the supporting utilities that other tiers need:

  • NodeID / CacheKey: construct globally-unique identifiers when a shared in-memory structure (graph, cache) spans multiple tenants.
  • Registry: maps human-readable tenant names to uint16 identifiers. When a Persister is attached, mappings are durable across restarts.

Index

Constants

View Source
const (
	// TenantsTable is the tenant registry table. One per database file.
	TenantsTable = "tenants"

	// SchemaVersionTable tracks applied migrations. One per database file.
	SchemaVersionTable = "schema_version"
)

Variables

This section is empty.

Functions

func AdaptedEdgeIndexField

func AdaptedEdgeIndexField(tenantID uint16, relType, field string) string

AdaptedEdgeIndexField returns a field index name on an adapted edge table. Example: idx_t0001_edata_KNOWS_since

func AdaptedEdgeTableName

func AdaptedEdgeTableName(tenantID uint16, relType string) string

AdaptedEdgeTableName returns the adapted native-column table name for a schema-registered edge label. Example: t0001_edata_KNOWS, t0001_edata_MEMBER_OF

func AdaptedNodeIndexField

func AdaptedNodeIndexField(tenantID uint16, entityType, field string) string

AdaptedNodeIndexField returns a field index name on an adapted node table. Example: idx_t0001_ndata_user_email

func AdaptedNodeIndexTenant

func AdaptedNodeIndexTenant(tenantID uint16, entityType string) string

AdaptedNodeIndexTenant returns the tenant index name on an adapted node table. Example: idx_t0001_ndata_user_tenant

func AdaptedNodeTableName

func AdaptedNodeTableName(tenantID uint16, entityType string) string

AdaptedNodeTableName returns the adapted native-column table name for a schema-registered node entity type. Example: t0001_ndata_user, t0001_ndata_user_profile

func CacheKey

func CacheKey(tenantID uint16, entity string, id int) string

CacheKey returns a cache key scoped to a tenant. For tenant 0 (unscoped): "entity:id" For non-zero tenants: "XXXX:entity:id"

func CacheListPattern

func CacheListPattern(tenantID uint16, entity string) string

CacheListPattern returns a pattern matching only list cache keys for an entity type, scoped to a tenant. This leaves individual GET cache entries intact, improving cache hit rate when a single entity is modified. For tenant 0 (unscoped): "entity:list:*" For non-zero tenants: "XXXX:entity:list:*"

func CachePattern

func CachePattern(tenantID uint16, entity string) string

CachePattern returns a pattern for cache invalidation scoped to a tenant. For tenant 0 (unscoped): "entity:*" For non-zero tenants: "XXXX:entity:*"

func CacheTenantPattern

func CacheTenantPattern(tenantID uint16) string

CacheTenantPattern returns a pattern matching all keys for a tenant. For tenant 0: "*" (everything) For non-zero: "XXXX:*"

func EdgeFTSTableName

func EdgeFTSTableName(tenantID uint16) string

EdgeFTSTableName returns the edge full-text search virtual table name for a tenant. Used when edge properties carry free-text content that needs full-text search — e.g. a contract document on a MARRIED_TO relationship, a clinical note on a TREATS relationship, or a lease agreement on LEASES. Example: t0001_efts

func EdgePropsTableName

func EdgePropsTableName(tenantID uint16) string

EdgePropsTableName returns the blob edge property store table name for a tenant. Stores JSON property blobs for edges whose label has no registered schema. Example: t0001_edges

func EdgeSchemaTableName

func EdgeSchemaTableName(tenantID uint16) string

EdgeSchemaTableName returns the edge schema registry table name for a tenant. Stores the raw JSON schema, derived column spec, and warning-suppression flag for each relationship label. Example: t0001_e_sch

func EdgeSeqIndexRelType

func EdgeSeqIndexRelType(tenantID uint16) string

EdgeSeqIndexRelType returns the index on t<X>_eseq. Example: idx_t0001_eseq_rel

func EdgeSeqTableName

func EdgeSeqTableName(tenantID uint16) string

EdgeSeqTableName returns the edge ID sequence table name for a tenant. Provides explicit control over surrogate edge ID assignment, consistent with NodeSeqTableName. One row per relationship label per tenant. Example: t0001_eseq

func GraphEdgesTableName

func GraphEdgesTableName(tenantID uint16) string

GraphEdgesTableName is the legacy name for GraphTableName. Deprecated: use GraphTableName. Retained for the migration command only.

func GraphIndexRel

func GraphIndexRel(tenantID uint16) string

GraphIndexRel returns the index name for relationship_name lookups on t<X>_graph. Example: idx_t0001_graph_rel

func GraphIndexSource

func GraphIndexSource(tenantID uint16) string

GraphIndexSource returns the index name for source-side lookups on t<X>_graph. Example: idx_t0001_graph_src

func GraphIndexTarget

func GraphIndexTarget(tenantID uint16) string

GraphIndexTarget returns the index name for target-side lookups on t<X>_graph. Example: idx_t0001_graph_tgt

func GraphNodePrefix

func GraphNodePrefix(tenantID uint16) string

GraphNodePrefix returns the XXXX@ prefix used to namespace graph node IDs in a shared in-memory graph that spans multiple tenants. For tenant 0 (unscoped): "" (no prefix; node IDs are bare "entity:id") For non-zero tenants: "XXXX@" (e.g. "0001@")

Uses uppercase hex. NodeIDPrefix is the corresponding parser; both must agree on case. If this format ever changes, NodeIDPrefix must be updated.

func GraphTableName

func GraphTableName(tenantID uint16) string

GraphTableName returns the topology table name for a tenant. Stores directed edges as (source_entity, source_id, target_entity, target_id, relationship_name, edge_id). Example: t0001_graph

func NodeFTSTableName

func NodeFTSTableName(tenantID uint16) string

NodeFTSTableName returns the node full-text search virtual table name for a tenant. Replaces the global shared-mode `entities_fts` virtual table. Example: t0001_nfts

func NodeID

func NodeID(tenantID uint16, entity string, id int) string

NodeID returns a graph node identifier scoped to a tenant. For tenant 0 (unscoped): "entity:id" For non-zero tenants: "XXXX@entity:id"

func NodeIDPrefix

func NodeIDPrefix(nodeID string) string

NodeIDPrefix extracts the XXXX@ tenant prefix from a graph node ID, returning "" if the node ID carries no prefix.

Only uppercase hex digits (0-9, A-F) are recognised, matching the output of GraphNodePrefix. Lowercase hex will cause this function to return "". This intentional strictness prevents ambiguous or malformed prefixes from being silently accepted.

func NodeIDStripped

func NodeIDStripped(nodeID string) string

NodeIDStripped returns nodeID with its XXXX@ tenant prefix removed, if any. For bare node IDs (no prefix) the input is returned unchanged. Intended for use in error messages that must not leak internal prefixes.

func NodeSchemaTableName

func NodeSchemaTableName(tenantID uint16) string

NodeSchemaTableName returns the node schema registry table name for a tenant. Stores both the raw JSON schema and the derived adapted-table column spec. Replaces the global `schemas` and `adapted_table_schemas` tables. Example: t0001_n_sch

func NodeSeqIndexEntityType

func NodeSeqIndexEntityType(tenantID uint16) string

NodeSeqIndexEntityType returns the index on t<X>_nseq (the PK already covers this, but an explicit name is needed for migration assertions). Example: idx_t0001_nseq_etype

func NodeSeqTableName

func NodeSeqTableName(tenantID uint16) string

NodeSeqTableName returns the node ID sequence table name for a tenant. Replaces the global shared-mode `entity_sequences` table. Example: t0001_nseq

func NodesIndexEntityType

func NodesIndexEntityType(tenantID uint16) string

NodesIndexEntityType returns the index name for entity_type lookups on t<X>_nodes. Example: idx_t0001_nodes_etype

func NodesIndexUpdatedAt

func NodesIndexUpdatedAt(tenantID uint16) string

NodesIndexUpdatedAt returns the index name for updated_at ordering on t<X>_nodes. Example: idx_t0001_nodes_updated

func NodesTableName

func NodesTableName(tenantID uint16) string

NodesTableName returns the blob node store table name for a tenant. Replaces the global shared-mode `entities` table. Example: t0001_nodes

func ScopeKey

func ScopeKey(tenantID uint16, key string) string

ScopeKey prepends the tenant's hex ID to an arbitrary cache or lookup key, producing a tenant-scoped key of the form "XXXX:key". For tenant 0 (unscoped): the key is returned unchanged. For non-zero tenants: "XXXX:key" (e.g. "0001:post:list:1:10")

This is the generic scoping primitive; use CacheKey, CachePattern, etc. for the specialised cache key formats.

func StorageDirSegment

func StorageDirSegment(tenantID uint16) string

StorageDirSegment returns the directory name used for tenant-scoped file storage (timeseries data, JSON file store). The segment is intended to be joined with a base directory using filepath.Join. For tenant 0 (unscoped): "" (data lives directly in the base directory) For non-zero tenants: "tXXXX" (e.g. "t0001")

Uses uppercase hex, consistent with GraphNodePrefix.

Types

type ElementKind

type ElementKind uint8

ElementKind is the fundamental kind of a graph element.

const (
	// ElementNode is a real node with a confirmed entity type and property store.
	// Properties live in t<X>_nodes (blob) or t<X>_ndata_<label> (adapted).
	ElementNode ElementKind = iota

	// ElementEdge is a directed relationship between two nodes.
	// Properties live in t<X>_edges (blob) or t<X>_edata_<label> (adapted).
	ElementEdge

	// ElementVode is a forward-reference placeholder node created implicitly
	// by AddEdge when the target entity has not yet been written. A Vode has
	// topology (it exists in t<X>_graph adjacency) but no property store entry.
	// Its label is always NodeTypeVode ("__vode__"). Vodes are promoted to real
	// nodes when the entity data arrives; a non-zero Vode count at the end of
	// hydration indicates dangling references.
	//
	// Hydration must short-circuit for Vodes: there is no property row to fetch.
	// Query results that include Vodes should be excluded or flagged rather than
	// returned with empty property maps.
	ElementVode
)

func (ElementKind) String

func (k ElementKind) String() string

String returns a human-readable name for the ElementKind.

type Persister

type Persister interface {
	// LoadAll returns all persisted tenant mappings.
	LoadAll(ctx context.Context) (map[string]uint16, error)
	// Save persists a single tenant mapping. It must be idempotent:
	// saving an already-persisted (name, id) pair is not an error.
	Save(ctx context.Context, name string, id uint16) error
}

Persister stores and retrieves tenant name-to-ID mappings durably. Implementations must be safe for concurrent use.

type Registry

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

Registry maps human-readable tenant names (e.g. "acme") to uint16 IDs. It is safe for concurrent use. When a Persister is attached, all mutations are durably stored, ensuring stable name-to-ID mappings across restarts.

func NewRegistry

func NewRegistry() *Registry

NewRegistry creates an empty tenant registry with no persistence. Mappings will be lost on restart. Use SetPersister or LoadFrom to attach durable storage.

func (*Registry) Count

func (r *Registry) Count() int

Count returns the number of registered tenants.

func (*Registry) GetOrRegister

func (r *Registry) GetOrRegister(ctx context.Context, name string) (uint16, error)

GetOrRegister returns the tenant ID for a name, auto-registering with the next available ID if the name is not yet known. This is intended for non-strict tenant modes where tenants are created on first access. If a persister is attached, new mappings are durably stored.

func (*Registry) List

func (r *Registry) List() map[string]uint16

List returns all registered tenant name-ID pairs.

func (*Registry) LoadFrom

func (r *Registry) LoadFrom(ctx context.Context) error

LoadFrom loads all tenant mappings from the attached persister into the in-memory registry. Existing in-memory mappings are preserved; conflicts (same name with different ID) return an error. This should be called once at startup, after SetPersister.

func (*Registry) Lookup

func (r *Registry) Lookup(name string) (uint16, bool)

Lookup returns the tenant ID for a name, or 0 and false if not found.

func (*Registry) Name

func (r *Registry) Name(id uint16) (string, bool)

Name returns the tenant name for an ID, or "" and false if not found.

func (*Registry) Register

func (r *Registry) Register(ctx context.Context, name string, id uint16) error

Register adds a tenant with an explicit ID. Returns an error if the name or ID is already registered. If a persister is attached, the mapping is durably stored.

func (*Registry) SetPersister

func (r *Registry) SetPersister(p Persister)

SetPersister attaches a persistence backend to the registry. Must be called before any Register/GetOrRegister calls.

Jump to

Keyboard shortcuts

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