feat(errkind): a database error is reduced to its SQLSTATE, never its message, which can quote a transcript value (fourth review)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-02 17:47:13 +02:00
co-authored by Claude Sonnet 5.5
parent cff5cd2f0a
commit 51ee5d48e5
+10 -1
View File
@@ -17,13 +17,20 @@ import (
// HTTPStatuser is implemented by errors that are a non-2xx answer from a service. // HTTPStatuser is implemented by errors that are a non-2xx answer from a service.
type HTTPStatuser interface{ HTTPStatus() int } type HTTPStatuser interface{ HTTPStatus() int }
// Of is the kind of err: "timeout", "canceled", "http_<code>", "network", or "error". // SQLStater is implemented by database errors that carry a SQLSTATE (pgx's PgError does).
// The five-character code is a fixed vocabulary; the error's message is not: Postgres quotes
// the offending value, which for a transcript row is transcript text.
type SQLStater interface{ SQLState() string }
// Of is the kind of err: "timeout", "canceled", "http_<code>", "sql_<state>", "network",
// or "error".
// It is empty for nil. // It is empty for nil.
func Of(err error) string { func Of(err error) string {
if err == nil { if err == nil {
return "" return ""
} }
var hs HTTPStatuser var hs HTTPStatuser
var ss SQLStater
var ne net.Error var ne net.Error
switch { switch {
case errors.Is(err, context.DeadlineExceeded): case errors.Is(err, context.DeadlineExceeded):
@@ -32,6 +39,8 @@ func Of(err error) string {
return "canceled" return "canceled"
case errors.As(err, &hs): case errors.As(err, &hs):
return fmt.Sprintf("http_%d", hs.HTTPStatus()) return fmt.Sprintf("http_%d", hs.HTTPStatus())
case errors.As(err, &ss) && ss.SQLState() != "":
return "sql_" + ss.SQLState()
case errors.As(err, &ne): case errors.As(err, &ne):
if ne.Timeout() { if ne.Timeout() {
return "timeout" return "timeout"