check / check (push) Canceled after 0s
Takes .golangci.yml, .dockerignore, .gitignore, .editorconfig, the workflow and REPO_POLICIES.md from sneak/prompts 0653579, with this repository's own entries after the shared content. Lint (golangci-lint v2.14.0) and test are Dockerfile phases that script/lint and script/test build alone with a new CACHEBUST value, keeping Go's and golangci-lint's caches; the image build depends on both. make fmt and make fmt-check also format the markdown with prettier, pinned in yarn.lock. The agent guidance moves to AGENTS.md. The Go code is fixed for what the new configuration finds, and the AS and prefix detail reads now return the rows' error after their loops. Model: opus-5-5
84 lines
2.2 KiB
Go
84 lines
2.2 KiB
Go
package database
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"time"
|
|
|
|
"git.eeqj.de/sneak/routewatch/internal/logger"
|
|
)
|
|
|
|
const slowQueryThreshold = 25 * time.Millisecond
|
|
|
|
// logSlowQuery logs queries that take longer than slowQueryThreshold
|
|
func logSlowQuery(logger *logger.Logger, query string, start time.Time) {
|
|
elapsed := time.Since(start)
|
|
if elapsed > slowQueryThreshold {
|
|
logger.Debug("Slow query", "query", query, "duration", elapsed)
|
|
}
|
|
}
|
|
|
|
// exec wraps Exec with slow query logging
|
|
func (d *Database) exec(query string, args ...any) error {
|
|
start := time.Now()
|
|
defer logSlowQuery(d.logger, query, start)
|
|
|
|
_, err := d.db.ExecContext(context.Background(), query, args...)
|
|
|
|
return err
|
|
}
|
|
|
|
// loggingTx wraps sql.Tx to log slow queries
|
|
type loggingTx struct {
|
|
*sql.Tx
|
|
|
|
logger *logger.Logger
|
|
}
|
|
|
|
// QueryRow wraps sql.Tx.QueryRow to log slow queries
|
|
func (tx *loggingTx) QueryRow(query string, args ...any) *sql.Row {
|
|
start := time.Now()
|
|
defer logSlowQuery(tx.logger, query, start)
|
|
|
|
return tx.Tx.QueryRowContext(context.Background(), query, args...)
|
|
}
|
|
|
|
// QueryRowContext wraps sql.Tx.QueryRowContext to log slow queries
|
|
func (tx *loggingTx) QueryRowContext(
|
|
ctx context.Context, query string, args ...any,
|
|
) *sql.Row {
|
|
start := time.Now()
|
|
defer logSlowQuery(tx.logger, query, start)
|
|
|
|
return tx.Tx.QueryRowContext(ctx, query, args...)
|
|
}
|
|
|
|
// QueryContext wraps sql.Tx.QueryContext to log slow queries
|
|
func (tx *loggingTx) QueryContext(
|
|
ctx context.Context, query string, args ...any,
|
|
) (*sql.Rows, error) {
|
|
start := time.Now()
|
|
defer logSlowQuery(tx.logger, query, start)
|
|
|
|
//nolint:sqlclosecheck // returns the rows, which the caller closes
|
|
return tx.Tx.QueryContext(ctx, query, args...)
|
|
}
|
|
|
|
// Exec wraps sql.Tx.Exec to log slow queries
|
|
func (tx *loggingTx) Exec(query string, args ...any) (sql.Result, error) {
|
|
start := time.Now()
|
|
defer logSlowQuery(tx.logger, query, start)
|
|
|
|
return tx.Tx.ExecContext(context.Background(), query, args...)
|
|
}
|
|
|
|
// ExecContext wraps sql.Tx.ExecContext to log slow queries
|
|
func (tx *loggingTx) ExecContext(
|
|
ctx context.Context, query string, args ...any,
|
|
) (sql.Result, error) {
|
|
start := time.Now()
|
|
defer logSlowQuery(tx.logger, query, start)
|
|
|
|
return tx.Tx.ExecContext(ctx, query, args...)
|
|
}
|