factory_wasm.go raw

   1  //go:build js && wasm
   2  
   3  package database
   4  
   5  import (
   6  	"context"
   7  	"fmt"
   8  	"strings"
   9  	"time"
  10  )
  11  
  12  // DatabaseConfig holds all database configuration options that can be passed
  13  // to any database backend. Each backend uses the relevant fields for its type.
  14  // This centralizes configuration instead of having each backend read env vars directly.
  15  type DatabaseConfig struct {
  16  	// Common settings for all backends
  17  	DataDir  string
  18  	LogLevel string
  19  
  20  	// Badger-specific settings (not available in WASM)
  21  	BlockCacheMB     int           // ORLY_DB_BLOCK_CACHE_MB
  22  	IndexCacheMB     int           // ORLY_DB_INDEX_CACHE_MB
  23  	QueryCacheSizeMB int           // ORLY_QUERY_CACHE_SIZE_MB
  24  	QueryCacheMaxAge time.Duration // ORLY_QUERY_CACHE_MAX_AGE
  25  
  26  	// Serial cache settings for compact event storage (Badger-specific)
  27  	SerialCachePubkeys  int // ORLY_SERIAL_CACHE_PUBKEYS - max pubkeys to cache (default: 100000)
  28  	SerialCacheEventIds int // ORLY_SERIAL_CACHE_EVENT_IDS - max event IDs to cache (default: 500000)
  29  
  30  	// Neo4j-specific settings
  31  	Neo4jURI      string // ORLY_NEO4J_URI
  32  	Neo4jUser     string // ORLY_NEO4J_USER
  33  	Neo4jPassword string // ORLY_NEO4J_PASSWORD
  34  
  35  	// Neo4j driver tuning (memory and connection management)
  36  	Neo4jMaxConnPoolSize   int // ORLY_NEO4J_MAX_CONN_POOL - max connection pool size (default: 25)
  37  	Neo4jFetchSize         int // ORLY_NEO4J_FETCH_SIZE - max records per fetch batch (default: 1000)
  38  	Neo4jMaxTxRetrySeconds int // ORLY_NEO4J_MAX_TX_RETRY_SEC - max transaction retry time (default: 30)
  39  	Neo4jQueryResultLimit  int // ORLY_NEO4J_QUERY_RESULT_LIMIT - max results per query (default: 10000, 0=unlimited)
  40  }
  41  
  42  // NewDatabase creates a database instance based on the specified type.
  43  // Supported types in WASM: "wasmdb", "neo4j"
  44  // Note: "badger" is not available in WASM builds due to filesystem dependencies
  45  func NewDatabase(
  46  	ctx context.Context,
  47  	cancel context.CancelFunc,
  48  	dbType string,
  49  	dataDir string,
  50  	logLevel string,
  51  ) (Database, error) {
  52  	// Create a default config for backward compatibility with existing callers
  53  	cfg := &DatabaseConfig{
  54  		DataDir:  dataDir,
  55  		LogLevel: logLevel,
  56  	}
  57  	return NewDatabaseWithConfig(ctx, cancel, dbType, cfg)
  58  }
  59  
  60  // NewDatabaseWithConfig creates a database instance with full configuration.
  61  // This is the preferred method when you have access to the app config.
  62  func NewDatabaseWithConfig(
  63  	ctx context.Context,
  64  	cancel context.CancelFunc,
  65  	dbType string,
  66  	cfg *DatabaseConfig,
  67  ) (Database, error) {
  68  	switch strings.ToLower(dbType) {
  69  	case "wasmdb", "indexeddb", "wasm", "badger", "":
  70  		// In WASM builds, default to wasmdb (IndexedDB backend)
  71  		// "badger" is mapped to wasmdb since Badger is not available
  72  		if newWasmDBDatabase == nil {
  73  			return nil, fmt.Errorf("wasmdb database backend not available (import _ \"next.orly.dev/pkg/wasmdb\")")
  74  		}
  75  		return newWasmDBDatabase(ctx, cancel, cfg)
  76  	case "neo4j":
  77  		// Use the neo4j implementation (HTTP-based, works in WASM)
  78  		if newNeo4jDatabase == nil {
  79  			return nil, fmt.Errorf("neo4j database backend not available (import _ \"next.orly.dev/pkg/neo4j\")")
  80  		}
  81  		return newNeo4jDatabase(ctx, cancel, cfg)
  82  	default:
  83  		return nil, fmt.Errorf("unsupported database type: %s (supported in WASM: wasmdb, neo4j)", dbType)
  84  	}
  85  }
  86  
  87  // newNeo4jDatabase creates a neo4j database instance
  88  // This is defined here to avoid import cycles
  89  var newNeo4jDatabase func(context.Context, context.CancelFunc, *DatabaseConfig) (Database, error)
  90  
  91  // RegisterNeo4jFactory registers the neo4j database factory
  92  // This is called from the neo4j package's init() function
  93  func RegisterNeo4jFactory(factory func(context.Context, context.CancelFunc, *DatabaseConfig) (Database, error)) {
  94  	newNeo4jDatabase = factory
  95  }
  96  
  97  // newWasmDBDatabase creates a wasmdb database instance (IndexedDB backend for WebAssembly)
  98  // This is defined here to avoid import cycles
  99  var newWasmDBDatabase func(context.Context, context.CancelFunc, *DatabaseConfig) (Database, error)
 100  
 101  // RegisterWasmDBFactory registers the wasmdb database factory
 102  // This is called from the wasmdb package's init() function
 103  func RegisterWasmDBFactory(factory func(context.Context, context.CancelFunc, *DatabaseConfig) (Database, error)) {
 104  	newWasmDBDatabase = factory
 105  }
 106