Files
zeekayandHanzo Dev 64519916bf the corporate name is Lux Industries Inc
Lux Partners Limited is not the entity behind this work. Every place the
old name stood — copyright lines, site footers, brand config, legal and
compliance text — now names the company that actually holds it.

lux.fund is the exception and is not renamed to match: that site belongs
to Lux Assets Management LLC, a different company, and it says so.

Two kinds of line were left for a person rather than rewritten. A dated
news item recording that Lux Partners Limited was established in the Isle
of Man is a historical fact, and renaming it would falsify the record. And
a sentence asserting that the company is domiciled in the Isle of Man is a
claim about a jurisdiction, not a name — an Inc or an LLC is not an Isle
of Man company, so swapping the name there would assert something untrue.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-28 13:01:04 -07:00

235 lines
6.7 KiB
Go

// Copyright (c) 2025 Lux Industries Inc
// SPDX-License-Identifier: MIT
// Package storage provides a pluggable storage interface for the LUX indexer.
// Supported backends: PostgreSQL, MySQL, SQLite, MongoDB, ZapDB, Dgraph
package storage
import (
"context"
"encoding/json"
"fmt"
"time"
)
// Backend identifies the storage backend type
type Backend string
const (
BackendPostgres Backend = "postgres"
BackendMySQL Backend = "mysql"
BackendSQLite Backend = "sqlite"
BackendMongo Backend = "mongo"
BackendBadger Backend = "badger"
BackendDgraph Backend = "dgraph"
)
// Config for storage backend
type Config struct {
Backend Backend
URL string // Connection URL (postgres://, mysql://, mongo://, etc.)
Database string // Database name (for MongoDB)
Options map[string]string // Backend-specific options
DataDir string // For file-based backends (ZapDB, SQLite)
}
// Store is the main storage interface for indexed data
type Store interface {
// Backend returns the query backend type (sqlite, postgres, etc.)
Backend() Backend
// Lifecycle
Init(ctx context.Context) error
Close() error
Ping(ctx context.Context) error
// Schema management
InitSchema(ctx context.Context, schema Schema) error
MigrateSchema(ctx context.Context, schema Schema) error
// Block/Vertex storage (for chain/dag indexers)
StoreBlock(ctx context.Context, table string, block *Block) error
GetBlock(ctx context.Context, table string, id string) (*Block, error)
GetBlockByHeight(ctx context.Context, table string, height uint64) (*Block, error)
GetRecentBlocks(ctx context.Context, table string, limit int) ([]*Block, error)
StoreVertex(ctx context.Context, table string, vertex *Vertex) error
GetVertex(ctx context.Context, table string, id string) (*Vertex, error)
GetRecentVertices(ctx context.Context, table string, limit int) ([]*Vertex, error)
// Edge storage (for DAG)
StoreEdge(ctx context.Context, table string, edge *Edge) error
GetEdges(ctx context.Context, table string, vertexID string) ([]*Edge, error)
// Generic key-value storage
Put(ctx context.Context, table string, key string, value []byte) error
Get(ctx context.Context, table string, key string) ([]byte, error)
Delete(ctx context.Context, table string, key string) error
List(ctx context.Context, table string, prefix string, limit int) ([]KV, error)
// Stats
UpdateStats(ctx context.Context, table string, stats map[string]interface{}) error
GetStats(ctx context.Context, table string) (map[string]interface{}, error)
Count(ctx context.Context, table string, where string, args ...interface{}) (int64, error)
// Queries
Query(ctx context.Context, query string, args ...interface{}) ([]map[string]interface{}, error)
Exec(ctx context.Context, query string, args ...interface{}) error
// Transaction support (optional, may return ErrNotSupported)
Begin(ctx context.Context) (Transaction, error)
}
// Transaction represents a storage transaction
type Transaction interface {
Store
Commit() error
Rollback() error
}
// Block represents a linear chain block for storage
type Block struct {
ID string `json:"id"`
ParentID string `json:"parent_id"`
Height uint64 `json:"height"`
Timestamp time.Time `json:"timestamp"`
Status string `json:"status"`
TxCount int `json:"tx_count"`
TxIDs []string `json:"tx_ids"`
Data json.RawMessage `json:"data"`
Metadata json.RawMessage `json:"metadata"`
CreatedAt time.Time `json:"created_at"`
}
// Vertex represents a DAG vertex for storage
type Vertex struct {
ID string `json:"id"`
Type string `json:"type"`
ParentIDs []string `json:"parent_ids"`
Height uint64 `json:"height"`
Epoch uint32 `json:"epoch"`
TxIDs []string `json:"tx_ids"`
Timestamp time.Time `json:"timestamp"`
Status string `json:"status"`
Data json.RawMessage `json:"data"`
Metadata json.RawMessage `json:"metadata"`
CreatedAt time.Time `json:"created_at"`
}
// Edge represents a DAG edge for storage
type Edge struct {
Source string `json:"source"`
Target string `json:"target"`
Type string `json:"type"`
CreatedAt time.Time `json:"created_at"`
}
// KV represents a key-value pair
type KV struct {
Key string
Value []byte
}
// Schema defines the database schema
type Schema struct {
Name string
Tables []Table
Indexes []Index
}
// Table defines a database table
type Table struct {
Name string
Columns []Column
}
// Column defines a table column
type Column struct {
Name string
Type ColumnType
Nullable bool
Default string
Primary bool
}
// ColumnType represents a column data type
type ColumnType string
const (
TypeText ColumnType = "text"
TypeInt ColumnType = "int"
TypeBigInt ColumnType = "bigint"
TypeFloat ColumnType = "float"
TypeBool ColumnType = "bool"
TypeTimestamp ColumnType = "timestamp"
TypeJSON ColumnType = "json"
TypeBytes ColumnType = "bytes"
)
// Index defines a database index
type Index struct {
Name string
Table string
Columns []string
Unique bool
}
// Errors
var (
ErrNotFound = fmt.Errorf("not found")
ErrAlreadyExists = fmt.Errorf("already exists")
ErrNotSupported = fmt.Errorf("not supported by this backend")
ErrClosed = fmt.Errorf("store is closed")
)
// New creates a new unified storage backend based on config
// The unified storage uses a KV layer (ZapDB) + Query layer (SQLite/PostgreSQL)
func New(cfg Config) (Store, error) {
// Determine data directory
dataDir := cfg.DataDir
if dataDir == "" {
dataDir = "/tmp/indexer-data"
}
// Map legacy backend config to unified config
ucfg := DefaultUnifiedConfig(dataDir)
switch cfg.Backend {
case BackendPostgres:
ucfg.Query.Backend = "postgres"
ucfg.Query.URL = cfg.URL
case BackendMySQL:
// MySQL not yet supported in unified, fall back to SQLite
ucfg.Query.Backend = "sqlite"
case BackendSQLite:
ucfg.Query.Backend = "sqlite"
case BackendMongo, BackendBadger, BackendDgraph:
// These are KV-style backends, use SQLite as query layer
ucfg.Query.Backend = "sqlite"
default:
return nil, fmt.Errorf("unknown storage backend: %s", cfg.Backend)
}
return NewUnified(ucfg)
}
// ParseBackend parses a backend string
func ParseBackend(s string) (Backend, error) {
switch s {
case "postgres", "postgresql", "pg":
return BackendPostgres, nil
case "mysql", "mariadb":
return BackendMySQL, nil
case "sqlite", "sqlite3":
return BackendSQLite, nil
case "mongo", "mongodb":
return BackendMongo, nil
case "badger", "zapdb":
return BackendBadger, nil
case "dgraph":
return BackendDgraph, nil
default:
return "", fmt.Errorf("unknown backend: %s", s)
}
}