package with import ( "context" "database/sql" "fmt" "log" "net/url" "time" _ "modernc.org/sqlite" ) func SQL(ctx context.Context, conn string, foo func(*sql.DB) error) error { u, err := url.Parse(conn) if err != nil { return err } switch u.Scheme { case "sqlite": return Sqlite(ctx, conn, foo) case "postgres", "postgresql": return PSQL(ctx, conn, foo) } return fmt.Errorf("unknown sql scheme %q", u.Scheme) } func _sql(ctx context.Context, engine, conn string, foo func(db *sql.DB) error) error { log.Printf("opening %s %s...", engine, conn) db, err := sql.Open(engine, conn) if err != nil { return err } defer func() { log.Println("closed:", db.Close()) }() func() { pinged := make(chan bool) defer close(pinged) for { log.Println("pinging...") go func() { err := db.PingContext(ctx) if err != nil { log.Println("!", err) } select { case pinged <- err == nil: case <-ctx.Done(): case <-time.After(time.Second * 5): } }() select { case <-ctx.Done(): return case ok := <-pinged: if ok { return } } select { case <-ctx.Done(): case <-time.After(time.Second): } } }() log.Println("connected") return foo(db) }