feat: add project-owned error catalogs and HTTP 200 failure contracts

This commit is contained in:
2026-09-24 12:40:05 +08:00
parent bb2caefbb4
commit ebfd279f9a
42 changed files with 1897 additions and 120 deletions

View File

@@ -31,6 +31,7 @@ type IdempotencyConfig struct {
type replay struct {
fingerprint [32]byte
errorCode string
status int
headers http.Header
body []byte
@@ -150,8 +151,12 @@ func (i *Idempotency) Middleware() httpx.Middleware {
return apierrors.New(409, "IDEMPOTENCY_UNAVAILABLE", "request is in progress or its outcome cannot be replayed")
}
status, headers, data := saved.status, saved.headers.Clone(), append([]byte(nil), saved.body...)
errorCode := saved.errorCode
i.mu.Unlock()
headers.Set("Idempotency-Replayed", "true")
if errorCode != "" {
c.RecordError(apierrors.New(status, errorCode, ""))
}
return c.WriteResponse(status, headers, data)
}
if len(i.items) >= i.config.MaxEntries {
@@ -171,6 +176,9 @@ func (i *Idempotency) Middleware() httpx.Middleware {
saved.failed = true
saved.expires = i.now().Add(i.config.TTL)
size := buffer.body.Len()
if failure := c.Failure(); failure != nil {
size += len(failure.Code)
}
for k, values := range buffer.headers {
size += len(k)
for _, v := range values {
@@ -180,6 +188,9 @@ func (i *Idempotency) Middleware() httpx.Middleware {
if buffer.complete && buffer.err == nil && buffer.status < 500 && buffer.headers.Get("Set-Cookie") == "" && !strings.Contains(strings.ToLower(buffer.headers.Get("Cache-Control")), "no-store") && size <= i.config.MaxBytes-i.bytes {
saved.failed = false
saved.status = buffer.status
if failure := c.Failure(); failure != nil {
saved.errorCode = failure.Code
}
saved.headers = buffer.headers.Clone()
saved.body = append([]byte(nil), buffer.body.Bytes()...)
saved.size = size
@@ -202,6 +213,9 @@ func (i *Idempotency) Middleware() httpx.Middleware {
if buffer.status == 0 {
buffer.status = 200
}
if failure := child.Failure(); failure != nil {
c.RecordError(failure)
}
buffer.complete = true
return c.WriteResponse(buffer.status, buffer.headers, buffer.body.Bytes())
}