GetOrCreate returns the database for the given host, creating it on first access. Runs migrations before creating the pool. Returns nil if the host is not found or suspended.
(ctx stdctx.Context, host string)
| 54 | // GetOrCreate returns the database for the given host, creating it on first access. |
| 55 | // Runs migrations before creating the pool. Returns nil if the host is not found or suspended. |
| 56 | func (c *PoolCache) GetOrCreate(ctx stdctx.Context, host string) (*database.DB, error) { |
| 57 | key := strings.ToLower(strings.TrimSpace(host)) |
| 58 | if key == "" { |
| 59 | return nil, nil |
| 60 | } |
| 61 | |
| 62 | entry := c.registry.GetByHost(host) |
| 63 | if entry == nil { |
| 64 | return nil, nil |
| 65 | } |
| 66 | if entry.DatabaseURL == "" { |
| 67 | return nil, nil |
| 68 | } |
| 69 | |
| 70 | // Fast path: check cache under read lock. |
| 71 | c.mu.RLock() |
| 72 | ent, ok := c.entries[key] |
| 73 | c.mu.RUnlock() |
| 74 | |
| 75 | if ok && ent != nil && (c.ttl <= 0 || time.Now().Before(ent.expiresAt)) { |
| 76 | return ent.db, nil |
| 77 | } |
| 78 | |
| 79 | // Slow path: per-host lock for migration/pool creation so that only requests |
| 80 | // for the same host block each other, not all hosts. |
| 81 | hmu := c.hostLock(key) |
| 82 | hmu.Lock() |
| 83 | defer hmu.Unlock() |
| 84 | |
| 85 | // Double-check after acquiring per-host lock. |
| 86 | c.mu.RLock() |
| 87 | ent, ok = c.entries[key] |
| 88 | c.mu.RUnlock() |
| 89 | if ok && ent != nil && (c.ttl <= 0 || time.Now().Before(ent.expiresAt)) { |
| 90 | return ent.db, nil |
| 91 | } |
| 92 | |
| 93 | // Evict stale entry if present (under write lock, but only briefly). |
| 94 | if ok && ent != nil { |
| 95 | c.mu.Lock() |
| 96 | if old, exists := c.entries[key]; exists && old != nil { |
| 97 | old.db.Close() |
| 98 | delete(c.entries, key) |
| 99 | } |
| 100 | c.mu.Unlock() |
| 101 | } |
| 102 | |
| 103 | maxConns := c.cfg.HostPoolMaxConns |
| 104 | if maxConns <= 0 { |
| 105 | maxConns = 5 |
| 106 | } |
| 107 | if entry.MaxConnections != nil && *entry.MaxConnections > 0 { |
| 108 | maxConns = *entry.MaxConnections |
| 109 | } |
| 110 | minConns := c.cfg.HostPoolMinConns |
| 111 | if minConns < 0 { |
| 112 | minConns = 1 |
| 113 | } |
no test coverage detected