Skip to content

Commit af47c64

Browse files
EDsCODEclaude
andcommitted
Simplify to always use in-memory database with DuckLake
- Always use :memory: since DuckLake provides actual storage (RDS/S3) - Remove file-based database path logic - Clean up debug logging - Simplify pool key to just username 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]>
1 parent 20d1b44 commit af47c64

File tree

1 file changed

+11
-34
lines changed

1 file changed

+11
-34
lines changed

server/server.go

Lines changed: 11 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -256,64 +256,46 @@ func (s *Server) ActiveConnections() int64 {
256256
}
257257

258258
// getDBConnection returns a DuckDB connection for a client session.
259-
// Connections are pooled per database file to avoid DuckDB file locking issues
260-
// from rapid open/close cycles. The connection is shared across all clients
261-
// using the same database file.
259+
// Connections are pooled per user. Uses in-memory database as an anchor
260+
// for DuckLake attachment (actual data lives in RDS/S3).
262261
func (s *Server) getDBConnection(username string) (*sql.DB, error) {
263-
// Use in-memory database when DuckLake is configured (data lives in RDS/S3),
264-
// otherwise use file-based database for local storage.
265-
var dbPath string
266-
if s.cfg.DuckLake.MetadataStore != "" {
267-
dbPath = ":memory:"
268-
} else {
269-
dbPath = fmt.Sprintf("%s/%s.db", s.cfg.DataDir, username)
270-
}
271-
272-
// Check if we already have a connection for this database
273-
poolKey := fmt.Sprintf("%s:%s", username, dbPath)
262+
// Check if we already have a connection for this user
274263
s.dbPoolMu.Lock()
275-
if db, ok := s.dbPool[poolKey]; ok {
264+
if db, ok := s.dbPool[username]; ok {
276265
s.dbPoolMu.Unlock()
277266
// Verify connection is still alive
278267
if err := db.Ping(); err == nil {
279-
log.Printf("[%s] Reusing pooled DuckDB connection", username)
280268
return db, nil
281269
}
282270
// Connection is dead, remove from pool and create new one
283271
log.Printf("[%s] Pooled connection dead, creating new one", username)
284272
s.dbPoolMu.Lock()
285-
delete(s.dbPool, poolKey)
273+
delete(s.dbPool, username)
286274
}
287275
s.dbPoolMu.Unlock()
288276

289-
// Create new connection
290-
log.Printf("[%s] Opening DuckDB at %s", username, dbPath)
291-
db, err := sql.Open("duckdb", dbPath)
277+
// Create new in-memory connection (DuckLake provides actual storage)
278+
db, err := sql.Open("duckdb", ":memory:")
292279
if err != nil {
293280
return nil, fmt.Errorf("failed to open duckdb: %w", err)
294281
}
295282

296283
// Configure connection pool - allow multiple concurrent queries since
297-
// this connection is shared across all clients for this database
284+
// this connection is shared across all clients for this user
298285
db.SetMaxOpenConns(10)
299286
db.SetMaxIdleConns(5)
300287
db.SetConnMaxLifetime(30 * time.Minute)
301288

302289
// Verify connection
303-
log.Printf("[%s] Pinging DuckDB...", username)
304290
if err := db.Ping(); err != nil {
305291
db.Close()
306292
return nil, fmt.Errorf("failed to ping duckdb: %w", err)
307293
}
308-
log.Printf("[%s] Ping successful", username)
309294

310295
// Load configured extensions
311-
log.Printf("[%s] Loading extensions...", username)
312296
if err := s.loadExtensions(db); err != nil {
313297
log.Printf("Warning: failed to load some extensions for user %q: %v", username, err)
314-
// Continue anyway - database will still work without the extensions
315298
}
316-
log.Printf("[%s] Extensions loaded", username)
317299

318300
// Attach DuckLake catalog if configured
319301
if err := s.attachDuckLake(db); err != nil {
@@ -335,10 +317,10 @@ func (s *Server) getDBConnection(username string) (*sql.DB, error) {
335317

336318
// Add to pool
337319
s.dbPoolMu.Lock()
338-
s.dbPool[poolKey] = db
320+
s.dbPool[username] = db
339321
s.dbPoolMu.Unlock()
340322

341-
log.Printf("[%s] Created new pooled DuckDB connection at %s", username, dbPath)
323+
log.Printf("[%s] DuckDB connection ready", username)
342324
return db, nil
343325
}
344326

@@ -381,14 +363,9 @@ func (s *Server) attachDuckLake(db *sql.DB) error {
381363
// "database with name '__ducklake_metadata_ducklake' already exists".
382364
// Use a 30-second timeout to prevent connections from hanging indefinitely
383365
// if attachment is slow (e.g., network latency to metadata store).
384-
log.Printf("Waiting for DuckLake attachment lock...")
385366
select {
386367
case s.duckLakeSem <- struct{}{}:
387-
log.Printf("Acquired DuckLake attachment lock")
388-
defer func() {
389-
<-s.duckLakeSem
390-
log.Printf("Released DuckLake attachment lock")
391-
}()
368+
defer func() { <-s.duckLakeSem }()
392369
case <-time.After(30 * time.Second):
393370
return fmt.Errorf("timeout waiting for DuckLake attachment lock")
394371
}

0 commit comments

Comments
 (0)