fix(pglite): do not cut slow readers, and bind playlist rules as text

The bridge gave every reply write a 5 second deadline. Scanner phase 3
streams all touched albums through a cursor and runs queries per row on
other pooled connections, which queue on the single session, so a large
library could not drain the reply in time and the bridge closed the pipe
mid-message ('unexpected EOF'). Replies now block as long as the client
needs, and client connections are closed on shutdown instead.

Playlist rules were bound as []byte, which pgx sends as bytea; the text
column then stored the hex form and the JSON parser failed on it.
This commit is contained in:
Deluan 2026-09-04 22:25:13 -04:00
commit e2c8a1930a
2 changed files with 5 additions and 3 deletions

View file

@ -428,6 +428,7 @@ func (pg *PGlite) handleConn(conn net.Conn, ioBase string) {
defer fmt.Fprintln(pg.cfg.Stderr, "# bridge: client disconnected")
}
defer conn.Close()
defer context.AfterFunc(pg.ctx, func() { _ = conn.Close() })()
outFile := ioBase + ".out"
buf := make([]byte, 65536)
@ -597,7 +598,8 @@ func (pg *PGlite) sendReplies(conn net.Conn, replies [][]byte) bool {
fmt.Fprintf(pg.cfg.Stderr, "# bridge S> raw %q\n", data)
}
}
_ = conn.SetWriteDeadline(time.Now().Add(5 * time.Second))
// No write deadline: a client may drain a large result slowly (e.g. a cursor that runs
// queries per row); the connection is closed on shutdown instead.
if _, err := conn.Write(data); err != nil {
return false
}

View file

@ -33,12 +33,12 @@ func (p *dbPlaylist) PostScan() error {
}
func (p dbPlaylist) PostMapArgs(args map[string]any) error {
var err error
if p.Playlist.IsSmartPlaylist() {
args["rules"], err = json.Marshal(p.Playlist.Rules)
rules, err := json.Marshal(p.Playlist.Rules)
if err != nil {
return fmt.Errorf("invalid criteria expression: %w", err)
}
args["rules"] = string(rules) // []byte would be bound as bytea and stored as its hex form
// Smart playlist counters are owned by refreshCounters (evaluation), never by callers
delete(args, "song_count")
delete(args, "duration")