db_manager.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. package storage
  2. import (
  3. "fmt"
  4. "sync"
  5. )
  6. // DatabaseInstance represents a single database with its own schema and table managers.
  7. type DatabaseInstance struct {
  8. Name string
  9. Schema *SchemaManager
  10. Table *TableManager
  11. // Hub is the shared LISTEN/NOTIFY channel registry for this database. All
  12. // connections to the same database instance publish and subscribe through
  13. // the same hub; separate instances (tenants) are fully isolated.
  14. Hub *Hub
  15. }
  16. // DatabaseManager manages multiple database instances.
  17. type DatabaseManager struct {
  18. pool *KVPool
  19. defaultDatabase string
  20. databases map[string]*DatabaseInstance
  21. autoCreate bool
  22. mu sync.RWMutex
  23. }
  24. // DatabaseManagerConfig holds configuration for the database manager.
  25. type DatabaseManagerConfig struct {
  26. DefaultDatabase string
  27. AutoCreate bool // Auto-create databases on first access
  28. }
  29. // NewDatabaseManager creates a new database manager.
  30. func NewDatabaseManager(pool *KVPool, config *DatabaseManagerConfig) *DatabaseManager {
  31. if config == nil {
  32. config = &DatabaseManagerConfig{
  33. DefaultDatabase: "pizzasql",
  34. AutoCreate: true,
  35. }
  36. }
  37. dm := &DatabaseManager{
  38. pool: pool,
  39. defaultDatabase: config.DefaultDatabase,
  40. databases: make(map[string]*DatabaseInstance),
  41. autoCreate: config.AutoCreate,
  42. }
  43. // Pre-create the default database instance
  44. dm.getOrCreateDatabase(config.DefaultDatabase)
  45. return dm
  46. }
  47. // GetDatabase returns the database instance for the given name.
  48. // If name is empty, returns the default database.
  49. // If autoCreate is enabled and the database doesn't exist, it will be created.
  50. func (dm *DatabaseManager) GetDatabase(name string) (*DatabaseInstance, error) {
  51. if name == "" {
  52. name = dm.defaultDatabase
  53. }
  54. dm.mu.RLock()
  55. db, exists := dm.databases[name]
  56. dm.mu.RUnlock()
  57. if exists {
  58. return db, nil
  59. }
  60. if !dm.autoCreate {
  61. return nil, fmt.Errorf("database not found: %s", name)
  62. }
  63. return dm.getOrCreateDatabase(name), nil
  64. }
  65. // getOrCreateDatabase creates a new database instance if it doesn't exist.
  66. func (dm *DatabaseManager) getOrCreateDatabase(name string) *DatabaseInstance {
  67. dm.mu.Lock()
  68. defer dm.mu.Unlock()
  69. // Double-check after acquiring write lock
  70. if db, exists := dm.databases[name]; exists {
  71. return db
  72. }
  73. schema := NewSchemaManager(dm.pool, name)
  74. table := NewTableManager(dm.pool, schema, name)
  75. db := &DatabaseInstance{
  76. Name: name,
  77. Schema: schema,
  78. Table: table,
  79. Hub: NewHub(),
  80. }
  81. dm.databases[name] = db
  82. return db
  83. }
  84. // DefaultDatabase returns the default database name.
  85. func (dm *DatabaseManager) DefaultDatabase() string {
  86. return dm.defaultDatabase
  87. }
  88. // ListDatabases returns a list of all active database names.
  89. func (dm *DatabaseManager) ListDatabases() []string {
  90. dm.mu.RLock()
  91. defer dm.mu.RUnlock()
  92. names := make([]string, 0, len(dm.databases))
  93. for name := range dm.databases {
  94. names = append(names, name)
  95. }
  96. return names
  97. }
  98. // DatabaseExists checks if a database instance exists (is loaded).
  99. func (dm *DatabaseManager) DatabaseExists(name string) bool {
  100. dm.mu.RLock()
  101. defer dm.mu.RUnlock()
  102. _, exists := dm.databases[name]
  103. return exists
  104. }
  105. // GetPool returns the underlying KV pool.
  106. func (dm *DatabaseManager) GetPool() *KVPool {
  107. return dm.pool
  108. }
  109. // SetAutoCreate enables or disables auto-creation of databases.
  110. func (dm *DatabaseManager) SetAutoCreate(autoCreate bool) {
  111. dm.mu.Lock()
  112. defer dm.mu.Unlock()
  113. dm.autoCreate = autoCreate
  114. }